From bdf778a9d92d150394f4e0fa4970ddd39b76985e Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sat, 24 Jul 2021 18:04:51 +0100 Subject: [PATCH] Implement support for enum tuples variants and tuple structs --- src/lib.rs | 8 ++++++++ src/ser.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5ee98d2..a143b80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,15 +31,21 @@ mod test { pub enum Test { Abc, Def(i32), + Ghi(i32, i32, i32), } #[derive(Serialize)] + pub struct Tup(i32, i32); + + #[derive(Serialize)] pub struct B<'a> { s: &'a str, a: Vec<&'a str>, e: Test, e2: Test, + e3: Test, t: (i32, i32, i32), + ts: Tup, } let test = &A { @@ -51,7 +57,9 @@ mod test { a: vec!["yooo", "mayn"], e: Test::Abc, e2: Test::Def(1999), + e3: Test::Ghi(16, 07, 1999), t: (16, 07, 1999), + ts: Tup(99, 100), }, }; diff --git a/src/ser.rs b/src/ser.rs index 735bc24..ef35b91 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -29,8 +29,8 @@ impl<'a> serde::Serializer for Serializer<'a> { type SerializeSeq = SeqSerializer<'a>; type SerializeTuple = TupleSerializer<'a>; - type SerializeTupleStruct = serde::ser::Impossible; - type SerializeTupleVariant = serde::ser::Impossible; + type SerializeTupleStruct = TupleStructSerializer<'a>; + type SerializeTupleVariant = TupleVariantSerializer<'a>; type SerializeMap = serde::ser::Impossible; type SerializeStruct = StructSerializer<'a>; type SerializeStructVariant = serde::ser::Impossible; @@ -205,19 +205,39 @@ impl<'a> serde::Serializer for Serializer<'a> { fn serialize_tuple_struct( self, _name: &'static str, - _len: usize, + len: usize, ) -> Result { - todo!("tuple struct") + Ok(TupleStructSerializer { + inner: self.serialize_seq(Some(len))?, + }) } fn serialize_tuple_variant( - self, + mut self, _name: &'static str, _variant_index: u32, - _variant: &'static str, + variant: &'static str, _len: usize, ) -> Result { - todo!("tuple variant") + // we essentially need a nested type here which isn't too well supported with serde's + // model, first we create a new document which we'll use to write the variant into as + // the key, and then we'll create a second document we'll use as an array for each + // tuple element + + 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!(0x04, Some(DocumentKey::Str(variant)), &mut doc_output); + let array_output = start_document(&mut doc_output); + + Ok(TupleVariantSerializer { + original_output: self.output, + array_output, + doc_output, + key: 0, + }) } fn serialize_map(self, _len: Option) -> Result { @@ -272,6 +292,60 @@ impl<'a> serde::ser::SerializeTuple for TupleSerializer<'a> { } } +pub struct TupleVariantSerializer<'a> { + original_output: &'a mut BytesMut, + array_output: BytesMut, + doc_output: BytesMut, + key: usize, +} + +impl<'a> serde::ser::SerializeTupleVariant for TupleVariantSerializer<'a> { + type Ok = (); + type Error = as serde::Serializer>::Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + // we're basically inside a SeqSerializer here, but we can't instantiate one + // so we'll duplicate the functionality instead + value.serialize(Serializer { + key: Some(DocumentKey::Int(self.key)), + output: &mut self.array_output, + })?; + self.key += 1; + Ok(()) + } + + fn end(mut self) -> Result { + // first we close the array output into the doc output, then write the complete doc output + // to original_output + terminate_document(&mut self.doc_output, self.array_output); + terminate_document(self.original_output, self.doc_output); + Ok(()) + } +} + +pub struct TupleStructSerializer<'a> { + inner: SeqSerializer<'a>, +} + +impl<'a> serde::ser::SerializeTupleStruct for TupleStructSerializer<'a> { + type Ok = (); + type Error = as serde::Serializer>::Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + self.inner.serialize_element(value) + } + + fn end(self) -> Result { + self.inner.end() + } +} + pub struct SeqSerializer<'a> { original_output: &'a mut BytesMut, doc_output: BytesMut, -- libgit2 1.7.2