Skip to main content

enum_map/
serde.rs

1// SPDX-FileCopyrightText: 2017 - 2023 Luna Borowska <luna@borowska.pw>
2// SPDX-FileCopyrightText: 2021 Bruno CorrĂȘa Zimmermann <brunoczim@gmail.com>
3//
4// SPDX-License-Identifier: MIT OR Apache-2.0
5
6use crate::internal::Array;
7use crate::{Enum, EnumMap, enum_map};
8use core::fmt;
9use core::marker::PhantomData;
10use serde::de::{self, Deserialize, Deserializer, Error, MapAccess, SeqAccess};
11use serde::ser::{Serialize, SerializeTuple, Serializer};
12
13/// Requires crate feature `"serde"`
14impl<K: Enum + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
15    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
16        if serializer.is_human_readable() {
17            serializer.collect_map(self)
18        } else {
19            let mut tup = serializer.serialize_tuple(self.len())?;
20            for value in self.values() {
21                tup.serialize_element(value)?;
22            }
23            tup.end()
24        }
25    }
26}
27
28/// Requires crate feature `"serde"`
29impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
30where
31    K: Enum + Deserialize<'de>,
32    V: Deserialize<'de>,
33{
34    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
35        if deserializer.is_human_readable() {
36            deserializer.deserialize_map(HumanReadableVisitor(PhantomData))
37        } else {
38            deserializer.deserialize_tuple(K::Array::<V>::LENGTH, CompactVisitor(PhantomData))
39        }
40    }
41}
42
43struct HumanReadableVisitor<K, V>(PhantomData<(K, V)>);
44
45impl<'de, K, V> de::Visitor<'de> for HumanReadableVisitor<K, V>
46where
47    K: Enum + Deserialize<'de>,
48    V: Deserialize<'de>,
49{
50    type Value = EnumMap<K, V>;
51
52    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
53        write!(formatter, "a map")
54    }
55
56    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
57        let mut entries = EnumMap::default();
58        while let Some((key, value)) = access.next_entry()? {
59            entries[key] = Some(value);
60        }
61        for value in entries.values() {
62            value
63                .as_ref()
64                .ok_or_else(|| M::Error::custom("key not specified"))?;
65        }
66        Ok(enum_map! { key => entries[key].take().unwrap() })
67    }
68}
69
70struct CompactVisitor<K, V>(PhantomData<(K, V)>);
71
72impl<'de, K, V> de::Visitor<'de> for CompactVisitor<K, V>
73where
74    K: Enum + Deserialize<'de>,
75    V: Deserialize<'de>,
76{
77    type Value = EnumMap<K, V>;
78
79    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
80        write!(formatter, "a sequence")
81    }
82
83    fn visit_seq<M: SeqAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
84        let mut entries = EnumMap::default();
85        let len = entries.len();
86        {
87            let mut iter = entries.values_mut();
88            while let Some(place) = iter.next() {
89                *place = Some(access.next_element()?.ok_or_else(|| {
90                    M::Error::invalid_length(
91                        len - iter.len() - 1,
92                        &"a sequence with as many elements as there are variants",
93                    )
94                })?);
95            }
96        }
97        Ok(enum_map! { key => entries[key].take().unwrap() })
98    }
99}