enum_dict/
dict_key.rs

1use std::marker::PhantomData;
2
3/// Trait for types that can be used as dictionary keys
4pub trait DictKey {
5    const VARIANTS: &'static [&'static str];
6
7    /// Convert to usize index
8    fn variant_index(self) -> usize;
9}
10
11pub(crate) struct DictVisitor<K, V>(PhantomData<(K, V)>);
12
13impl<K, V> DictVisitor<K, V> {
14    pub fn new() -> Self {
15        Self(PhantomData)
16    }
17}
18
19#[cfg(feature = "serde")]
20mod serde_impl {
21    use std::fmt;
22
23    use serde::Deserialize;
24    use serde::de::{MapAccess, Visitor};
25
26    use super::*;
27
28    impl<'de, K: DictKey, V: Deserialize<'de>> Visitor<'de> for DictVisitor<K, V> {
29        type Value = Vec<Option<V>>;
30
31        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
32            formatter.write_str("a map with optional keys")
33        }
34
35        fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
36            let mut vec = K::VARIANTS.iter().map(|_| None).collect::<Vec<_>>();
37            while let Some((key, value)) = map.next_entry::<String, V>()? {
38                // ignore unknown keys
39                for (index, &name) in K::VARIANTS.iter().enumerate() {
40                    if name == key {
41                        vec[index] = Some(value);
42                        break;
43                    }
44                }
45            }
46            Ok(vec)
47        }
48    }
49}