use crate::{ content::ser::{Content, ContentSerializer}, DeserializeAs, SerializeAs, }; use alloc::{string::ToString, vec::Vec}; use core::{fmt, marker::PhantomData}; use serde::{ de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor}, ser, ser::{Impossible, SerializeMap, SerializeSeq, SerializeStructVariant, SerializeTupleVariant}, Deserialize, Deserializer, Serialize, Serializer, }; /// Represent a list of enum values as a map. /// /// This **only works** if the enum uses the default *externally tagged* representation. /// Other enum representations are not supported. /// /// serde data formats often represent *externally tagged* enums as maps with a single key. /// The key is the enum variant name, and the value is the variant value. /// Sometimes a map with multiple keys should be treated like a list of enum values. /// /// # Examples /// /// ## JSON Map with multiple keys /// /// ```rust /// # #[cfg(feature = "macros")] { /// # use serde::{Deserialize, Serialize}; /// use serde_with::EnumMap; /// /// # #[derive(Debug, Clone, PartialEq, Eq)] /// #[derive(Serialize, Deserialize)] /// enum EnumValue { /// Int(i32), /// String(String), /// Unit, /// Tuple(i32, String, bool), /// Struct { /// a: i32, /// b: String, /// c: bool, /// }, /// } /// /// #[serde_with::serde_as] /// # #[derive(Debug, Clone, PartialEq, Eq)] /// #[derive(Serialize, Deserialize)] /// struct VecEnumValues ( /// #[serde_as(as = "EnumMap")] /// Vec, /// ); /// /// // --- /// /// // This will serialize this list of values /// let values = VecEnumValues(vec![ /// EnumValue::Int(123), /// EnumValue::String("FooBar".to_string()), /// EnumValue::Int(456), /// EnumValue::String("XXX".to_string()), /// EnumValue::Unit, /// EnumValue::Tuple(1, "Middle".to_string(), false), /// EnumValue::Struct { /// a: 666, /// b: "BBB".to_string(), /// c: true, /// }, /// ]); /// /// // into this JSON map /// // Duplicate keys are emitted for identical enum variants. /// let expected = /// r#"{ /// "Int": 123, /// "String": "FooBar", /// "Int": 456, /// "String": "XXX", /// "Unit": null, /// "Tuple": [ /// 1, /// "Middle", /// false /// ], /// "Struct": { /// "a": 666, /// "b": "BBB", /// "c": true /// } /// }"#; /// /// // Both serialization and deserialization work flawlessly. /// let serialized = serde_json::to_string_pretty(&values).unwrap(); /// assert_eq!(expected, serialized); /// let deserialized: VecEnumValues = serde_json::from_str(&serialized).unwrap(); /// assert_eq!(values, deserialized); /// # } /// ``` /// /// ## XML structure with varying keys /// /// With `serde_xml_rs` tuple and struct variants are not supported since they fail to roundtrip. /// The enum may have such variants as long as they are not serialized or deserialized. /// /// ``` /// # #[cfg(feature = "macros")] { /// # use serde::{Deserialize, Serialize}; /// use serde_with::EnumMap; /// /// # #[derive(Debug, Clone, PartialEq, Eq)] /// #[derive(Serialize, Deserialize)] /// enum EnumValue { /// Int(i32), /// String(String), /// Unit, /// } /// /// #[serde_with::serde_as] /// # #[derive(Debug, Clone, PartialEq, Eq)] /// #[derive(Serialize, Deserialize)] /// struct VecEnumValues { /// #[serde_as(as = "EnumMap")] /// vec: Vec, /// } /// /// // --- /// /// // This will serialize this list of values /// let values = VecEnumValues { /// vec: vec![ /// EnumValue::Int(123), /// EnumValue::String("FooBar".to_string()), /// EnumValue::Int(456), /// EnumValue::String("XXX".to_string()), /// EnumValue::Unit, /// ], /// }; /// /// // into this XML document /// // Duplicate keys are emitted for identical enum variants. /// let expected = r#" /// /// /// 123 /// FooBar /// 456 /// XXX /// /// /// "# /// // Remove whitespace /// .replace(' ', "") /// .replace('\n', ""); /// /// // Both serialization and deserialization work flawlessly. /// let serialized = serde_xml_rs::to_string(&values).unwrap(); /// assert_eq!(expected, serialized); /// let deserialized: VecEnumValues = serde_xml_rs::from_str(&serialized).unwrap(); /// assert_eq!(values, deserialized); /// # } /// ``` #[derive(Debug, Copy, Clone)] pub struct EnumMap; impl SerializeAs> for EnumMap where T: Serialize, { fn serialize_as(source: &Vec, serializer: S) -> Result where S: Serializer, { source.serialize(SeqAsMapSerializer(serializer)) } } impl<'de, T> DeserializeAs<'de, Vec> for EnumMap where T: Deserialize<'de>, { fn deserialize_as(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { struct EnumMapVisitor(PhantomData); impl<'de, T> Visitor<'de> for EnumMapVisitor where T: Deserialize<'de>, { type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { write!(formatter, "a map or enum values") } fn visit_map>(self, map: A) -> Result { Vec::deserialize(SeqDeserializer(map)) } } deserializer.deserialize_map(EnumMapVisitor(PhantomData)) } } static END_OF_MAP_IDENTIFIER: &str = "__PRIVATE_END_OF_MAP_MARKER__"; // Serialization code below here /// Convert a sequence to a map during serialization. /// /// Only `serialize_seq` is implemented and forwarded to `serialize_map` on the inner `Serializer`. /// The elements are serialized with [`SerializeSeqElement`]. struct SeqAsMapSerializer(S); impl Serializer for SeqAsMapSerializer where S: Serializer, { type Ok = S::Ok; type Error = S::Error; type SerializeSeq = SerializeSeqElement; type SerializeTuple = Impossible; type SerializeTupleStruct = Impossible; type SerializeTupleVariant = Impossible; type SerializeMap = Impossible; type SerializeStruct = Impossible; type SerializeStructVariant = Impossible; fn serialize_bool(self, _v: bool) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i8(self, _v: i8) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i16(self, _v: i16) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i32(self, _v: i32) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i64(self, _v: i64) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i128(self, _v: i128) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u8(self, _v: u8) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u16(self, _v: u16) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u32(self, _v: u32) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u64(self, _v: u64) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u128(self, _v: u128) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_f32(self, _v: f32) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_f64(self, _v: f64) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_char(self, _v: char) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_str(self, _v: &str) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_bytes(self, _v: &[u8]) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_none(self) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_some(self, _value: &T) -> Result where T: Serialize, { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_unit(self) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_unit_struct(self, _name: &'static str) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, _variant: &'static str, ) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_newtype_struct( self, _name: &'static str, _value: &T, ) -> Result where T: Serialize, { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, _variant: &'static str, _value: &T, ) -> Result where T: Serialize, { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_seq(self, len: Option) -> Result { let is_human_readable = self.0.is_human_readable(); self.0 .serialize_map(len) .map(|delegate| SerializeSeqElement { delegate, is_human_readable, }) } fn serialize_tuple(self, _len: usize) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_tuple_struct( self, _name: &'static str, _len: usize, ) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize, ) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_map(self, _len: Option) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_struct( self, _name: &'static str, _len: usize, ) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_struct_variant( self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize, ) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } } /// Serialize a single element but turn the sequence into a map logic. /// /// It uses [`SerializeEnumAsMapElement`] for the map element serialization. /// /// The [`Serializer`] implementation handles all the `serialize_*_variant` functions and defers to [`SerializeVariant`] for the more complicated tuple and struct variants. struct SerializeSeqElement { delegate: M, is_human_readable: bool, } impl SerializeSeq for SerializeSeqElement where M: SerializeMap, { type Ok = M::Ok; type Error = M::Error; fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize, { value.serialize(EnumAsMapElementSerializer { delegate: &mut self.delegate, is_human_readable: self.is_human_readable, })?; Ok(()) } fn end(self) -> Result { self.delegate.end() } } struct EnumAsMapElementSerializer<'a, M> { delegate: &'a mut M, is_human_readable: bool, } impl<'a, M> Serializer for EnumAsMapElementSerializer<'a, M> where M: SerializeMap, { type Ok = (); type Error = M::Error; type SerializeSeq = Impossible; type SerializeTuple = Impossible; type SerializeTupleStruct = Impossible; type SerializeTupleVariant = SerializeVariant<'a, M>; type SerializeMap = Impossible; type SerializeStruct = Impossible; type SerializeStructVariant = SerializeVariant<'a, M>; fn serialize_bool(self, _v: bool) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i8(self, _v: i8) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i16(self, _v: i16) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i32(self, _v: i32) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i64(self, _v: i64) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_i128(self, _v: i128) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u8(self, _v: u8) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u16(self, _v: u16) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u32(self, _v: u32) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u64(self, _v: u64) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_u128(self, _v: u128) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_f32(self, _v: f32) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_f64(self, _v: f64) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_char(self, _v: char) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_str(self, _v: &str) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_bytes(self, _v: &[u8]) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_none(self) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_some(self, _value: &T) -> Result where T: Serialize, { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_unit(self) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_unit_struct(self, _name: &'static str) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, ) -> Result { self.delegate.serialize_entry(variant, &())?; Ok(()) } fn serialize_newtype_struct( self, _name: &'static str, _value: &T, ) -> Result where T: Serialize, { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: Serialize, { self.delegate.serialize_entry(variant, value)?; Ok(()) } fn serialize_seq(self, _len: Option) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_tuple(self, _len: usize) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_tuple_struct( self, _name: &'static str, _len: usize, ) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_tuple_variant( self, name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(SerializeVariant { delegate: self.delegate, is_human_readable: self.is_human_readable, variant, content: Content::TupleStruct(name, Vec::with_capacity(len)), }) } fn serialize_map(self, _len: Option) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_struct( self, _name: &'static str, _len: usize, ) -> Result { Err(ser::Error::custom("wrong type for EnumMap")) } fn serialize_struct_variant( self, name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(SerializeVariant { delegate: self.delegate, is_human_readable: self.is_human_readable, variant, content: Content::Struct(name, Vec::with_capacity(len)), }) } } /// Serialize a struct or tuple variant enum as a map element /// /// [`SerializeStructVariant`] serializes a struct variant, and [`SerializeTupleVariant`] a tuple variant. struct SerializeVariant<'a, M> { delegate: &'a mut M, is_human_readable: bool, variant: &'static str, content: Content, } impl<'a, M> SerializeStructVariant for SerializeVariant<'a, M> where M: SerializeMap, { type Ok = (); type Error = M::Error; fn serialize_field( &mut self, key: &'static str, value: &T, ) -> Result<(), Self::Error> where T: Serialize, { // Serialize to a Content type first let value: Content = value.serialize(ContentSerializer::new(self.is_human_readable))?; if let Content::Struct(_name, fields) = &mut self.content { fields.push((key, value)); } Ok(()) } fn end(self) -> Result { self.delegate.serialize_entry(&self.variant, &self.content) } } impl<'a, M> SerializeTupleVariant for SerializeVariant<'a, M> where M: SerializeMap, { type Ok = (); type Error = M::Error; fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize, { // Serialize to a Content type first let value: Content = value.serialize(ContentSerializer::new(self.is_human_readable))?; if let Content::TupleStruct(_name, fields) = &mut self.content { fields.push(value); } Ok(()) } fn end(self) -> Result { self.delegate.serialize_entry(&self.variant, &self.content) } } // Below is deserialization code /// Deserialize the sequence of enum instances. /// /// The main [`Deserializer`] implementation handles the outer sequence (e.g., `Vec`), while the [`SeqAccess`] implementation is responsible for the inner elements. struct SeqDeserializer(M); impl<'de, M> Deserializer<'de> for SeqDeserializer where M: MapAccess<'de>, { type Error = M::Error; fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_seq(self) } fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } serde::forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct tuple tuple_struct map struct enum identifier ignored_any } } impl<'de, M> SeqAccess<'de> for SeqDeserializer where M: MapAccess<'de>, { type Error = M::Error; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { match seed.deserialize(EnumDeserializer(&mut self.0)) { Ok(value) => Ok(Some(value)), Err(err) => { // Unfortunately we loose the optional aspect of MapAccess, so we need to special case an error value to mark the end of the map. if err.to_string().contains(END_OF_MAP_IDENTIFIER) { Ok(None) } else { Err(err) } } } } fn size_hint(&self) -> Option { self.0.size_hint() } } /// Deserialize an enum from a map element /// /// The [`Deserializer`] implementation is the starting point, which first calls the [`EnumAccess`] methods. /// The [`EnumAccess`] is used to deserialize the enum variant type of the enum. /// The [`VariantAccess`] is used to deserialize the value part of the enum. struct EnumDeserializer(M); impl<'de, M> Deserializer<'de> for EnumDeserializer where M: MapAccess<'de>, { type Error = M::Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_enum("", &[], visitor) } fn deserialize_enum( self, _name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_enum(self) } serde::forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } } impl<'de, M> EnumAccess<'de> for EnumDeserializer where M: MapAccess<'de>, { type Error = M::Error; type Variant = Self; fn variant_seed(mut self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> where T: DeserializeSeed<'de>, { match self.0.next_key_seed(seed)? { Some(key) => Ok((key, self)), // Unfortunately we loose the optional aspect of MapAccess, so we need to special case an error value to mark the end of the map. None => Err(Error::custom(END_OF_MAP_IDENTIFIER)), } } } impl<'de, M> VariantAccess<'de> for EnumDeserializer where M: MapAccess<'de>, { type Error = M::Error; fn unit_variant(mut self) -> Result<(), Self::Error> { self.0.next_value() } fn newtype_variant_seed(mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { self.0.next_value_seed(seed) } fn tuple_variant(mut self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.0.next_value_seed(SeedTupleVariant { len, visitor }) } fn struct_variant( mut self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.0.next_value_seed(SeedStructVariant { visitor }) } } struct SeedTupleVariant { len: usize, visitor: V, } impl<'de, V> DeserializeSeed<'de> for SeedTupleVariant where V: Visitor<'de>, { type Value = V::Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_tuple(self.len, self.visitor) } } struct SeedStructVariant { visitor: V, } impl<'de, V> DeserializeSeed<'de> for SeedStructVariant where V: Visitor<'de>, { type Value = V::Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_map(self.visitor) } }