// SPDX-FileCopyrightText: 2017 - 2023 Kamila Borowska // SPDX-FileCopyrightText: 2021 Bruno CorrĂȘa Zimmermann // // SPDX-License-Identifier: MIT OR Apache-2.0 use crate::{enum_map, EnumArray, EnumMap}; use core::fmt; use core::marker::PhantomData; use serde::de::{self, Deserialize, Deserializer, Error, MapAccess, SeqAccess}; use serde::ser::{Serialize, SerializeTuple, Serializer}; /// Requires crate feature `"serde"` impl + Serialize, V: Serialize> Serialize for EnumMap { fn serialize(&self, serializer: S) -> Result { if serializer.is_human_readable() { serializer.collect_map(self) } else { let mut tup = serializer.serialize_tuple(self.len())?; for value in self.values() { tup.serialize_element(value)?; } tup.end() } } } /// Requires crate feature `"serde"` impl<'de, K, V> Deserialize<'de> for EnumMap where K: EnumArray + EnumArray> + Deserialize<'de>, V: Deserialize<'de>, { fn deserialize>(deserializer: D) -> Result { if deserializer.is_human_readable() { deserializer.deserialize_map(HumanReadableVisitor(PhantomData)) } else { deserializer.deserialize_tuple(K::LENGTH, CompactVisitor(PhantomData)) } } } struct HumanReadableVisitor(PhantomData<(K, V)>); impl<'de, K, V> de::Visitor<'de> for HumanReadableVisitor where K: EnumArray + EnumArray> + Deserialize<'de>, V: Deserialize<'de>, { type Value = EnumMap; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a map") } fn visit_map>(self, mut access: M) -> Result { let mut entries = EnumMap::default(); while let Some((key, value)) = access.next_entry()? { entries[key] = Some(value); } for value in entries.values() { value .as_ref() .ok_or_else(|| M::Error::custom("key not specified"))?; } Ok(enum_map! { key => entries[key].take().unwrap() }) } } struct CompactVisitor(PhantomData<(K, V)>); impl<'de, K, V> de::Visitor<'de> for CompactVisitor where K: EnumArray + EnumArray> + Deserialize<'de>, V: Deserialize<'de>, { type Value = EnumMap; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a sequence") } fn visit_seq>(self, mut access: M) -> Result { let mut entries = EnumMap::default(); let len = entries.len(); { let mut iter = entries.values_mut(); while let Some(place) = iter.next() { *place = Some(access.next_element()?.ok_or_else(|| { M::Error::invalid_length( len - iter.len() - 1, &"a sequence with as many elements as there are variants", ) })?); } } Ok(enum_map! { key => entries[key].take().unwrap() }) } }