oauth2/
helpers.rs

1use serde::de::value::SeqAccessDeserializer;
2use serde::ser::{Impossible, SerializeStructVariant, SerializeTupleVariant};
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use serde_json::Value;
5
6use std::error::Error;
7use std::fmt::{Display, Formatter};
8use std::marker::PhantomData;
9
10/// Serde case-insensitive deserializer for an untagged `enum`.
11///
12/// This function converts values to lowercase before deserializing as the `enum`. Requires the
13/// `#[serde(rename_all = "lowercase")]` attribute to be set on the `enum`.
14///
15/// # Example
16///
17/// In example below, the following JSON values all deserialize to
18/// `GroceryBasket { fruit_item: Fruit::Banana }`:
19///
20///  * `{"fruit_item": "banana"}`
21///  * `{"fruit_item": "BANANA"}`
22///  * `{"fruit_item": "Banana"}`
23///
24/// Note: this example does not compile automatically due to
25/// [Rust issue #29286](https://github.com/rust-lang/rust/issues/29286).
26///
27/// ```
28/// # /*
29/// use serde::Deserialize;
30///
31/// #[derive(Deserialize)]
32/// #[serde(rename_all = "lowercase")]
33/// enum Fruit {
34///     Apple,
35///     Banana,
36///     Orange,
37/// }
38///
39/// #[derive(Deserialize)]
40/// struct GroceryBasket {
41///     #[serde(deserialize_with = "helpers::deserialize_untagged_enum_case_insensitive")]
42///     fruit_item: Fruit,
43/// }
44/// # */
45/// ```
46pub fn deserialize_untagged_enum_case_insensitive<'de, T, D>(deserializer: D) -> Result<T, D::Error>
47where
48    T: Deserialize<'de>,
49    D: Deserializer<'de>,
50{
51    T::deserialize(Value::String(
52        String::deserialize(deserializer)?.to_lowercase(),
53    ))
54    .map_err(serde::de::Error::custom)
55}
56
57/// Serde space-delimited string deserializer for a `Vec<String>`.
58///
59/// This function splits a JSON string at each space character into a `Vec<String>` .
60///
61/// # Example
62///
63/// In example below, the JSON value `{"items": "foo bar baz"}` would deserialize to:
64///
65/// ```
66/// # struct GroceryBasket {
67/// #     items: Vec<String>,
68/// # }
69/// GroceryBasket {
70///     items: vec!["foo".to_string(), "bar".to_string(), "baz".to_string()]
71/// };
72/// ```
73///
74/// Note: this example does not compile automatically due to
75/// [Rust issue #29286](https://github.com/rust-lang/rust/issues/29286).
76///
77/// ```
78/// # /*
79/// use serde::Deserialize;
80///
81/// #[derive(Deserialize)]
82/// struct GroceryBasket {
83///     #[serde(deserialize_with = "helpers::deserialize_space_delimited_vec")]
84///     items: Vec<String>,
85/// }
86/// # */
87/// ```
88pub fn deserialize_space_delimited_vec<'de, T, D>(deserializer: D) -> Result<T, D::Error>
89where
90    T: Default + Deserialize<'de>,
91    D: Deserializer<'de>,
92{
93    if let Some(space_delimited) = Option::<String>::deserialize(deserializer)? {
94        let entries = space_delimited
95            .split(' ')
96            .map(|s| Value::String(s.to_string()))
97            .collect();
98        T::deserialize(Value::Array(entries)).map_err(serde::de::Error::custom)
99    } else {
100        // If the JSON value is null, use the default value.
101        Ok(T::default())
102    }
103}
104
105/// Deserializes a string or array of strings into an array of strings
106pub fn deserialize_optional_string_or_vec_string<'de, D>(
107    deserializer: D,
108) -> Result<Option<Vec<String>>, D::Error>
109where
110    D: Deserializer<'de>,
111{
112    struct StringOrVec(PhantomData<Vec<String>>);
113
114    impl<'de> serde::de::Visitor<'de> for StringOrVec {
115        type Value = Option<Vec<String>>;
116
117        fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
118            formatter.write_str("string or list of strings")
119        }
120
121        fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
122        where
123            E: serde::de::Error,
124        {
125            Ok(Some(vec![value.to_owned()]))
126        }
127
128        fn visit_none<E>(self) -> Result<Self::Value, E>
129        where
130            E: serde::de::Error,
131        {
132            Ok(None)
133        }
134
135        fn visit_unit<E>(self) -> Result<Self::Value, E>
136        where
137            E: serde::de::Error,
138        {
139            Ok(None)
140        }
141
142        fn visit_seq<S>(self, visitor: S) -> Result<Self::Value, S::Error>
143        where
144            S: serde::de::SeqAccess<'de>,
145        {
146            Deserialize::deserialize(SeqAccessDeserializer::new(visitor)).map(Some)
147        }
148    }
149
150    deserializer.deserialize_any(StringOrVec(PhantomData))
151}
152
153/// Serde space-delimited string serializer for an `Option<Vec<String>>`.
154///
155/// This function serializes a string vector into a single space-delimited string.
156/// If `string_vec_opt` is `None`, the function serializes it as `None` (e.g., `null`
157/// in the case of JSON serialization).
158pub fn serialize_space_delimited_vec<T, S>(
159    vec_opt: &Option<Vec<T>>,
160    serializer: S,
161) -> Result<S::Ok, S::Error>
162where
163    T: AsRef<str>,
164    S: Serializer,
165{
166    if let Some(ref vec) = *vec_opt {
167        let space_delimited = vec.iter().map(|s| s.as_ref()).collect::<Vec<_>>().join(" ");
168
169        serializer.serialize_str(&space_delimited)
170    } else {
171        serializer.serialize_none()
172    }
173}
174
175/// Serde string serializer for an enum.
176///
177/// Source:
178/// [https://github.com/serde-rs/serde/issues/553](https://github.com/serde-rs/serde/issues/553)
179pub fn variant_name<T: Serialize>(t: &T) -> &'static str {
180    #[derive(Debug)]
181    struct NotEnum;
182    type Result<T> = std::result::Result<T, NotEnum>;
183    impl Error for NotEnum {
184        fn description(&self) -> &str {
185            "not struct"
186        }
187    }
188    impl Display for NotEnum {
189        fn fmt(&self, _f: &mut Formatter) -> std::fmt::Result {
190            unimplemented!()
191        }
192    }
193    impl serde::ser::Error for NotEnum {
194        fn custom<T: Display>(_msg: T) -> Self {
195            NotEnum
196        }
197    }
198
199    struct VariantName;
200    impl Serializer for VariantName {
201        type Ok = &'static str;
202        type Error = NotEnum;
203        type SerializeSeq = Impossible<Self::Ok, Self::Error>;
204        type SerializeTuple = Impossible<Self::Ok, Self::Error>;
205        type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
206        type SerializeTupleVariant = Enum;
207        type SerializeMap = Impossible<Self::Ok, Self::Error>;
208        type SerializeStruct = Impossible<Self::Ok, Self::Error>;
209        type SerializeStructVariant = Enum;
210        fn serialize_bool(self, _v: bool) -> Result<Self::Ok> {
211            Err(NotEnum)
212        }
213        fn serialize_i8(self, _v: i8) -> Result<Self::Ok> {
214            Err(NotEnum)
215        }
216        fn serialize_i16(self, _v: i16) -> Result<Self::Ok> {
217            Err(NotEnum)
218        }
219        fn serialize_i32(self, _v: i32) -> Result<Self::Ok> {
220            Err(NotEnum)
221        }
222        fn serialize_i64(self, _v: i64) -> Result<Self::Ok> {
223            Err(NotEnum)
224        }
225        fn serialize_u8(self, _v: u8) -> Result<Self::Ok> {
226            Err(NotEnum)
227        }
228        fn serialize_u16(self, _v: u16) -> Result<Self::Ok> {
229            Err(NotEnum)
230        }
231        fn serialize_u32(self, _v: u32) -> Result<Self::Ok> {
232            Err(NotEnum)
233        }
234        fn serialize_u64(self, _v: u64) -> Result<Self::Ok> {
235            Err(NotEnum)
236        }
237        fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
238            Err(NotEnum)
239        }
240        fn serialize_f64(self, _v: f64) -> Result<Self::Ok> {
241            Err(NotEnum)
242        }
243        fn serialize_char(self, _v: char) -> Result<Self::Ok> {
244            Err(NotEnum)
245        }
246        fn serialize_str(self, _v: &str) -> Result<Self::Ok> {
247            Err(NotEnum)
248        }
249        fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok> {
250            Err(NotEnum)
251        }
252        fn serialize_none(self) -> Result<Self::Ok> {
253            Err(NotEnum)
254        }
255        fn serialize_some<T: ?Sized + Serialize>(self, _value: &T) -> Result<Self::Ok> {
256            Err(NotEnum)
257        }
258        fn serialize_unit(self) -> Result<Self::Ok> {
259            Err(NotEnum)
260        }
261        fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
262            Err(NotEnum)
263        }
264        fn serialize_unit_variant(
265            self,
266            _name: &'static str,
267            _variant_index: u32,
268            variant: &'static str,
269        ) -> Result<Self::Ok> {
270            Ok(variant)
271        }
272        fn serialize_newtype_struct<T: ?Sized + Serialize>(
273            self,
274            _name: &'static str,
275            _value: &T,
276        ) -> Result<Self::Ok> {
277            Err(NotEnum)
278        }
279        fn serialize_newtype_variant<T: ?Sized + Serialize>(
280            self,
281            _name: &'static str,
282            _variant_index: u32,
283            variant: &'static str,
284            _value: &T,
285        ) -> Result<Self::Ok> {
286            Ok(variant)
287        }
288        fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
289            Err(NotEnum)
290        }
291        fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
292            Err(NotEnum)
293        }
294        fn serialize_tuple_struct(
295            self,
296            _name: &'static str,
297            _len: usize,
298        ) -> Result<Self::SerializeTupleStruct> {
299            Err(NotEnum)
300        }
301        fn serialize_tuple_variant(
302            self,
303            _name: &'static str,
304            _variant_index: u32,
305            variant: &'static str,
306            _len: usize,
307        ) -> Result<Self::SerializeTupleVariant> {
308            Ok(Enum(variant))
309        }
310        fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
311            Err(NotEnum)
312        }
313        fn serialize_struct(
314            self,
315            _name: &'static str,
316            _len: usize,
317        ) -> Result<Self::SerializeStruct> {
318            Err(NotEnum)
319        }
320        fn serialize_struct_variant(
321            self,
322            _name: &'static str,
323            _variant_index: u32,
324            variant: &'static str,
325            _len: usize,
326        ) -> Result<Self::SerializeStructVariant> {
327            Ok(Enum(variant))
328        }
329    }
330
331    struct Enum(&'static str);
332    impl SerializeStructVariant for Enum {
333        type Ok = &'static str;
334        type Error = NotEnum;
335        fn serialize_field<T: ?Sized + Serialize>(
336            &mut self,
337            _key: &'static str,
338            _value: &T,
339        ) -> Result<()> {
340            Ok(())
341        }
342        fn end(self) -> Result<Self::Ok> {
343            Ok(self.0)
344        }
345    }
346    impl SerializeTupleVariant for Enum {
347        type Ok = &'static str;
348        type Error = NotEnum;
349        fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<()> {
350            Ok(())
351        }
352        fn end(self) -> Result<Self::Ok> {
353            Ok(self.0)
354        }
355    }
356
357    t.serialize(VariantName).unwrap()
358}
359
360#[cfg(test)]
361mod tests {
362    use serde::Deserialize;
363
364    #[derive(Deserialize, Debug, Clone)]
365    pub struct ObjectWithOptionalStringOrVecString {
366        #[serde(deserialize_with = "crate::helpers::deserialize_optional_string_or_vec_string")]
367        pub strings: Option<Vec<String>>,
368    }
369
370    #[test]
371    fn test_deserialize_optional_string_or_vec_string_none() {
372        let list_of_strings: ObjectWithOptionalStringOrVecString =
373            serde_json::from_str(r#"{ "strings": null }"#).unwrap();
374        assert_eq!(None, list_of_strings.strings);
375    }
376
377    #[test]
378    fn test_deserialize_optional_string_or_vec_string_single_value() {
379        let list_of_strings: ObjectWithOptionalStringOrVecString =
380            serde_json::from_str(r#"{ "strings": "v1" }"#).unwrap();
381        assert_eq!(Some(vec!["v1".to_string()]), list_of_strings.strings);
382    }
383
384    #[test]
385    fn test_deserialize_optional_string_or_vec_string_vec() {
386        let list_of_strings: ObjectWithOptionalStringOrVecString =
387            serde_json::from_str(r#"{ "strings": ["v1", "v2"] }"#).unwrap();
388        assert_eq!(
389            Some(vec!["v1".to_string(), "v2".to_string()]),
390            list_of_strings.strings
391        );
392    }
393}