templar_primitives/strnum/
serializable_u256.rs

1#[cfg(any(feature = "serde", feature = "schemars"))]
2use alloc::string::String;
3#[cfg(any(feature = "borsh", feature = "serde", feature = "schemars"))]
4use alloc::string::ToString;
5use primitive_types::U256;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
8#[cfg_attr(
9    feature = "borsh",
10    derive(borsh::BorshSerialize, borsh::BorshDeserialize, borsh::BorshSchema)
11)]
12pub struct SerializableU256([u64; 4]);
13
14impl SerializableU256 {
15    pub fn to_u256(self) -> U256 {
16        self.into()
17    }
18}
19
20impl From<U256> for SerializableU256 {
21    fn from(value: U256) -> Self {
22        Self(value.0)
23    }
24}
25
26impl From<SerializableU256> for U256 {
27    fn from(value: SerializableU256) -> Self {
28        U256(value.0)
29    }
30}
31
32#[cfg(feature = "schemars")]
33impl schemars::JsonSchema for SerializableU256 {
34    fn schema_name() -> String {
35        "SerializableU256".to_string()
36    }
37
38    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
39        let mut schema = gen.subschema_for::<String>().into_object();
40        schema.metadata().description = Some("unsigned 256-bit integer".to_string());
41        schema.into()
42    }
43}
44
45#[cfg(feature = "serde")]
46impl serde::Serialize for SerializableU256 {
47    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48    where
49        S: serde::Serializer,
50    {
51        serde::Serialize::serialize(&U256(self.0).to_string(), serializer)
52    }
53}
54
55#[cfg(feature = "serde")]
56impl<'de> serde::Deserialize<'de> for SerializableU256 {
57    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58    where
59        D: serde::Deserializer<'de>,
60    {
61        let s = <String as serde::Deserialize>::deserialize(deserializer)?;
62        U256::from_dec_str(&s)
63            .map(Self::from)
64            .map_err(serde::de::Error::custom)
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use primitive_types::U256;
71
72    use super::SerializableU256;
73
74    #[cfg(feature = "serde")]
75    #[test]
76    fn serde_round_trip_decimal_string() {
77        let value =
78            SerializableU256::from(U256::from_dec_str("123456789012345678901234567890").unwrap());
79
80        let serialized = serde_json::to_string(&value).unwrap();
81        assert_eq!(serialized, "\"123456789012345678901234567890\"");
82
83        let deserialized: SerializableU256 = serde_json::from_str(&serialized).unwrap();
84        assert_eq!(deserialized, value);
85    }
86
87    #[cfg(feature = "schemars")]
88    #[test]
89    fn schemars_schema_is_string() {
90        let schema = schemars::schema_for!(SerializableU256).schema;
91
92        assert_eq!(
93            schema.instance_type,
94            Some(schemars::schema::InstanceType::String.into())
95        );
96    }
97}