#![deny(missing_docs)]
#![no_std]
extern crate alloc;
#[cfg(test)]
extern crate std;
use core::{borrow::Borrow, fmt};
use alloc::{boxed::Box, string::String, vec::Vec};
use serde_core::Serialize;
mod de;
mod raw;
mod ser;
use self::raw::{Leaf, PartBuf};
pub use self::{de::Deserializer, ser::Serializer};
#[derive(Debug)]
pub struct Error(#[allow(dead_code)] String);
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "error buffering a value")
}
}
impl serde_core::ser::StdError for Error {}
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(PartialEq))]
pub struct Owned(PartBuf<'static, Box<[u8]>>);
impl From<Ref<'static>> for Owned {
fn from(value: Ref<'static>) -> Self {
Owned(value.into_value().into_boxed_slice())
}
}
impl Owned {
pub fn buffer(v: impl Serialize) -> Result<Self, Error> {
v.serialize(Serializer::new())
}
}
#[derive(Clone, Debug)]
pub struct Ref<'a>(RefValue<'a>);
#[derive(Clone)]
enum RefValue<'a> {
Leaf(Leaf<'a>),
Value(PartBuf<'a, Vec<u8>>),
}
impl<'a> fmt::Debug for RefValue<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RefValue::Leaf(leaf) => leaf.fmt(f),
RefValue::Value(value) => value.fmt(f),
}
}
}
#[cfg(test)]
impl<'a> PartialEq for Ref<'a> {
fn eq(&self, other: &Self) -> bool {
self.clone().into_value() == other.clone().into_value()
}
}
impl From<Owned> for Ref<'static> {
fn from(value: Owned) -> Self {
Ref(RefValue::Value(value.0.into_vec()))
}
}
impl Ref<'static> {
pub fn buffer(v: impl Serialize) -> Result<Self, Error> {
Ok(v.serialize(Serializer::new())?.into())
}
}
impl<'a> Ref<'a> {
fn encode_into(self, value: &mut PartBuf<'a, Vec<u8>>) {
match self.0 {
RefValue::Leaf(leaf) => leaf.encode_into(value),
RefValue::Value(v) => value.extend_value(&v),
}
}
fn into_value(self) -> PartBuf<'a, Vec<u8>> {
match self.0 {
RefValue::Leaf(leaf) => leaf.into_value(),
RefValue::Value(v) => v,
}
}
pub fn unit() -> Self {
Ref(RefValue::Leaf(Leaf::Unit))
}
pub fn bool(v: bool) -> Self {
Ref(RefValue::Leaf(Leaf::Bool(v)))
}
pub fn u8(v: u8) -> Self {
Ref(RefValue::Leaf(Leaf::U8(v)))
}
pub fn u16(v: u16) -> Self {
Ref(RefValue::Leaf(Leaf::U16(v)))
}
pub fn u32(v: u32) -> Self {
Ref(RefValue::Leaf(Leaf::U32(v)))
}
pub fn u64(v: u64) -> Self {
Ref(RefValue::Leaf(Leaf::U64(v)))
}
pub fn u128(v: u128) -> Self {
Ref(RefValue::Leaf(Leaf::U128(v)))
}
pub fn i8(v: i8) -> Self {
Ref(RefValue::Leaf(Leaf::I8(v)))
}
pub fn i16(v: i16) -> Self {
Ref(RefValue::Leaf(Leaf::I16(v)))
}
pub fn i32(v: i32) -> Self {
Ref(RefValue::Leaf(Leaf::I32(v)))
}
pub fn i64(v: i64) -> Self {
Ref(RefValue::Leaf(Leaf::I64(v)))
}
pub fn i128(v: i128) -> Self {
Ref(RefValue::Leaf(Leaf::I128(v)))
}
pub fn f32(v: f32) -> Self {
Ref(RefValue::Leaf(Leaf::F32(v)))
}
pub fn f64(v: f64) -> Self {
Ref(RefValue::Leaf(Leaf::F64(v)))
}
pub fn char(v: char) -> Self {
Ref(RefValue::Leaf(Leaf::Char(v)))
}
pub fn owned_str(v: impl Into<String>) -> Self {
let mut value = PartBuf::new();
value.encode_str(&v.into());
Ref(RefValue::Value(value))
}
pub fn str(v: &'a (impl Borrow<str> + ?Sized)) -> Self {
Ref(RefValue::Leaf(Leaf::Str(v.borrow())))
}
pub fn owned_bytes(v: impl Into<Vec<u8>>) -> Self {
let mut value = PartBuf::new();
value.encode_bytes(&v.into());
Ref(RefValue::Value(value))
}
pub fn bytes(v: &'a (impl Borrow<[u8]> + ?Sized)) -> Self {
Ref(RefValue::Leaf(Leaf::Bytes(v.borrow())))
}
pub fn none() -> Self {
Ref(RefValue::Leaf(Leaf::None))
}
pub fn some(v: impl Into<Ref<'a>>) -> Self {
let mut value = PartBuf::new();
value.encode_some();
v.into().encode_into(&mut value);
Ref(RefValue::Value(value))
}
pub fn unit_struct(name: &'static str) -> Self {
Ref(RefValue::Leaf(Leaf::UnitStruct(name)))
}
pub fn newtype_struct(name: &'static str, v: impl Into<Ref<'a>>) -> Self {
let mut value = PartBuf::new();
value.encode_newtype_struct(name);
v.into().encode_into(&mut value);
Ref(RefValue::Value(value))
}
pub fn record_struct(
name: &'static str,
fields: impl IntoIterator<Item = (&'static str, Ref<'a>)>,
) -> Self {
let mut value = PartBuf::new();
let mut frame = value.begin_struct(name);
for (key, field) in fields {
value.push_field_key(key);
field.encode_into(&mut value);
frame.num += 1;
}
value.end_struct(&frame);
Ref(RefValue::Value(value))
}
pub fn tuple_struct(name: &'static str, fields: impl IntoIterator<Item = Ref<'a>>) -> Self {
let mut value = PartBuf::new();
let mut frame = value.begin_tuple_struct(name);
for field in fields {
field.encode_into(&mut value);
frame.num += 1;
}
value.end_tuple_struct(&frame);
Ref(RefValue::Value(value))
}
pub fn tuple(fields: impl IntoIterator<Item = Ref<'a>>) -> Self {
let mut value = PartBuf::new();
let mut frame = value.begin_tuple();
for field in fields {
field.encode_into(&mut value);
frame.num += 1;
}
value.end_tuple(&frame);
Ref(RefValue::Value(value))
}
pub fn unit_variant(name: &'static str, variant_index: u32, variant: &'static str) -> Self {
Ref(RefValue::Leaf(Leaf::UnitVariant {
name,
variant_index,
variant,
}))
}
pub fn newtype_variant(
name: &'static str,
variant_index: u32,
variant: &'static str,
v: impl Into<Ref<'a>>,
) -> Self {
let mut value = PartBuf::new();
value.encode_newtype_variant(name, variant_index, variant);
v.into().encode_into(&mut value);
Ref(RefValue::Value(value))
}
pub fn tuple_variant(
name: &'static str,
variant_index: u32,
variant: &'static str,
fields: impl IntoIterator<Item = Ref<'a>>,
) -> Self {
let mut value = PartBuf::new();
let mut frame = value.begin_tuple_variant(name, variant_index, variant);
for field in fields {
field.encode_into(&mut value);
frame.num += 1;
}
value.end_tuple_variant(&frame);
Ref(RefValue::Value(value))
}
pub fn record_struct_variant(
name: &'static str,
variant_index: u32,
variant: &'static str,
fields: impl IntoIterator<Item = (&'static str, Ref<'a>)>,
) -> Self {
let mut value = PartBuf::new();
let mut frame = value.begin_struct_variant(name, variant_index, variant);
for (key, field) in fields {
value.push_field_key(key);
field.encode_into(&mut value);
frame.num += 1;
}
value.end_struct_variant(&frame);
Ref(RefValue::Value(value))
}
pub fn seq(fields: impl IntoIterator<Item = Ref<'a>>) -> Self {
let mut value = PartBuf::new();
let mut frame = value.begin_seq();
for field in fields {
field.encode_into(&mut value);
frame.num += 1;
}
value.end_seq(&frame);
Ref(RefValue::Value(value))
}
pub fn map(fields: impl IntoIterator<Item = (Ref<'a>, Ref<'a>)>) -> Self {
let mut value = PartBuf::new();
let mut frame = value.begin_map();
for (key, field) in fields {
key.encode_into(&mut value);
field.encode_into(&mut value);
frame.num += 1;
}
value.end_map(&frame);
Ref(RefValue::Value(value))
}
}
#[cfg(test)]
mod tests {
use core::marker::PhantomData;
use alloc::borrow::{Cow, ToOwned};
use serde_core::{
de::{Deserializer, IntoDeserializer, Visitor},
ser::SerializeMap,
Deserialize, Serialize,
};
use serde_test::Token;
use serde_derive::{Deserialize, Serialize};
use super::*;
#[test]
fn consistency() {
test_case(
Input::new(()),
Input::new(Ref::unit()),
Tokens::new(&[Token::Unit]),
None,
);
test_case(
Input::new(true),
Input::new(Ref::bool(true)),
Tokens::new(&[Token::Bool(true)]),
None,
);
test_case(
Input::new('a'),
Input::new(Ref::char('a')),
Tokens::new(&[Token::Char('a')]),
None,
);
test_case(
Input::new(1u8),
Input::new(Ref::u8(1)),
Tokens::new(&[Token::U8(1)]),
None,
);
test_case(
Input::new(1u16),
Input::new(Ref::u16(1)),
Tokens::new(&[Token::U16(1)]),
None,
);
test_case(
Input::new(1u32),
Input::new(Ref::u32(1)),
Tokens::new(&[Token::U32(1)]),
None,
);
test_case(
Input::new(1u64),
Input::new(Ref::u64(1)),
Tokens::new(&[Token::U64(1)]),
None,
);
test_case(
Input::new(-1i8),
Input::new(Ref::i8(-1)),
Tokens::new(&[Token::I8(-1)]),
None,
);
test_case(
Input::new(-1i16),
Input::new(Ref::i16(-1)),
Tokens::new(&[Token::I16(-1)]),
None,
);
test_case(
Input::new(-1i32),
Input::new(Ref::i32(-1)),
Tokens::new(&[Token::I32(-1)]),
None,
);
test_case(
Input::new(-1i64),
Input::new(Ref::i64(-1)),
Tokens::new(&[Token::I64(-1)]),
None,
);
i128_test_case(1u128, Ref::u128(1));
i128_test_case(-1i128, Ref::i128(-1));
test_case(
Input::new(1f32),
Input::new(Ref::f32(1.0)),
Tokens::new(&[Token::F32(1.0)]),
None,
);
test_case(
Input::new(1f64),
Input::new(Ref::f64(1.0)),
Tokens::new(&[Token::F64(1.0)]),
None,
);
test_case(
Input::new(Str(Cow::Borrowed("a string"))),
Input::new(Ref::str("a string")),
Tokens::new(&[Token::BorrowedStr("a string")]),
Tokens::new(&[Token::Str("a string")]),
);
test_case(
Input::new(Str(Cow::Owned("a string".to_owned()))),
Input::new(Ref::owned_str("a string")),
Tokens::new(&[Token::Str("a string")]),
None,
);
test_case(
Input::new(Bytes(Cow::Borrowed(b"a string"))),
Input::new(Ref::bytes(b"a string")),
Tokens::new(&[Token::BorrowedBytes(b"a string")]),
Tokens::new(&[Token::Bytes(b"a string")]),
);
test_case(
Input::new(Bytes(Cow::Owned(b"a string".to_vec()))),
Input::new(Ref::owned_bytes(b"a string" as &[u8])),
Tokens::new(&[Token::Bytes(b"a string")]),
None,
);
test_case(
Input::new(None::<()>),
Input::new(Ref::none()),
Tokens::new(&[Token::None]),
None,
);
test_case(
Input::new(Some(())),
Input::new(Ref::some(Ref::unit())),
Tokens::new(&[Token::Some, Token::Unit]),
None,
);
test_case(
Input::new(UnitStruct),
Input::new(Ref::unit_struct("UnitStruct")),
Tokens::new(&[Token::UnitStruct { name: "UnitStruct" }]),
None,
);
test_case(
Input::new(Enum::UnitVariant),
Input::new(Ref::unit_variant("Enum", 0, "UnitVariant")),
Tokens::new(&[Token::UnitVariant {
name: "Enum",
variant: "UnitVariant",
}]),
None,
);
test_case(
Input::new(Enum::NewtypeVariant(())),
Input::new(Ref::newtype_variant(
"Enum",
1,
"NewtypeVariant",
Ref::unit(),
)),
Tokens::new(&[
Token::NewtypeVariant {
name: "Enum",
variant: "NewtypeVariant",
},
Token::Unit,
]),
None,
);
test_case(
Input::new(Enum::TupleVariant((), ())),
Input::new(Ref::tuple_variant(
"Enum",
2,
"TupleVariant",
alloc::vec![Ref::unit(), Ref::unit()],
)),
Tokens::new(&[
Token::TupleVariant {
name: "Enum",
variant: "TupleVariant",
len: 2,
},
Token::Unit,
Token::Unit,
Token::TupleVariantEnd,
]),
None,
);
test_case(
Input::new(Enum::StructVariant { a: (), b: () }),
Input::new(Ref::record_struct_variant(
"Enum",
3,
"StructVariant",
alloc::vec![("a", Ref::unit()), ("b", Ref::unit())],
)),
Tokens::new(&[
Token::StructVariant {
name: "Enum",
variant: "StructVariant",
len: 2,
},
Token::Str("a"),
Token::Unit,
Token::Str("b"),
Token::Unit,
Token::StructVariantEnd,
]),
None,
);
test_case(
Input::new(((), ())),
Input::new(Ref::tuple(alloc::vec![Ref::unit(), Ref::unit()])),
Tokens::new(&[
Token::Tuple { len: 2 },
Token::Unit,
Token::Unit,
Token::TupleEnd,
]),
None,
);
test_case(
Input::new(TupleStruct((), ())),
Input::new(Ref::tuple_struct(
"TupleStruct",
alloc::vec![Ref::unit(), Ref::unit()],
)),
Tokens::new(&[
Token::TupleStruct {
name: "TupleStruct",
len: 2,
},
Token::Unit,
Token::Unit,
Token::TupleStructEnd,
]),
None,
);
test_case(
Input::new(Struct { a: (), b: () }),
Input::new(Ref::record_struct(
"Struct",
alloc::vec![("a", Ref::unit()), ("b", Ref::unit())],
)),
Tokens::new(&[
Token::Struct {
name: "Struct",
len: 2,
},
Token::Str("a"),
Token::Unit,
Token::Str("b"),
Token::Unit,
Token::StructEnd,
]),
None,
);
test_case(
Input::new(NewtypeStruct(())),
Input::new(Ref::newtype_struct("NewtypeStruct", Ref::unit())),
Tokens::new(&[
Token::NewtypeStruct {
name: "NewtypeStruct",
},
Token::Unit,
]),
None,
);
test_case(
Input::new(alloc::vec![(), ()]),
Input::new(Ref::seq(alloc::vec![Ref::unit(), Ref::unit()])),
Tokens::new(&[
Token::Seq { len: Some(2) },
Token::Unit,
Token::Unit,
Token::SeqEnd,
]),
None,
);
test_case(
Input::new(Map(alloc::vec![
(Str(Cow::Borrowed("a")), ()),
(Str(Cow::Borrowed("b")), ())
])),
Input::new(Ref::map(alloc::vec![
(Ref::str("a"), Ref::unit()),
(Ref::str("b"), Ref::unit())
])),
Tokens::new(&[
Token::Map { len: Some(2) },
Token::Str("a"),
Token::Unit,
Token::Str("b"),
Token::Unit,
Token::MapEnd,
]),
None,
);
}
#[test]
fn is_send_sync() {
fn assert<T: Send + Sync>() {}
assert::<Owned>();
assert::<Ref>();
}
#[test]
fn nested() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Nested<'a> {
id: i32,
title: &'a str,
attributes: Vec<(&'a str, Option<i32>)>,
}
let data = Nested {
id: 42,
title: "A very important document",
attributes: alloc::vec![("#1", None), ("#2", Some(3))],
};
let buffered = Owned::buffer(&data).unwrap();
let built = Ref::record_struct(
"Nested",
[
("id", Ref::i32(data.id)),
("title", Ref::str(data.title)),
(
"attributes",
Ref::seq(data.attributes.iter().map(|(k, v)| {
Ref::tuple([
Ref::str(*k),
match v {
Some(v) => Ref::some(Ref::i32(*v)),
None => Ref::none(),
},
])
})),
),
],
);
let expected = serde_json::to_string(&data).unwrap();
assert_eq!(expected, serde_json::to_string(&buffered).unwrap());
assert_eq!(expected, serde_json::to_string(&built).unwrap());
#[derive(Deserialize, PartialEq, Debug)]
struct NestedOwned {
id: i32,
title: String,
attributes: Vec<(String, Option<i32>)>,
}
let from_buffered = NestedOwned::deserialize(buffered.into_deserializer()).unwrap();
assert_eq!(expected, serde_json::to_string(&data).unwrap());
assert_eq!(42, from_buffered.id);
assert_eq!(data.title, from_buffered.title);
let from_built = Nested::deserialize(built.into_deserializer()).unwrap();
assert_eq!(data, from_built);
}
#[test]
fn deserialize_borrowed_is_zero_copy() {
let buffer = Ref::tuple([Ref::str("borrowed"), Ref::bytes(b"borrowed")]);
let (s, b) = <(Str, Bytes)>::deserialize(buffer.into_deserializer()).unwrap();
assert!(matches!(s.0, Cow::Borrowed(_)));
assert!(matches!(b.0, Cow::Borrowed(_)));
let buffer = Ref::owned_str("owned");
let s = Str::deserialize(buffer.into_deserializer()).unwrap();
assert!(matches!(s.0, Cow::Owned(_)));
}
#[test]
fn deserialize_partial_consumption() {
struct FirstElement;
impl<'de> Visitor<'de> for FirstElement {
type Value = i32;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "a sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde_core::de::SeqAccess<'de>,
{
Ok(seq.next_element()?.unwrap())
}
}
struct FirstKey;
impl<'de> Visitor<'de> for FirstKey {
type Value = String;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "a map")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde_core::de::MapAccess<'de>,
{
Ok(map.next_key::<String>()?.unwrap())
}
}
let buffer = Ref::tuple([
Ref::seq([Ref::i32(1), Ref::i32(2), Ref::i32(3)]),
Ref::str("next"),
]);
struct Outer;
impl<'de> Visitor<'de> for Outer {
type Value = (i32, String);
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "a sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde_core::de::SeqAccess<'de>,
{
struct First(FirstElement);
impl<'de> serde_core::de::DeserializeSeed<'de> for First {
type Value = i32;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self.0)
}
}
let first = seq.next_element_seed(First(FirstElement))?.unwrap();
let next = seq.next_element::<String>()?.unwrap();
Ok((first, next))
}
}
struct OuterSeed;
impl<'de> serde_core::de::DeserializeSeed<'de> for OuterSeed {
type Value = (i32, String);
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(Outer)
}
}
use serde_core::de::DeserializeSeed as _;
let (first, next) = OuterSeed.deserialize(buffer.into_deserializer()).unwrap();
assert_eq!(1, first);
assert_eq!("next", next);
let buffer = Ref::tuple([
Ref::map([
(Ref::owned_str("a"), Ref::i32(1)),
(Ref::owned_str("b"), Ref::i32(2)),
]),
Ref::str("next"),
]);
struct OuterMap;
impl<'de> Visitor<'de> for OuterMap {
type Value = (String, String);
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "a sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde_core::de::SeqAccess<'de>,
{
struct First(FirstKey);
impl<'de> serde_core::de::DeserializeSeed<'de> for First {
type Value = String;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self.0)
}
}
let first = seq.next_element_seed(First(FirstKey))?.unwrap();
let next = seq.next_element::<String>()?.unwrap();
Ok((first, next))
}
}
struct OuterMapSeed;
impl<'de> serde_core::de::DeserializeSeed<'de> for OuterMapSeed {
type Value = (String, String);
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(OuterMap)
}
}
let (first, next) = OuterMapSeed
.deserialize(buffer.into_deserializer())
.unwrap();
assert_eq!("a", first);
assert_eq!("next", next);
}
#[test]
fn deserialize_partial_variant_consumption() {
use serde_core::de::{DeserializeSeed, EnumAccess, VariantAccess};
struct FirstVariantField;
impl<'de> Visitor<'de> for FirstVariantField {
type Value = i32;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "an enum")
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
struct First;
impl<'de> Visitor<'de> for First {
type Value = i32;
fn expecting(
&self,
formatter: &mut alloc::fmt::Formatter,
) -> alloc::fmt::Result {
write!(formatter, "a tuple variant")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde_core::de::SeqAccess<'de>,
{
Ok(seq.next_element()?.unwrap())
}
}
let (_, variant) = data.variant::<u32>()?;
variant.tuple_variant(3, First)
}
}
struct Outer;
impl<'de> Visitor<'de> for Outer {
type Value = (i32, String);
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "a sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde_core::de::SeqAccess<'de>,
{
struct First;
impl<'de> DeserializeSeed<'de> for First {
type Value = i32;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(FirstVariantField)
}
}
let first = seq.next_element_seed(First)?.unwrap();
let next = seq.next_element::<String>()?.unwrap();
Ok((first, next))
}
}
struct OuterSeed;
impl<'de> DeserializeSeed<'de> for OuterSeed {
type Value = (i32, String);
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(Outer)
}
}
let buffer = Ref::tuple([
Ref::tuple_variant(
"Enum",
0,
"TupleVariant",
[Ref::i32(1), Ref::i32(2), Ref::i32(3)],
),
Ref::str("next"),
]);
let (first, next) = OuterSeed.deserialize(buffer.into_deserializer()).unwrap();
assert_eq!(1, first);
assert_eq!("next", next);
}
#[test]
fn roundtrip_shapes() {
use alloc::{collections::BTreeMap, string::ToString, vec::Vec};
fn assert_roundtrip<T>(v: T)
where
T: Serialize + serde_core::de::DeserializeOwned + PartialEq + fmt::Debug,
{
let buffered = Owned::buffer(&v).unwrap();
let deserialized = T::deserialize(buffered.clone().into_deserializer()).unwrap();
assert_eq!(v, deserialized);
let as_ref: Ref<'static> = buffered.into();
let deserialized = T::deserialize(as_ref.into_deserializer()).unwrap();
assert_eq!(v, deserialized);
}
assert_roundtrip(());
assert_roundtrip(true);
assert_roundtrip(u8::MAX);
assert_roundtrip(u16::MAX);
assert_roundtrip(u32::MAX);
assert_roundtrip(u64::MAX);
assert_roundtrip(i8::MIN);
assert_roundtrip(i16::MIN);
assert_roundtrip(i32::MIN);
assert_roundtrip(i64::MIN);
assert_roundtrip(f32::MIN_POSITIVE);
assert_roundtrip(2.0f64.powi(60));
assert_roundtrip('a');
assert_roundtrip('é');
assert_roundtrip('🦀');
assert_roundtrip(String::new());
assert_roundtrip("text".to_string());
assert_roundtrip("ünïcödé 🦀".to_string());
assert_roundtrip(None::<i32>);
assert_roundtrip(Some(42i32));
assert_roundtrip(Some(None::<i32>));
assert_roundtrip(Some(Some(42i32)));
assert_roundtrip(Some("text".to_string()));
assert_roundtrip(Vec::<i32>::new());
assert_roundtrip(alloc::vec![1i32, 2, 3]);
assert_roundtrip(alloc::vec![
alloc::vec![1i32],
Vec::new(),
alloc::vec![2, 3]
]);
assert_roundtrip((1u8, -1i64, "text".to_string(), 3.5f64));
assert_roundtrip(((1u8, 2u16), (3u32, (4u64, ()))));
assert_roundtrip(BTreeMap::<String, i32>::new());
assert_roundtrip(BTreeMap::from_iter([
("a".to_string(), 1i32),
("b".to_string(), 2),
]));
assert_roundtrip(BTreeMap::from_iter([(7u32, "x".to_string())]));
assert_roundtrip(BTreeMap::from_iter([((1u8, 2u8), 3u8)]));
assert_roundtrip(BTreeMap::from_iter([(
"outer".to_string(),
BTreeMap::from_iter([("inner".to_string(), alloc::vec![1i32])]),
)]));
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Empty {}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Fields {
id: u64,
name: String,
tags: Vec<String>,
opt: Option<f64>,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Newtype(Fields);
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Pair(i32, String);
let fields = || Fields {
id: 42,
name: "a name".to_string(),
tags: alloc::vec!["x".to_string(), "y".to_string()],
opt: Some(1.5),
};
assert_roundtrip(UnitStruct);
assert_roundtrip(Empty {});
assert_roundtrip(fields());
assert_roundtrip(Newtype(fields()));
assert_roundtrip(Pair(-1, "pair".to_string()));
assert_roundtrip(Some(Newtype(fields())));
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum Shape {
Unit,
Newtype(i32),
NewtypeSeq(Vec<i32>),
NewtypeStruct(Fields),
Tuple(i32, String),
Struct { a: i32, b: String },
}
assert_roundtrip(Shape::Unit);
assert_roundtrip(Shape::Newtype(42));
assert_roundtrip(Shape::NewtypeSeq(alloc::vec![1, 2, 3]));
assert_roundtrip(Shape::NewtypeStruct(fields()));
assert_roundtrip(Shape::Tuple(1, "tuple".to_string()));
assert_roundtrip(Shape::Struct {
a: 1,
b: "struct".to_string(),
});
assert_roundtrip(alloc::vec![
Shape::Unit,
Shape::Newtype(1),
Shape::Struct {
a: 2,
b: "nested".to_string(),
},
]);
assert_roundtrip(BTreeMap::from_iter([(
"shape".to_string(),
Shape::Tuple(3, "in a map".to_string()),
)]));
assert_roundtrip("x".repeat(10 * 1024));
assert_roundtrip((0..10_000u64).collect::<Vec<_>>());
assert_roundtrip(alloc::vec![fields(), fields(), fields()]);
}
#[test]
fn deep_some_nesting() {
struct DeepSome(usize);
impl Serialize for DeepSome {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
if self.0 == 0 {
serializer.serialize_i32(42)
} else {
serializer.serialize_some(&DeepSome(self.0 - 1))
}
}
}
let buffer = Owned::buffer(&(DeepSome(64), "next")).unwrap();
assert_eq!("[42,\"next\"]", serde_json::to_string(&buffer).unwrap());
let (v, next) =
<(Option<Option<Option<serde_core::de::IgnoredAny>>>, String)>::deserialize(
buffer.into_deserializer(),
)
.unwrap();
assert!(v.is_some());
assert_eq!("next", next);
}
#[test]
fn clone_outlives_the_original() {
let original = Owned::buffer(&alloc::vec!["one".to_owned(), "two".to_owned()]).unwrap();
let clone = original.clone();
drop(original);
assert_eq!("[\"one\",\"two\"]", serde_json::to_string(&clone).unwrap());
let v = Vec::<String>::deserialize(clone.into_deserializer()).unwrap();
assert_eq!(alloc::vec!["one".to_owned(), "two".to_owned()], v);
let text = "borrowed text".to_owned();
let bytes = alloc::vec![1u8, 2, 3];
let original = Ref::record_struct(
"Data",
[
("text", Ref::str(&text)),
("bytes", Ref::bytes(&*bytes)),
("owned", Ref::owned_str("inline")),
],
);
let clone1 = original.clone();
let clone2 = clone1.clone();
drop(original);
drop(clone1);
assert_eq!(
"{\"text\":\"borrowed text\",\"bytes\":[1,2,3],\"owned\":\"inline\"}",
serde_json::to_string(&clone2).unwrap()
);
}
#[test]
fn convert_between_ref_and_owned() {
let leaf = Ref::str("static text");
let owned: Owned = leaf.into();
assert_eq!("\"static text\"", serde_json::to_string(&owned).unwrap());
let built = Ref::record_struct(
"Data",
[
("borrowed", Ref::str("static str")),
("owned", Ref::owned_str("inline string")),
("nested", Ref::tuple([Ref::u64(1), Ref::none()])),
],
);
let expected = serde_json::to_string(&built).unwrap();
let owned: Owned = built.into();
assert_eq!(expected, serde_json::to_string(&owned).unwrap());
let back: Ref<'static> = owned.clone().into();
assert_eq!(expected, serde_json::to_string(&back).unwrap());
#[derive(Deserialize, PartialEq, Debug)]
struct Data {
borrowed: String,
owned: String,
nested: (u64, Option<()>),
}
let data = Data::deserialize(owned.into_deserializer()).unwrap();
assert_eq!(
Data {
borrowed: "static str".to_owned(),
owned: "inline string".to_owned(),
nested: (1, None),
},
data
);
}
struct FailsWithoutWriting;
impl Serialize for FailsWithoutWriting {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
use serde_core::ser::Error as _;
Err(S::Error::custom("deliberate failure"))
}
}
#[test]
fn misbehaving_serialize_cannot_corrupt_the_buffer() {
use serde_core::ser::{Error as _, SerializeSeq, SerializeStruct};
struct AbandonsSeq;
impl Serialize for AbandonsSeq {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
let mut seq = serializer.serialize_seq(Some(2))?;
seq.serialize_element(&1i32)?;
Err(S::Error::custom("deliberate failure"))
}
}
struct Swallows<T>(T);
impl<T: Serialize> Serialize for Swallows<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element(&1i32)?;
let _swallowed = seq.serialize_element(&self.0);
seq.serialize_element(&2i32)?;
seq.end()
}
}
assert!(Owned::buffer(&Swallows(FailsWithoutWriting)).is_err());
assert!(Owned::buffer(&Swallows(AbandonsSeq)).is_err());
assert!(Owned::buffer(&alloc::vec![Swallows(FailsWithoutWriting)]).is_err());
assert!(Owned::buffer(&Some(Swallows(AbandonsSeq))).is_err());
struct SwallowsField;
impl Serialize for SwallowsField {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
let mut s = serializer.serialize_struct("SwallowsField", 2)?;
s.serialize_field("a", &1i32)?;
let _swallowed = s.serialize_field("b", &FailsWithoutWriting);
s.end()
}
}
assert!(Owned::buffer(&SwallowsField).is_err());
assert!(Owned::buffer(&alloc::vec![SwallowsField]).is_err());
struct SwallowsMapValue;
impl Serialize for SwallowsMapValue {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
let mut m = serializer.serialize_map(None)?;
m.serialize_key("k")?;
let _swallowed = m.serialize_value(&FailsWithoutWriting);
m.serialize_key("k2")?;
m.serialize_value(&2i32)?;
m.end()
}
}
assert!(Owned::buffer(&SwallowsMapValue).is_err());
}
#[test]
fn reusing_a_failed_serializer_still_errors() {
use serde_core::ser::SerializeSeq;
use serde_core::Serializer as _;
let mut seq = Serializer::new().serialize_seq(None).unwrap();
seq.serialize_element(&1i32).unwrap();
assert!(seq.serialize_element(&FailsWithoutWriting).is_err());
seq.serialize_element(&2i32).unwrap();
assert!(SerializeSeq::end(seq).is_err());
}
#[test]
fn panicking_serialize_cannot_corrupt_the_buffer() {
use serde_core::ser::SerializeStruct;
use serde_core::Serializer as _;
use std::panic::{catch_unwind, AssertUnwindSafe};
struct PanicsWithoutWriting;
impl Serialize for PanicsWithoutWriting {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
panic!("deliberate panic")
}
}
let mut s = Serializer::new().serialize_struct("Struct", 3).unwrap();
s.serialize_field("a", &1i32).unwrap();
assert!(catch_unwind(AssertUnwindSafe(
|| s.serialize_field("b", &PanicsWithoutWriting)
))
.is_err());
s.serialize_field("c", &2i32).unwrap();
assert!(SerializeStruct::end(s).is_err());
use serde_core::ser::SerializeSeq;
let mut seq = Serializer::new().serialize_seq(None).unwrap();
seq.serialize_element(&1i32).unwrap();
assert!(catch_unwind(AssertUnwindSafe(
|| seq.serialize_element(&PanicsWithoutWriting)
))
.is_err());
seq.serialize_element(&2i32).unwrap();
assert!(SerializeSeq::end(seq).is_err());
struct CatchesPanickingElement;
impl Serialize for CatchesPanickingElement {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
let mut seq = serializer.serialize_seq(Some(2))?;
seq.serialize_element(&1i32)?;
let _ = catch_unwind(AssertUnwindSafe(|| {
seq.serialize_element(&PanicsWithoutWriting)
}));
seq.end()
}
}
assert!(Owned::buffer(&CatchesPanickingElement).is_err());
assert!(Owned::buffer(&alloc::vec![CatchesPanickingElement]).is_err());
}
#[test]
fn panicking_visitor_cannot_desync_the_buffer() {
use serde_core::de::{DeserializeSeed, MapAccess, SeqAccess};
use std::panic::{catch_unwind, AssertUnwindSafe};
struct PanicsMidSeq;
impl<'de> DeserializeSeed<'de> for PanicsMidSeq {
type Value = ();
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<(), D::Error> {
struct V;
impl<'de> Visitor<'de> for V {
type Value = ();
fn expecting(&self, f: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(f, "a sequence")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<(), A::Error> {
let _ = seq.next_element::<i32>()?;
panic!("deliberate panic")
}
}
deserializer.deserialize_any(V)
}
}
let buffer = Ref::record_struct(
"Struct",
[
("a", Ref::seq([Ref::i32(1), Ref::i32(2), Ref::i32(3)])),
("b", Ref::str("text")),
],
);
struct Outer;
impl<'de> Visitor<'de> for Outer {
type Value = alloc::string::String;
fn expecting(&self, f: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(f, "a struct")
}
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
let _key = map.next_key::<alloc::string::String>()?.unwrap();
assert!(
catch_unwind(AssertUnwindSafe(|| map.next_value_seed(PanicsMidSeq))).is_err()
);
let key = map.next_key::<alloc::string::String>()?.unwrap();
assert_eq!("b", key);
let value: alloc::string::String = map.next_value()?;
assert_eq!("text", value);
Ok(value)
}
}
struct OuterSeed;
impl<'de> DeserializeSeed<'de> for OuterSeed {
type Value = alloc::string::String;
fn deserialize<D: Deserializer<'de>>(
self,
deserializer: D,
) -> Result<Self::Value, D::Error> {
deserializer.deserialize_any(Outer)
}
}
let value = OuterSeed.deserialize(buffer.into_deserializer()).unwrap();
assert_eq!("text", value);
}
#[test]
fn debug() {
use alloc::format;
let buffer = Ref::record_struct(
"Data",
[
("id", Ref::i32(42)),
("title", Ref::str("a document")),
("tags", Ref::seq([Ref::owned_str("a"), Ref::owned_str("b")])),
("removed", Ref::some(Ref::bool(true))),
],
);
assert_eq!(
"Ref(Data { id: 42, title: \"a document\", tags: [\"a\", \"b\"], removed: Some(true) })",
format!("{:?}", buffer)
);
}
#[derive(Debug, Clone, Copy, PartialEq)]
struct Input<S> {
value: S,
}
type Tokens<'de> = Input<&'de [Token]>;
impl<S> Input<S> {
fn new(value: S) -> Self {
Input { value }
}
}
fn test_case<'de, S: Serialize + Deserialize<'de> + PartialEq + fmt::Debug + Clone>(
t: Input<S>,
ref_buf: Input<Ref<'de>>,
ref_tokens: Tokens<'de>,
owned_tokens: impl Into<Option<Tokens<'de>>>,
) {
let owned_tokens: Tokens<'de> = owned_tokens.into().unwrap_or(ref_tokens);
serde_test::assert_ser_tokens(&t.value, ref_tokens.value);
let t_to_owned = Input {
value: t.value.serialize(Serializer::new()).unwrap(),
};
serde_test::assert_ser_tokens(&ref_buf.value, ref_tokens.value);
serde_test::assert_ser_tokens(&t_to_owned.value, owned_tokens.value);
let ref_to_t = Input {
value: S::deserialize(ref_buf.value.into_deserializer()).unwrap(),
};
let owned_to_t = Input {
value: S::deserialize(t_to_owned.value.into_deserializer()).unwrap(),
};
assert_eq!(t, ref_to_t);
assert_eq!(t, owned_to_t);
}
fn i128_test_case<'de, T: Serialize + Deserialize<'de> + PartialEq + fmt::Debug>(
v: T,
ref_buf: Ref<'de>,
) {
let t_to_owned = v.serialize(Serializer::new()).unwrap();
assert_eq!(ref_buf, Ref::from(t_to_owned.clone()));
let owned_to_t = T::deserialize(t_to_owned.into_deserializer()).unwrap();
assert_eq!(v, owned_to_t);
}
#[derive(Debug, PartialEq, Clone)]
struct Str<'a>(Cow<'a, str>);
impl<'a> Serialize for Str<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
serializer.serialize_str(&self.0)
}
}
impl<'de> Deserialize<'de> for Str<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde_core::Deserializer<'de>,
{
let v = deserializer.deserialize_str(StrVisitor(PhantomData))?;
Ok(Str(v))
}
}
struct StrVisitor<'de>(PhantomData<Cow<'de, str>>);
impl<'de> Visitor<'de> for StrVisitor<'de> {
type Value = Cow<'de, str>;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "a string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde_core::de::Error,
{
Ok(Cow::Owned(v.to_owned()))
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde_core::de::Error,
{
Ok(Cow::Owned(v))
}
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: serde_core::de::Error,
{
Ok(Cow::Borrowed(v))
}
}
#[derive(Debug, PartialEq, Clone)]
struct Bytes<'a>(Cow<'a, [u8]>);
impl<'a> Serialize for Bytes<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
serializer.serialize_bytes(&self.0)
}
}
impl<'de> Deserialize<'de> for Bytes<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde_core::Deserializer<'de>,
{
let v = deserializer.deserialize_bytes(BytesVisitor(PhantomData))?;
Ok(Bytes(v))
}
}
struct BytesVisitor<'de>(PhantomData<Cow<'de, [u8]>>);
impl<'de> Visitor<'de> for BytesVisitor<'de> {
type Value = Cow<'de, [u8]>;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "a byte string")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: serde_core::de::Error,
{
Ok(Cow::Owned(v.to_owned()))
}
fn visit_byte_buf<E>(self, v: alloc::vec::Vec<u8>) -> Result<Self::Value, E>
where
E: serde_core::de::Error,
{
Ok(Cow::Owned(v))
}
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
where
E: serde_core::de::Error,
{
Ok(Cow::Borrowed(v))
}
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
struct UnitStruct;
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
struct TupleStruct((), ());
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
struct Struct {
a: (),
b: (),
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
struct NewtypeStruct(());
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
enum Enum {
UnitVariant,
NewtypeVariant(()),
TupleVariant((), ()),
StructVariant { a: (), b: () },
}
#[derive(PartialEq, Clone, Debug)]
struct Map<'a>(Vec<(Str<'a>, ())>);
impl<'a> Serialize for Map<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
let mut serializer = serializer.serialize_map(Some(self.0.len()))?;
for (k, v) in &*self.0 {
serializer.serialize_key(k)?;
serializer.serialize_value(v)?;
}
serializer.end()
}
}
impl<'de> Deserialize<'de> for Map<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(MapVisitor(PhantomData))
}
}
struct MapVisitor<'de>(PhantomData<Map<'de>>);
impl<'de> Visitor<'de> for MapVisitor<'de> {
type Value = Map<'de>;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
write!(formatter, "a map")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde_core::de::MapAccess<'de>,
{
let mut de = Vec::new();
while let Some(k) = map.next_key()? {
let v = map.next_value()?;
de.push((k, v));
}
Ok(Map(de))
}
}
}