stm32builder/helpers/
serde.rs

1//! Serde helpers
2
3use crate::api::Error;
4use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
5use std::fmt;
6use std::marker::PhantomData;
7use std::str::FromStr;
8
9pub fn default_true() -> bool {
10    true
11}
12
13pub fn string_or_struct<'de, T, D>(deserializer: D) -> Result<T, D::Error>
14where
15    T: Deserialize<'de> + FromStr<Err = Error>,
16    D: Deserializer<'de>,
17{
18    // This is a Visitor that forwards string types to T's `FromStr` impl and
19    // forwards map types to T's `Deserialize` impl. The `PhantomData` is to
20    // keep the compiler from complaining about T being an unused generic type
21    // parameter. We need T in order to know the Value type for the Visitor
22    // impl.
23    struct StringOrStruct<T>(PhantomData<fn() -> T>);
24
25    impl<'de, T> Visitor<'de> for StringOrStruct<T>
26    where
27        T: Deserialize<'de> + FromStr<Err = Error>,
28    {
29        type Value = T;
30
31        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
32            formatter.write_str("string or map")
33        }
34
35        fn visit_str<E>(self, value: &str) -> Result<T, E>
36        where
37            E: de::Error,
38        {
39            Ok(FromStr::from_str(value).unwrap())
40        }
41
42        fn visit_map<M>(self, visitor: M) -> Result<T, M::Error>
43        where
44            M: MapAccess<'de>,
45        {
46            // `MapAccessDeserializer` is a wrapper that turns a `MapAccess`
47            // into a `Deserializer`, allowing it to be used as the input to T's
48            // `Deserialize` implementation. T then deserializes itself using
49            // the entries from the map visitor.
50            Deserialize::deserialize(de::value::MapAccessDeserializer::new(visitor))
51        }
52    }
53
54    deserializer.deserialize_any(StringOrStruct(PhantomData))
55}