diff --git a/src/model.rs b/src/model.rs index ead944d7..9a0937e7 100644 --- a/src/model.rs +++ b/src/model.rs @@ -2,7 +2,10 @@ use std::fmt::Display; use merge::Merge; -use serde::{Deserialize, Serialize}; +use serde::{ + de::{Error as DeError, Visitor}, + Deserialize, Deserializer, Serialize, Serializer, +}; use serde_json::Value as JsonValue; use strum_macros::Display; @@ -29,6 +32,8 @@ pub enum Era { pub enum MetadatumRendition { MapJson(JsonValue), ArrayJson(JsonValue), + #[serde(serialize_with = "serialize_int_scalar")] + #[serde(deserialize_with = "deserialize_int_scalar")] IntScalar(i128), TextScalar(String), BytesHex(String), @@ -374,3 +379,53 @@ pub struct Event { pub fingerprint: Option, } + +fn serialize_int_scalar(value: &i128, serializer: S) -> Result +where + S: Serializer, +{ + if *value > (i64::MAX as i128) || *value < (i64::MIN as i128) { + return value.to_string().serialize(serializer); + } + + value.serialize(serializer) +} + +fn deserialize_int_scalar<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + deserializer.deserialize_any(IntScalarVisitor) +} + +#[derive(Debug)] +struct IntScalarVisitor; +impl<'de> Visitor<'de> for IntScalarVisitor { + type Value = i128; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + dbg!(self); + formatter.write_str("expect to receive integer") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(v.parse().map_err(DeError::custom)?) + } + + fn visit_u64(self, v: u64) -> Result + where + E: serde::de::Error, + { + Ok(v as i128) + } + + fn visit_i64(self, v: i64) -> Result + where + E: serde::de::Error, + { + Ok(v as i128) + } +}