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 {v} is out of range for u8")))
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!("u64 value {v} is out of range for u16")))
70            }
71        }
72    }
73
74    deserializer.deserialize_any(StringOrNumberVisitor)
75}
76
77pub fn string_or_number_to_u32<'de, D>(deserializer: D) -> Result<u32, D::Error>
78where
79    D: serde::Deserializer<'de>,
80{
81    struct StringOrNumberVisitor;
82
83    impl<'de> serde::de::Visitor<'de> for StringOrNumberVisitor {
84        type Value = u32;
85
86        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
87            formatter.write_str("a string or an integer")
88        }
89
90        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
91        where
92            E: Error,
93        {
94            u32::from_str(v).map_err(serde::de::Error::custom)
95        }
96
97        fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
98        where
99            E: Error,
100        {
101            if v <= u32::MAX as u64 {
102                Ok(v as u32)
103            } else {
104                Err(E::custom(format!("u64 value {v} is out of range for u32")))
105            }
106        }
107    }
108
109    deserializer.deserialize_any(StringOrNumberVisitor)
110}
111
112pub fn option_string_or_number_to_u8<'de, D>(deserializer: D) -> Result<Option<u8>, D::Error>
113where
114    D: serde::Deserializer<'de>,
115{
116    struct OptionStringOrNumberVisitor;
117
118    impl<'de> serde::de::Visitor<'de> for OptionStringOrNumberVisitor {
119        type Value = Option<u8>;
120
121        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
122            formatter.write_str("an optional u8, either as a number, a string, or null")
123        }
124
125        fn visit_none<E>(self) -> Result<Self::Value, E>
126        where
127            E: Error,
128        {
129            Ok(None)
130        }
131
132        fn visit_unit<E>(self) -> Result<Self::Value, E>
133        where
134            E: Error,
135        {
136            Ok(None)
137        }
138
139        fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
140        where
141            D: serde::Deserializer<'de>,
142        {
143            // Delegate to the exisiting deserializer
144            super::string_or_number_to_u8(deserializer).map(Some)
145        }
146    }
147
148    deserializer.deserialize_option(OptionStringOrNumberVisitor)
149}
150
151pub fn option_string_or_number_to_u16<'de, D>(deserializer: D) -> Result<Option<u16>, D::Error>
152where
153    D: serde::Deserializer<'de>,
154{
155    struct OptionStringOrNumberVisitor;
156
157    impl<'de> serde::de::Visitor<'de> for OptionStringOrNumberVisitor {
158        type Value = Option<u16>;
159
160        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
161            formatter.write_str("an optional u8, either as a number, a string, or null")
162        }
163
164        fn visit_none<E>(self) -> Result<Self::Value, E>
165        where
166            E: Error,
167        {
168            Ok(None)
169        }
170
171        fn visit_unit<E>(self) -> Result<Self::Value, E>
172        where
173            E: Error,
174        {
175            Ok(None)
176        }
177
178        fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
179        where
180            D: serde::Deserializer<'de>,
181        {
182            // Delegate to the exisiting deserializer
183            super::string_or_number_to_u16(deserializer).map(Some)
184        }
185    }
186
187    deserializer.deserialize_option(OptionStringOrNumberVisitor)
188}
189
190pub fn bool_from_int_or_bool<'de, D>(deserializer: D) -> Result<Option<bool>, D::Error>
191where
192    D: Deserializer<'de>,
193{
194    let v: Option<Value> = Option::deserialize(deserializer)?;
195    match v {
196        Some(Value::Bool(b)) => Ok(Some(b)),
197        Some(Value::Number(n)) => {
198            if let Some(i) = n.as_i64() {
199                Ok(Some(i != 0))
200            } else {
201                Err(serde::de::Error::custom("Invalid number for bool"))
202            }
203        }
204        Some(Value::Null) | None => Ok(None),
205        _ => Err(serde::de::Error::custom("Expected bool or int")),
206    }
207}