Support nested documents, remove take_mut dependency
Diff
Cargo.toml | 1 -
src/lib.rs | 38 ++++++++++----------------------------
src/ser.rs | 49 +++++++++++++++++++++++++++++++++++--------------
3 files changed, 45 insertions(+), 43 deletions(-)
@@ -12,7 +12,6 @@ license = "0BSD"
[dependencies]
serde = "1"
bytes = "1"
take_mut = "0.2"
[dev-dependencies]
serde = { version = "1", features = ["derive"] }
@@ -3,36 +3,11 @@ pub mod ser;
pub use error::Error;
use bytes::{BufMut, BytesMut};
use bytes::BytesMut;
use serde::Serialize;
pub fn to_string<T: Serialize>(val: &T, output: &mut BytesMut) -> Result<(), Error> {
const SIZE_OF_SIZE: usize = std::mem::size_of::<i32>();
output.put_i32(0);
let mut size = output.split_to(SIZE_OF_SIZE);
val.serialize(ser::Serializer { key: None, output })?;
for (i, byte) in ((output.len() + SIZE_OF_SIZE) as i32)
.to_le_bytes()
.iter()
.enumerate()
{
size[i] = *byte;
}
take_mut::take(output, move |output| {
size.unsplit(output);
size
});
Ok(())
val.serialize(ser::Serializer { key: None, output })
}
#[cfg(test)]
@@ -49,16 +24,23 @@ mod test {
#[serde(with = "serde_bytes")]
beans: &'a [u8],
bro: &'a str,
b: B<'a>,
}
#[derive(Serialize)]
pub struct B<'a> {
s: &'a str,
}
let test = &A {
cool: 999,
beans: "so there was this one time at bandcamp".as_bytes(),
bro: "the craziest thing happened",
b: B { s: "dddd" },
};
let mut ours = BytesMut::new();
to_string(&test, &mut ours);
to_string(&test, &mut ours).unwrap();
let mut theirs = BytesMut::new().writer();
bson::ser::to_document(&test)
@@ -1,11 +1,11 @@
use crate::Error;
use bytes::BufMut;
use bytes::{BufMut, BytesMut};
use serde::Serialize;
use std::convert::TryFrom;
pub struct Serializer<'a, B: BufMut> {
pub struct Serializer<'a> {
pub key: Option<&'static str>,
pub output: &'a mut B,
pub output: &'a mut BytesMut,
}
macro_rules! write_key_or_error {
@@ -20,7 +20,7 @@ macro_rules! write_key_or_error {
};
}
impl<'a, B: BufMut> serde::Serializer for Serializer<'a, B> {
impl<'a> serde::Serializer for Serializer<'a> {
type Ok = ();
type Error = Error;
@@ -29,7 +29,7 @@ impl<'a, B: BufMut> serde::Serializer for Serializer<'a, B> {
type SerializeTupleStruct = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeTupleVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeMap = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeStruct = StructSerializer<'a, B>;
type SerializeStruct = StructSerializer<'a>;
type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
@@ -208,11 +208,19 @@ impl<'a, B: BufMut> serde::Serializer for Serializer<'a, B> {
_len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
if self.key.is_some() {
todo!("nested struct: {:?}", self.key);
write_key_or_error!(0x03, self.key, self.output);
}
let mut doc_output = self.output.split_off(self.output.len());
doc_output.put_i32(0);
Ok(StructSerializer {
output: self.output,
original_output: self.output,
doc_output,
})
}
@@ -227,13 +235,14 @@ impl<'a, B: BufMut> serde::Serializer for Serializer<'a, B> {
}
}
pub struct StructSerializer<'a, B: BufMut> {
output: &'a mut B,
pub struct StructSerializer<'a> {
original_output: &'a mut BytesMut,
doc_output: BytesMut,
}
impl<'a, B: BufMut> serde::ser::SerializeStruct for StructSerializer<'a, B> {
impl<'a> serde::ser::SerializeStruct for StructSerializer<'a> {
type Ok = ();
type Error = <Serializer<'a, B> as serde::Serializer>::Error;
type Error = <Serializer<'a> as serde::Serializer>::Error;
fn serialize_field<T: ?Sized>(
&mut self,
@@ -245,12 +254,24 @@ impl<'a, B: BufMut> serde::ser::SerializeStruct for StructSerializer<'a, B> {
{
value.serialize(Serializer {
key: Some(key),
output: &mut self.output,
output: &mut self.doc_output,
})
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.output.put_u8(0x00); fn end(mut self) -> Result<Self::Ok, Self::Error> {
self.doc_output.put_u8(0x00);
for (i, byte) in (self.doc_output.len() as i32)
.to_le_bytes()
.iter()
.enumerate()
{
self.doc_output[i] = *byte;
}
self.original_output.unsplit(self.doc_output);
Ok(())
}
}