1use std::marker::PhantomData;
2
3pub trait DictKey {
5 const VARIANTS: &'static [&'static str];
6
7 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 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}