Diff
Cargo.toml | 15 ++++++++++-----
README.md | 38 +++++++++-----------------------------
benches/borrowed.rs | 58 ----------------------------------------------------------
benches/deserialize.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
benches/owned.rs | 60 ------------------------------------------------------------
benches/serialize.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/byte.rs | 4 ++--
src/de.rs | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/lib.rs | 14 +++++++++-----
src/ser.rs | 44 ++++++++++++++++++--------------------------
test/test.bin | 0
src/snapshots/serde_bson__de__test__deserialize.snap | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 764 insertions(+), 185 deletions(-)
@@ -12,19 +12,24 @@
[dependencies]
serde = "1"
bytes = "1"
itoa = "0.4"
itoa = "1.0"
simdutf8 = "0.1"
memchr = "2.7"
thiserror = "1"
bumpalo = { version = "3.16", features = ["collections"] }
[dev-dependencies]
serde = { version = "1", features = ["derive"] }
serde_bytes = "0.11"
bson = "1.2"
criterion = "0.3"
bson = "2.13"
criterion = "0.5"
rand = "0.8"
insta = "1.4"
[[bench]]
name = "borrowed"
name = "serialize"
harness = false
[[bench]]
name = "owned"
name = "deserialize"
harness = false
@@ -1,38 +1,18 @@
## serde_bson
Originally implemented as a workaround to the `bson` crate cloning every value it
comes across and it's looking like it shows significant improvement across the board
for serialisation (~80% improvement).
comes across. The `bson` crate has since improved in this aspect, however this
clean room implementation of the spec still shows significant speedup in both
serialisation and deserialisation.
```
borrowed: mongodb's bson time: [1.1160 us 1.1171 us 1.1183 us]
Found 2 outliers among 100 measurements (2.00%)
2 (2.00%) high mild
deserialize: mongodb's bson
time: [867.32 ns 867.62 ns 867.97 ns]
borrowed: serde_bson time: [201.99 ns 202.17 ns 202.38 ns]
Found 10 outliers among 100 measurements (10.00%)
4 (4.00%) low mild
4 (4.00%) high mild
2 (2.00%) high severe
```
Even on owned data it shows a significant improvement:
deserialize: serde_bson time: [468.41 ns 470.12 ns 472.06 ns]
```
owned: mongodb's bson time: [1.0740 us 1.0762 us 1.0794 us]
Found 6 outliers among 100 measurements (6.00%)
4 (4.00%) low mild
1 (1.00%) high mild
1 (1.00%) high severe
serialize: mongodb's bson
time: [684.01 ns 686.48 ns 689.57 ns]
owned: serde_bson time: [209.67 ns 210.18 ns 211.06 ns]
Found 9 outliers among 100 measurements (9.00%)
5 (5.00%) high mild
4 (4.00%) high severe
serialize: serde_bson time: [136.42 ns 136.86 ns 137.36 ns]
```
There's a few pieces missing such as arrays and nested documents but they're not
too difficult to add, it's just that it's 2:38am and I've smashed this out in an
hour.
Pull requests welcome as always.
@@ -1,58 +1,0 @@
use bytes::BufMut;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
#[derive(serde::Serialize)]
pub struct A<'a> {
a: &'a str,
b: &'a str,
c: &'a str,
d: i64,
e: f64,
#[serde(with = "serde_bytes")]
f: &'a [u8],
}
fn benchmark(c: &mut Criterion) {
let val = A {
a: "Now this is a story all about how
My life got flipped turned upside down
And I'd like to take a minute, just sit right there
I'll tell you how I became the prince of a town called Bel-Air",
b: "In West Philadelphia born and raised
On the playground is where I spent most of my days
Chillin' out, maxin', relaxin' all cool
And all shootin' some b-ball outside of the school
When a couple of guys who were up to no good
Started makin' trouble in my neighborhood",
c: "I got in one little fight and my mom got scared
And said 'You're movin' with your auntie and uncle in Bel-Air'",
d: 420,
e: 420.69696969696969,
f: "Above are some popular 'pop culture' references for your perusal and enjoyment"
.as_bytes(),
};
c.bench_function("borrowed: mongodb's bson", |b| {
let mut theirs = Vec::new();
b.iter(|| {
bson::ser::to_document(black_box(&val))
.unwrap()
.to_writer(&mut theirs)
.unwrap();
theirs.clear();
})
});
c.bench_function("borrowed: serde_bson", |b| {
let mut out = bytes::BytesMut::new();
b.iter(|| {
serde_bson::to_string(black_box(&val), &mut out).unwrap();
drop(out.split());
});
});
}
criterion_group!(benches, benchmark);
criterion_main!(benches);
@@ -1,0 +1,51 @@
use bytes::BufMut;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct A<'a> {
cool: i32,
#[serde(with = "serde_bytes")]
beans: &'a [u8],
bro: &'a str,
b: B<'a>,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub enum Test {
Abc,
Def(i32),
Ghi(i32, i32, i32),
Jkl { a: i32, b: i32 },
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Tup(i32, i32);
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct B<'a> {
s: &'a str,
a: Vec<&'a str>,
e: Test,
e2: Test,
e3: Test,
e4: Test,
t: (i32, i32, i32),
ts: Tup,
y: bool,
}
fn benchmark(c: &mut Criterion) {
let data = include_bytes!("../test/test.bin");
c.bench_function("deserialize: mongodb's bson", |b| {
b.iter(|| bson::de::from_slice::<A>(black_box(data)))
});
c.bench_function("deserialize: serde_bson", |b| {
b.iter(|| serde_bson::de::from_bytes::<A>(black_box(data)));
});
}
criterion_group!(benches, benchmark);
criterion_main!(benches);
@@ -1,60 +1,0 @@
use bytes::BufMut;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
#[derive(serde::Serialize)]
pub struct A {
a: String,
b: String,
c: String,
d: i64,
e: f64,
#[serde(with = "serde_bytes")]
f: Vec<u8>,
}
fn benchmark(c: &mut Criterion) {
let val = A {
a: "Now this is a story all about how
My life got flipped turned upside down
And I'd like to take a minute, just sit right there
I'll tell you how I became the prince of a town called Bel-Air"
.to_string(),
b: "In West Philadelphia born and raised
On the playground is where I spent most of my days
Chillin' out, maxin', relaxin' all cool
And all shootin' some b-ball outside of the school
When a couple of guys who were up to no good
Started makin' trouble in my neighborhood"
.to_string(),
c: "I got in one little fight and my mom got scared
And said 'You're movin' with your auntie and uncle in Bel-Air'"
.to_string(),
d: 420,
e: 420.69696969696969,
f: "Above are some popular 'pop culture' references for your perusal and enjoyment".into(),
};
c.bench_function("owned: mongodb's bson", |b| {
let mut theirs = Vec::new();
b.iter(|| {
bson::ser::to_document(black_box(&val))
.unwrap()
.to_writer(&mut theirs)
.unwrap();
theirs.clear();
})
});
c.bench_function("owned: serde_bson", |b| {
let mut out = bytes::BytesMut::new();
b.iter(|| {
serde_bson::to_string(black_box(&val), &mut out).unwrap();
drop(out.split());
});
});
}
criterion_group!(benches, benchmark);
criterion_main!(benches);
@@ -1,0 +1,60 @@
use bytes::BufMut;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
#[derive(serde::Serialize)]
pub struct A {
a: String,
b: String,
c: String,
d: i64,
e: f64,
#[serde(with = "serde_bytes")]
f: Vec<u8>,
}
fn benchmark(c: &mut Criterion) {
let val = A {
a: "Now this is a story all about how
My life got flipped turned upside down
And I'd like to take a minute, just sit right there
I'll tell you how I became the prince of a town called Bel-Air"
.to_string(),
b: "In West Philadelphia born and raised
On the playground is where I spent most of my days
Chillin' out, maxin', relaxin' all cool
And all shootin' some b-ball outside of the school
When a couple of guys who were up to no good
Started makin' trouble in my neighborhood"
.to_string(),
c: "I got in one little fight and my mom got scared
And said 'You're movin' with your auntie and uncle in Bel-Air'"
.to_string(),
d: 420,
e: 420.69696969696969,
f: "Above are some popular 'pop culture' references for your perusal and enjoyment".into(),
};
c.bench_function("serialize: mongodb's bson", |b| {
let mut theirs = Vec::new();
b.iter(|| {
bson::ser::to_document(black_box(&val))
.unwrap()
.to_writer(&mut theirs)
.unwrap();
theirs.clear();
})
});
c.bench_function("serialize: serde_bson", |b| {
let mut out = bytes::BytesMut::new();
b.iter(|| {
serde_bson::to_string(black_box(&val), &mut out).unwrap();
drop(out.split());
});
});
}
criterion_group!(benches, benchmark);
criterion_main!(benches);
@@ -49,7 +49,7 @@
}
);
impl<'a, B: BytesLikeBuf> BytesLikeBuf for &mut B {
impl<B: BytesLikeBuf> BytesLikeBuf for &mut B {
type Out = <B as BytesLikeBuf>::Out;
fn put_u8(&mut self, v: u8) {
@@ -115,7 +115,7 @@
}
fn put_slice(&mut self, s: &[u8]) {
self.bytes += std::mem::size_of::<u8>() * s.len();
self.bytes += std::mem::size_of_val(s);
}
fn split_off(&mut self, _at: usize) -> Self {
@@ -1,0 +1,398 @@
use memchr::memchr;
use std::{cell::RefCell, convert::TryInto, fmt::Display};
use serde::{
de::{
value::BorrowedStrDeserializer, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
},
forward_to_deserialize_any, Deserializer,
};
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("unexpected map end")]
UnexpectedMapEnd,
#[error("unexpected key")]
UnexpectedKey,
#[error("end of file")]
EndOfFile,
#[error("custom: {0}")]
Custom(String),
#[error("malformed map, missing key or document end")]
MalformedMapMissingKey,
#[error("unexpected enum")]
UnexpectedEnum,
}
impl serde::de::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Self::Custom(msg.to_string())
}
}
thread_local! {
static ALLOCATOR: RefCell<bumpalo::Bump> = RefCell::new(bumpalo::Bump::new());
}
pub fn from_bytes<'de, D: serde::de::Deserialize<'de>>(data: &'de [u8]) -> Result<D, Error> {
ALLOCATOR.with_borrow_mut(|allocator| {
allocator.reset();
let mut tape = bumpalo::collections::Vec::new_in(allocator);
to_tape(data, &mut tape);
D::deserialize(&mut BsonDeserializer { tape: &tape })
})
}
struct BsonDeserializer<'a, 'de> {
tape: &'a [Tape<'de>],
}
impl<'a, 'de> BsonDeserializer<'a, 'de> {
fn next_item(&mut self) -> Option<&'a Tape<'de>> {
let (next, rest) = self.tape.split_first()?;
self.tape = rest;
Some(next)
}
}
impl<'de> Deserializer<'de> for &mut BsonDeserializer<'_, 'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.next_item() {
Some(Tape::DocumentStart) => visitor.visit_map(self),
Some(Tape::DocumentEnd) => Err(Error::UnexpectedMapEnd),
Some(Tape::Key(_)) => Err(Error::UnexpectedKey),
Some(Tape::Double(value)) => visitor.visit_f64(*value),
Some(Tape::String(value)) => visitor.visit_borrowed_str(value),
Some(Tape::ArrayStart) => self.deserialize_seq(visitor),
Some(Tape::Binary(value, _)) => visitor.visit_borrowed_bytes(value),
Some(Tape::Boolean(value)) => visitor.visit_bool(*value),
Some(Tape::UtcDateTime(value)) => visitor.visit_i64(*value),
Some(Tape::Null) => visitor.visit_none(),
Some(Tape::I32(value)) => visitor.visit_i32(*value),
Some(Tape::Timestamp(value)) => visitor.visit_u64(*value),
Some(Tape::I64(value)) => visitor.visit_i64(*value),
None => Err(Error::EndOfFile),
}
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Some(Tape::ArrayStart) = self.tape.first() {
self.tape = &self.tape[1..];
}
let res = visitor.visit_seq(&mut *self)?;
let Some(Tape::DocumentEnd) = self.next_item() else {
return Err(Error::UnexpectedMapEnd);
};
Ok(res)
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.next_item() {
Some(Tape::String(s)) => visitor.visit_enum(s.into_deserializer()),
Some(Tape::DocumentStart) => {
let data = visitor.visit_enum(&mut EnumDeserializer { deser: &mut *self })?;
let Some(Tape::DocumentEnd) = self.next_item() else {
return Err(Error::UnexpectedMapEnd);
};
Ok(data)
}
Some(Tape::ArrayStart) => {
let data = visitor.visit_enum(&mut EnumDeserializer { deser: &mut *self })?;
let Some(Tape::DocumentEnd) = self.next_item() else {
return Err(Error::UnexpectedMapEnd);
};
Ok(data)
}
_ => Err(Error::UnexpectedEnum),
}
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct tuple tuple_struct
map struct identifier ignored_any
}
}
struct EnumDeserializer<'a, 'b, 'de> {
deser: &'b mut BsonDeserializer<'a, 'de>,
}
impl<'de> Deserializer<'de> for &mut EnumDeserializer<'_, '_, 'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Some(Tape::Key(key)) = self.deser.tape.first() {
self.deser.tape = &self.deser.tape[1..];
visitor.visit_borrowed_str(key)
} else {
self.deser.deserialize_any(visitor)
}
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct enum identifier ignored_any
}
}
impl<'de> VariantAccess<'de> for &mut EnumDeserializer<'_, '_, 'de> {
type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> {
unreachable!()
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(self)
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_seq(visitor)
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_map(visitor)
}
}
impl<'de> EnumAccess<'de> for &mut EnumDeserializer<'_, '_, 'de> {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
let value = seed.deserialize(&mut *self)?;
Ok((value, self))
}
}
impl<'de> MapAccess<'de> for BsonDeserializer<'_, 'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: serde::de::DeserializeSeed<'de>,
{
let data = match self.next_item() {
Some(Tape::DocumentEnd) => return Ok(None),
Some(Tape::Key(key)) => key,
_ => return Err(Error::MalformedMapMissingKey),
};
seed.deserialize(BorrowedStrDeserializer::new(data))
.map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(self)
}
}
impl<'de> SeqAccess<'de> for BsonDeserializer<'_, 'de> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
if let Some(Tape::DocumentEnd) = self.tape.first() {
return Ok(None);
}
let Some(Tape::Key(_)) = self.next_item() else {
return Err(Error::MalformedMapMissingKey);
};
seed.deserialize(self).map(Some)
}
}
#[derive(Debug)]
pub enum Tape<'a> {
DocumentStart,
DocumentEnd,
Key(&'a str),
Double(f64),
String(&'a str),
ArrayStart,
Binary(&'a [u8], u8),
Boolean(bool),
UtcDateTime(i64),
Null,
I32(i32),
Timestamp(u64),
I64(i64),
}
fn to_tape<'a>(input: &'a [u8], tape: &mut bumpalo::collections::Vec<'_, Tape<'a>>) {
let length = u32::from_le_bytes([input[0], input[1], input[2], input[3]]) as usize;
let input = &input[4..length];
let mut position = 0;
tape.push(Tape::DocumentStart);
let take_cstring = |position: &mut usize| {
let idx = memchr(b'\0', &input[*position..]).expect("unterminated c-string");
let s = simdutf8::basic::from_utf8(&input[*position..*position + idx]).unwrap();
*position += idx + 1;
s
};
let take_bytes = |position: &mut usize, n| {
let res = &input[*position..*position + n];
*position += n;
res
};
while position < length - 4 {
position += 1;
match input[position - 1] {
0x00 => {
tape.push(Tape::DocumentEnd);
}
0x01 => {
let key = take_cstring(&mut position);
let value = f64::from_le_bytes(take_bytes(&mut position, 8).try_into().unwrap());
tape.push(Tape::Key(key));
tape.push(Tape::Double(value));
}
0x02 => {
let key = take_cstring(&mut position);
let length =
u32::from_le_bytes(take_bytes(&mut position, 4).try_into().unwrap()) as usize;
let value =
simdutf8::basic::from_utf8(&input[position..position + length - 1]).unwrap();
position += length;
tape.push(Tape::Key(key));
tape.push(Tape::String(value));
}
0x03 => {
let key = take_cstring(&mut position);
let _length = take_bytes(&mut position, 4);
tape.push(Tape::Key(key));
tape.push(Tape::DocumentStart);
}
0x04 => {
let key = take_cstring(&mut position);
let _length = take_bytes(&mut position, 4);
tape.push(Tape::Key(key));
tape.push(Tape::ArrayStart);
}
0x05 => {
let key = take_cstring(&mut position);
let length =
u32::from_le_bytes(take_bytes(&mut position, 4).try_into().unwrap()) as usize;
let subtype = input[position];
position += 1;
let value = &input[position..position + length];
position += length;
tape.push(Tape::Key(key));
tape.push(Tape::Binary(value, subtype));
}
0x08 => {
let key = take_cstring(&mut position);
let value = input[position] == 1;
position += 1;
tape.push(Tape::Key(key));
tape.push(Tape::Boolean(value));
}
0x09 => {
let key = take_cstring(&mut position);
let value = i64::from_le_bytes(take_bytes(&mut position, 8).try_into().unwrap());
tape.push(Tape::Key(key));
tape.push(Tape::UtcDateTime(value));
}
0x0a => {
let key = take_cstring(&mut position);
tape.push(Tape::Key(key));
tape.push(Tape::Null);
}
0x10 => {
let key = take_cstring(&mut position);
let value = i32::from_le_bytes(take_bytes(&mut position, 4).try_into().unwrap());
tape.push(Tape::Key(key));
tape.push(Tape::I32(value));
}
0x11 => {
let key = take_cstring(&mut position);
let value = u64::from_le_bytes(take_bytes(&mut position, 8).try_into().unwrap());
tape.push(Tape::Key(key));
tape.push(Tape::Timestamp(value));
}
0x12 => {
let key = take_cstring(&mut position);
let value = i64::from_le_bytes(take_bytes(&mut position, 8).try_into().unwrap());
tape.push(Tape::Key(key));
tape.push(Tape::I64(value));
}
_ => {}
};
}
}
#[cfg(test)]
mod test {
#[test]
fn deserialize() {
let f = std::fs::read("test/test.bin").unwrap();
let bump = bumpalo::Bump::new();
let mut tape = bumpalo::collections::Vec::new_in(&bump);
super::to_tape(&f, &mut tape);
insta::assert_debug_snapshot!(tape);
}
}
@@ -1,4 +1,5 @@
mod byte;
pub mod de;
mod error;
pub mod ser;
@@ -29,11 +30,11 @@
mod test {
use super::{serialised_size_of, to_string};
use bytes::{BufMut, BytesMut};
use serde::Serialize;
use serde::{Deserialize, Serialize};
#[test]
pub fn test_basic() {
#[derive(Serialize)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct A<'a> {
cool: i32,
#[serde(with = "serde_bytes")]
@@ -42,7 +43,7 @@
b: B<'a>,
}
#[derive(Serialize)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub enum Test {
Abc,
Def(i32),
@@ -50,10 +51,10 @@
Jkl { a: i32, b: i32 },
}
#[derive(Serialize)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Tup(i32, i32);
#[derive(Serialize)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct B<'a> {
s: &'a str,
a: Vec<&'a str>,
@@ -98,5 +99,8 @@
let calculated_size = serialised_size_of(&test).unwrap();
assert_eq!(calculated_size, ours.len());
assert_eq!(calculated_size, theirs.len());
let deserialized: A = crate::de::from_bytes(&ours).unwrap();
assert_eq!(&deserialized, test);
}
}
@@ -106,9 +106,9 @@
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
value.serialize(self)
}
@@ -130,18 +130,18 @@
self.serialize_str(variant)
}
fn serialize_newtype_struct<T: ?Sized>(
fn serialize_newtype_struct<T>(
self,
_name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
@@ -149,7 +149,7 @@
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let mut struct_serializer = self.serialize_struct("", 0)?;
struct_serializer.serialize_field(variant, value)?;
@@ -294,9 +294,9 @@
type Ok = ();
type Error = <Serializer<'a, B> as serde::Serializer>::Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
self.inner.serialize_element(value)
}
@@ -317,9 +317,9 @@
type Ok = ();
type Error = <Serializer<'a, B> as serde::Serializer>::Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
@@ -350,13 +350,9 @@
type Ok = ();
type Error = <Serializer<'a, B> as serde::Serializer>::Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
@@ -386,9 +382,9 @@
type Ok = ();
type Error = <Serializer<'a, B> as serde::Serializer>::Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
self.inner.serialize_element(value)
}
@@ -408,9 +404,9 @@
type Ok = ();
type Error = <Serializer<'a, B> as serde::Serializer>::Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
value.serialize(Serializer {
key: Some(DocumentKey::Int(self.key)),
@@ -435,13 +431,9 @@
type Ok = ();
type Error = <Serializer<'a, B> as serde::Serializer>::Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
value.serialize(Serializer {
key: Some(DocumentKey::Str(key)),
Binary files /dev/null and a/test/test.bin differ
@@ -1,0 +1,207 @@
---
source: src/de.rs
expression: x
---
[
DocumentStart,
Key(
"cool",
),
I32(
999,
),
Key(
"beans",
),
Binary(
[
115,
111,
32,
116,
104,
101,
114,
101,
32,
119,
97,
115,
32,
116,
104,
105,
115,
32,
111,
110,
101,
32,
116,
105,
109,
101,
32,
97,
116,
32,
98,
97,
110,
100,
99,
97,
109,
112,
],
0,
),
Key(
"bro",
),
String(
"the craziest thing happened",
),
Key(
"b",
),
DocumentStart,
Key(
"s",
),
String(
"dddd",
),
Key(
"a",
),
ArrayStart,
Key(
"0",
),
String(
"yooo",
),
Key(
"1",
),
String(
"mayn",
),
DocumentEnd,
Key(
"e",
),
String(
"Abc",
),
Key(
"e2",
),
DocumentStart,
Key(
"Def",
),
I32(
1999,
),
DocumentEnd,
Key(
"e3",
),
DocumentStart,
Key(
"Ghi",
),
ArrayStart,
Key(
"0",
),
I32(
16,
),
Key(
"1",
),
I32(
7,
),
Key(
"2",
),
I32(
1999,
),
DocumentEnd,
DocumentEnd,
Key(
"e4",
),
DocumentStart,
Key(
"Jkl",
),
DocumentStart,
Key(
"a",
),
I32(
16,
),
Key(
"b",
),
I32(
7,
),
DocumentEnd,
DocumentEnd,
Key(
"t",
),
ArrayStart,
Key(
"0",
),
I32(
16,
),
Key(
"1",
),
I32(
7,
),
Key(
"2",
),
I32(
1999,
),
DocumentEnd,
Key(
"ts",
),
ArrayStart,
Key(
"0",
),
I32(
99,
),
Key(
"1",
),
I32(
100,
),
DocumentEnd,
Key(
"y",
),
Boolean(
false,
),
DocumentEnd,
DocumentEnd,
]