🏡 index : ~doyle/serde_bson.git

author Jordan Doyle <jordan@doyle.la> 2021-07-24 17:15:52.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2021-07-24 17:15:52.0 +00:00:00
commit
a3fbfc26cc12d4602d09dc93425e7e241c1dfa47 [patch]
tree
bc753e0e134e8657254bf7d7761c363715207eed
parent
cfad5e67c162ceb6c278e5dc68c54767a3d06f2c
download
a3fbfc26cc12d4602d09dc93425e7e241c1dfa47.tar.gz

Implement struct-like enum variant serialisation



Diff

 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<Self::Ok, Self::Error>;
    type SerializeStruct = StructSerializer<'a>;
    type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
    type SerializeStructVariant = StructVariantSerializer<'a>;

    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
        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<Self::SerializeStructVariant, Self::Error> {
        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<Self::Ok, Self::Error> {
@@ -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 = <Serializer<'a> as serde::Serializer>::Error;

    fn serialize_field<T: ?Sized>(
        &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<Self::Ok, Self::Error> {
        // 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>,
}