levana_perpswap_cosmos/number/
serialize.rs

1use super::{NonZero, Signed, UnsignedDecimal};
2use schemars::schema::{InstanceType, SchemaObject};
3use schemars::JsonSchema;
4use serde::{de, ser, Deserialize, Deserializer, Serialize};
5use std::fmt;
6use std::marker::PhantomData;
7
8/// Serializes as a string for serde
9impl<T: UnsignedDecimal> Serialize for Signed<T> {
10    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
11    where
12        S: ser::Serializer,
13    {
14        serializer.serialize_str(&self.to_string())
15    }
16}
17
18/// Deserializes as string for serde
19impl<'de, T: UnsignedDecimal> Deserialize<'de> for Signed<T> {
20    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
21    where
22        D: Deserializer<'de>,
23    {
24        deserializer.deserialize_str(SignedVisitor(PhantomData))
25    }
26}
27
28struct SignedVisitor<T>(PhantomData<T>);
29
30impl<'de, T: UnsignedDecimal> de::Visitor<'de> for SignedVisitor<T> {
31    type Value = Signed<T>;
32
33    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
34        formatter.write_str("string-encoded signed decimal")
35    }
36
37    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
38    where
39        E: de::Error,
40    {
41        match v.parse() {
42            Ok(d) => Ok(d),
43            Err(e) => Err(E::custom(format!(
44                "Error parsing signed decimal '{}': {}",
45                v, e
46            ))),
47        }
48    }
49}
50
51impl<T: UnsignedDecimal> Serialize for NonZero<T> {
52    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
53    where
54        S: ser::Serializer,
55    {
56        serializer.serialize_str(&self.to_string())
57    }
58}
59
60impl<'de, T: UnsignedDecimal> Deserialize<'de> for NonZero<T> {
61    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
62    where
63        D: Deserializer<'de>,
64    {
65        deserializer.deserialize_str(NonZeroVisitor(PhantomData))
66    }
67}
68
69struct NonZeroVisitor<T>(PhantomData<T>);
70
71impl<'de, T: UnsignedDecimal> de::Visitor<'de> for NonZeroVisitor<T> {
72    type Value = NonZero<T>;
73
74    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
75        formatter.write_str("string-encoded decimal greater than zero")
76    }
77
78    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
79    where
80        E: de::Error,
81    {
82        match v.parse() {
83            Ok(d) => Ok(d),
84            Err(e) => Err(E::custom(format!(
85                "Error parsing non-zero decimal '{}': {}",
86                v, e
87            ))),
88        }
89    }
90}
91
92impl<T: UnsignedDecimal> JsonSchema for NonZero<T> {
93    fn schema_name() -> String {
94        "NonZero decimal".to_owned()
95    }
96
97    fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
98        SchemaObject {
99            instance_type: Some(InstanceType::String.into()),
100            format: Some("non-zero".to_owned()),
101            ..Default::default()
102        }
103        .into()
104    }
105}