paystack/
utils.rs

1use serde::de::Error;
2use serde::{Deserialize, Deserializer};
3use serde_json::Value;
4use std::fmt::Formatter;
5use std::str::FromStr;
6
7pub fn string_or_number_to_u8<'de, D>(deserializer: D) -> Result<u8, D::Error>
8where
9    D: serde::Deserializer<'de>,
10{
11    struct StringOrNumberVisitor;
12
13    impl<'de> serde::de::Visitor<'de> for StringOrNumberVisitor {
14        type Value = u8;
15
16        fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
17            formatter.write_str("a string or an integer")
18        }
19
20        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
21        where
22            E: Error,
23        {
24            u8::from_str(v).map_err(serde::de::Error::custom)
25        }
26
27        fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
28        where
29            E: Error,
30        {
31            if v <= u8::MAX as u64 {
32                Ok(v as u8)
33            } else {
34                Err(E::custom(format!("u64 value {} is out of range for u8", v)))
35            }
36        }
37    }
38
39    deserializer.deserialize_any(StringOrNumberVisitor)
40}
41
42pub fn string_or_number_to_u16<'de, D>(deserializer: D) -> Result<u16, D::Error>
43where
44    D: serde::Deserializer<'de>,
45{
46    struct StringOrNumberVisitor;
47
48    impl<'de> serde::de::Visitor<'de> for StringOrNumberVisitor {
49        type Value = u16;
50
51        fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
52            formatter.write_str("a string or an integer")
53        }
54
55        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
56        where
57            E: Error,
58        {
59            u16::from_str(v).map_err(serde::de::Error::custom)
60        }
61
62        fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
63        where
64            E: Error,
65        {
66            if v <= u16::MAX as u64 {
67                Ok(v as u16)
68            } else {
69                Err(E::custom(format!(
70                    "u64 value {} is out of range for u16",
71                    v
72                )))
73            }
74        }
75    }
76
77    deserializer.deserialize_any(StringOrNumberVisitor)
78}
79
80pub fn option_string_or_number_to_u8<'de, D>(deserializer: D) -> Result<Option<u8>, D::Error>
81where
82    D: serde::Deserializer<'de>,
83{
84    struct OptionStringOrNumberVisitor;
85
86    impl<'de> serde::de::Visitor<'de> for OptionStringOrNumberVisitor {
87        type Value = Option<u8>;
88
89        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
90            formatter.write_str("an optional u8, either as a number, a string, or null")
91        }
92
93        fn visit_none<E>(self) -> Result<Self::Value, E>
94        where
95            E: Error,
96        {
97            Ok(None)
98        }
99
100        fn visit_unit<E>(self) -> Result<Self::Value, E>
101        where
102            E: Error,
103        {
104            Ok(None)
105        }
106
107        fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
108        where
109            D: serde::Deserializer<'de>,
110        {
111            // Delegate to the exisiting deserializer
112            super::string_or_number_to_u8(deserializer).map(Some)
113        }
114    }
115
116    deserializer.deserialize_option(OptionStringOrNumberVisitor)
117}
118
119pub fn option_string_or_number_to_u16<'de, D>(deserializer: D) -> Result<Option<u16>, D::Error>
120where
121    D: serde::Deserializer<'de>,
122{
123    struct OptionStringOrNumberVisitor;
124
125    impl<'de> serde::de::Visitor<'de> for OptionStringOrNumberVisitor {
126        type Value = Option<u16>;
127
128        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
129            formatter.write_str("an optional u8, either as a number, a string, or null")
130        }
131
132        fn visit_none<E>(self) -> Result<Self::Value, E>
133        where
134            E: Error,
135        {
136            Ok(None)
137        }
138
139        fn visit_unit<E>(self) -> Result<Self::Value, E>
140        where
141            E: Error,
142        {
143            Ok(None)
144        }
145
146        fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
147        where
148            D: serde::Deserializer<'de>,
149        {
150            // Delegate to the exisiting deserializer
151            super::string_or_number_to_u16(deserializer).map(Some)
152        }
153    }
154
155    deserializer.deserialize_option(OptionStringOrNumberVisitor)
156}
157
158pub fn bool_from_int_or_bool<'de, D>(deserializer: D) -> Result<Option<bool>, D::Error>
159where
160    D: Deserializer<'de>,
161{
162    let v: Option<Value> = Option::deserialize(deserializer)?;
163    match v {
164        Some(Value::Bool(b)) => Ok(Some(b)),
165        Some(Value::Number(n)) => {
166            if let Some(i) = n.as_i64() {
167                Ok(Some(i != 0))
168            } else {
169                Err(serde::de::Error::custom("Invalid number for bool"))
170            }
171        }
172        Some(Value::Null) | None => Ok(None),
173        _ => Err(serde::de::Error::custom("Expected bool or int")),
174    }
175}