diff --git a/src/serde/ser.rs b/src/serde/ser.rs index 79b1b733..181573b0 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -103,10 +103,16 @@ impl Serializer for &mut DynamicSerializer { type SerializeSeq = DynamicSerializer; type SerializeTuple = DynamicSerializer; type SerializeTupleStruct = DynamicSerializer; - type SerializeTupleVariant = DynamicSerializer; + #[cfg(not(any(feature = "no_object", feature = "no_index")))] + type SerializeTupleVariant = TupleVariantSerializer; + #[cfg(any(feature = "no_object", feature = "no_index"))] + type SerializeTupleVariant = serde::ser::Impossible>; type SerializeMap = DynamicSerializer; type SerializeStruct = DynamicSerializer; - type SerializeStructVariant = DynamicSerializer; + #[cfg(not(feature = "no_object"))] + type SerializeStructVariant = StructVariantSerializer; + #[cfg(feature = "no_object")] + type SerializeStructVariant = serde::ser::Impossible>; fn serialize_bool(self, v: bool) -> Result> { Ok(v.into()) @@ -244,10 +250,20 @@ impl Serializer for &mut DynamicSerializer { self, _name: &'static str, _variant_index: u32, - _variant: &'static str, + variant: &'static str, value: &T, ) -> Result> { - value.serialize(&mut *self) + #[cfg(not(feature = "no_object"))] + { + let content = to_dynamic(value)?; + make_variant(variant, content) + } + #[cfg(feature = "no_object")] + return Err(Box::new(EvalAltResult::ErrorMismatchOutputType( + "Dynamic".into(), + "map".into(), + Position::none(), + ))); } fn serialize_seq(self, _len: Option) -> Result> { @@ -277,10 +293,26 @@ impl Serializer for &mut DynamicSerializer { self, _name: &'static str, _variant_index: u32, - _variant: &'static str, + variant: &'static str, len: usize, ) -> Result> { - self.serialize_seq(Some(len)) + #[cfg(not(any(feature = "no_object", feature = "no_index")))] + return Ok(TupleVariantSerializer { + variant, + array: Array::with_capacity(len), + }); + #[cfg(any(feature = "no_object", feature = "no_index"))] + { + #[cfg(feature = "no_object")] + let err_type = "map"; + #[cfg(not(feature = "no_object"))] + let err_type = "array"; + Err(Box::new(EvalAltResult::ErrorMismatchOutputType( + "Dynamic".into(), + err_type.into(), + Position::none(), + ))) + } } fn serialize_map(self, _len: Option) -> Result> { @@ -306,10 +338,20 @@ impl Serializer for &mut DynamicSerializer { self, _name: &'static str, _variant_index: u32, - _variant: &'static str, + variant: &'static str, len: usize, ) -> Result> { - self.serialize_map(Some(len)) + #[cfg(not(feature = "no_object"))] + return Ok(StructVariantSerializer { + variant, + map: Map::with_capacity(len), + }); + #[cfg(feature = "no_object")] + return Err(Box::new(EvalAltResult::ErrorMismatchOutputType( + "Dynamic".into(), + "map".into(), + Position::none(), + ))); } } @@ -395,33 +437,6 @@ impl SerializeTupleStruct for DynamicSerializer { } } -impl SerializeTupleVariant for DynamicSerializer { - type Ok = Dynamic; - type Error = Box; - - fn serialize_field( - &mut self, - value: &T, - ) -> Result<(), Box> { - #[cfg(not(feature = "no_index"))] - { - let value = value.serialize(&mut *self)?; - let arr = self.value.downcast_mut::().unwrap(); - arr.push(value); - Ok(()) - } - #[cfg(feature = "no_index")] - unreachable!() - } - - fn end(self) -> Result> { - #[cfg(not(feature = "no_index"))] - return Ok(self.value); - #[cfg(feature = "no_index")] - unreachable!() - } -} - impl SerializeMap for DynamicSerializer { type Ok = Dynamic; type Error = Box; @@ -520,7 +535,39 @@ impl SerializeStruct for DynamicSerializer { } } -impl SerializeStructVariant for DynamicSerializer { +#[cfg(not(any(feature = "no_object", feature = "no_index")))] +pub struct TupleVariantSerializer { + variant: &'static str, + array: Array, +} + +#[cfg(not(any(feature = "no_object", feature = "no_index")))] +impl SerializeTupleVariant for TupleVariantSerializer { + type Ok = Dynamic; + type Error = Box; + + fn serialize_field( + &mut self, + value: &T, + ) -> Result<(), Box> { + let value = to_dynamic(value)?; + self.array.push(value); + Ok(()) + } + + fn end(self) -> Result> { + make_variant(self.variant, self.array.into()) + } +} + +#[cfg(not(feature = "no_object"))] +pub struct StructVariantSerializer { + variant: &'static str, + map: Map, +} + +#[cfg(not(feature = "no_object"))] +impl SerializeStructVariant for StructVariantSerializer { type Ok = Dynamic; type Error = Box; @@ -529,21 +576,19 @@ impl SerializeStructVariant for DynamicSerializer { key: &'static str, value: &T, ) -> Result<(), Box> { - #[cfg(not(feature = "no_object"))] - { - let value = value.serialize(&mut *self)?; - let map = self.value.downcast_mut::().unwrap(); - map.insert(key.into(), value); - Ok(()) - } - #[cfg(feature = "no_object")] - unreachable!() + let value = to_dynamic(value)?; + self.map.insert(key.into(), value); + Ok(()) } fn end(self) -> Result> { - #[cfg(not(feature = "no_object"))] - return Ok(self.value); - #[cfg(feature = "no_object")] - unreachable!() + make_variant(self.variant, self.map.into()) } } + +#[cfg(not(feature = "no_object"))] +fn make_variant(variant: &'static str, value: Dynamic) -> Result> { + let mut map = Map::with_capacity(1); + map.insert(variant.into(), value); + Ok(map.into()) +} diff --git a/tests/serde.rs b/tests/serde.rs index cf86dcf2..7b0a4c5f 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -135,7 +135,6 @@ fn test_serde_ser_unit_enum() -> Result<(), Box> { } #[test] -#[ignore = "failing test"] #[cfg(not(feature = "no_object"))] fn test_serde_ser_externally_tagged_enum() -> Result<(), Box> { #[derive(Serialize)]