From a3fbfc26cc12d4602d09dc93425e7e241c1dfa47 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sat, 24 Jul 2021 18:15:52 +0100 Subject: [PATCH] Implement struct-like enum variant serialisation --- src/lib.rs | 3 +++ src/ser.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a143b80..b6eeaba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ mod test { Abc, Def(i32), Ghi(i32, i32, i32), + Jkl { a: i32, b: i32 }, } #[derive(Serialize)] @@ -44,6 +45,7 @@ mod test { e: Test, e2: Test, e3: Test, + e4: Test, t: (i32, i32, i32), ts: Tup, } @@ -58,6 +60,7 @@ mod test { e: Test::Abc, e2: Test::Def(1999), e3: Test::Ghi(16, 07, 1999), + e4: Test::Jkl { a: 16, b: 07 }, t: (16, 07, 1999), ts: Tup(99, 100), }, diff --git a/src/ser.rs b/src/ser.rs index 8957c12..32e4665 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -33,7 +33,7 @@ impl<'a> serde::Serializer for Serializer<'a> { type SerializeTupleVariant = TupleVariantSerializer<'a>; type SerializeMap = serde::ser::Impossible; type SerializeStruct = StructSerializer<'a>; - type SerializeStructVariant = serde::ser::Impossible; + type SerializeStructVariant = StructVariantSerializer<'a>; fn serialize_bool(self, v: bool) -> Result { write_key_or_error!(0x01, self.key, self.output); @@ -242,13 +242,28 @@ impl<'a> serde::Serializer for Serializer<'a> { } fn serialize_struct_variant( - self, + mut self, _name: &'static str, _variant_index: u32, - _variant: &'static str, + variant: &'static str, _len: usize, ) -> Result { - todo!("struct variant") + // this method ends up very similar to serialize_tuple_variant except string keys + // are used for the output document + + if self.key.is_some() { + write_key_or_error!(0x03, self.key, self.output); + } + + let mut doc_output = start_document(&mut self.output); + write_key_or_error!(0x03, Some(DocumentKey::Str(variant)), &mut doc_output); + let nested_doc_output = start_document(&mut doc_output); + + Ok(StructVariantSerializer { + original_output: self.output, + nested_doc_output, + doc_output, + }) } fn serialize_u8(self, _v: u8) -> Result { @@ -326,6 +341,44 @@ impl<'a> serde::ser::SerializeTupleVariant for TupleVariantSerializer<'a> { } } +pub struct StructVariantSerializer<'a> { + original_output: &'a mut BytesMut, + nested_doc_output: BytesMut, + doc_output: BytesMut, +} + +impl<'a> serde::ser::SerializeStructVariant for StructVariantSerializer<'a> { + type Ok = (); + type Error = as serde::Serializer>::Error; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize, + { + // we're basically inside a nested StructSerializer here, but we can't + // instantiate one so we'll duplicate the functionality instead. this + // is very similar to `TupleVariantSerializer` except string keys are + // used instead + value.serialize(Serializer { + key: Some(DocumentKey::Str(key)), + output: &mut self.nested_doc_output, + })?; + Ok(()) + } + + fn end(mut self) -> Result { + // first we close the nested output into the doc output, then write the complete doc output + // to original_output + terminate_document(&mut self.doc_output, self.nested_doc_output); + terminate_document(self.original_output, self.doc_output); + Ok(()) + } +} + pub struct TupleStructSerializer<'a> { inner: SeqSerializer<'a>, } -- libgit2 1.7.2