From aa750d2bf31e64370cfee5a2bed6bdcdf9b2a0ca Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 19 Apr 2017 14:12:56 -0700 Subject: [PATCH] Examples of every token --- serde_test/src/ser.rs | 96 ++++++--- serde_test/src/token.rs | 452 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 493 insertions(+), 55 deletions(-) diff --git a/serde_test/src/ser.rs b/serde_test/src/ser.rs index e8679e64..261d3215 100644 --- a/serde_test/src/ser.rs +++ b/serde_test/src/ser.rs @@ -24,7 +24,7 @@ impl<'a> Serializer<'a> { } /// Pulls the next token off of the serializer, ignoring it. - pub fn next_token(&mut self) -> Option { + fn next_token(&mut self) -> Option { if let Some((&first, rest)) = self.tokens.split_first() { self.tokens = rest; Some(first) @@ -39,27 +39,26 @@ impl<'a> Serializer<'a> { } macro_rules! assert_next_token { - ($ser:ident, $expected:ident) => { - assert_next_token!($ser, Token::$expected, true); + ($ser:expr, $expected:ident) => { + assert_next_token!($ser, $expected, Token::$expected, true); }; - ($ser:ident, $expected:ident($v:expr)) => { - assert_next_token!($ser, Token::$expected(v), v == $v); + ($ser:expr, $expected:ident($v:expr)) => { + assert_next_token!($ser, $expected, Token::$expected(v), v == $v); }; - ($ser:ident, $expected:ident { $($k:ident),* }) => { + ($ser:expr, $expected:ident { $($k:ident),* }) => { let compare = ($($k,)*); - assert_next_token!($ser, Token::$expected { $($k),* }, ($($k,)*) == compare); + assert_next_token!($ser, $expected, Token::$expected { $($k),* }, ($($k,)*) == compare); }; - ($ser:ident, $pat:pat, $guard:expr) => { + ($ser:expr, $expected:ident, $pat:pat, $guard:expr) => { match $ser.next_token() { Some($pat) if $guard => {} - //Some(Token::$expected $(($($n),*))*) $(if $($n == $v)&&*)* => {} Some(other) => { - panic!("expected Token::{} but serialized as {:?}", - stringify!($pat), other); + panic!("expected Token::{} but serialized as {}", + stringify!($expected), other); } None => { panic!("expected Token::{} after end of serialized tokens", - stringify!($pat)); + stringify!($expected)); } } }; @@ -72,10 +71,10 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> { type SerializeSeq = Self; type SerializeTuple = Self; type SerializeTupleStruct = Self; - type SerializeTupleVariant = Self; + type SerializeTupleVariant = Variant<'s, 'a>; type SerializeMap = Self; type SerializeStruct = Self; - type SerializeStructVariant = Self; + type SerializeStructVariant = Variant<'s, 'a>; fn serialize_bool(self, v: bool) -> Result<(), Error> { assert_next_token!(self, Bool(v)); @@ -138,12 +137,20 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> { } fn serialize_str(self, v: &str) -> Result<(), Error> { - assert_next_token!(self, Str(v)); + match self.tokens.first() { + Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)), + Some(&Token::String(_)) => assert_next_token!(self, String(v)), + _ => assert_next_token!(self, Str(v)), + } Ok(()) } - fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> { - assert_next_token!(self, Bytes(value)); + fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> { + match self.tokens.first() { + Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)), + Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)), + _ => assert_next_token!(self, Bytes(v)), + } Ok(()) } @@ -234,9 +241,17 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> { _variant_index: u32, variant: &'static str, len: usize, - ) -> Result { - assert_next_token!(self, TupleVariant { name, variant, len }); - Ok(self) + ) -> Result { + if self.tokens.first() == Some(&Token::Enum { name }) { + self.next_token(); + assert_next_token!(self, Str(variant)); + let len = Some(len); + assert_next_token!(self, Seq { len }); + Ok(Variant { ser: self, end: Token::SeqEnd }) + } else { + assert_next_token!(self, TupleVariant { name, variant, len }); + Ok(Variant { ser: self, end: Token::TupleVariantEnd }) + } } fn serialize_map(self, len: Option) -> Result { @@ -255,12 +270,25 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> { _variant_index: u32, variant: &'static str, len: usize, - ) -> Result { - assert_next_token!(self, StructVariant { name, variant, len }); - Ok(self) + ) -> Result { + if self.tokens.first() == Some(&Token::Enum { name }) { + self.next_token(); + assert_next_token!(self, Str(variant)); + let len = Some(len); + assert_next_token!(self, Map { len }); + Ok(Variant { ser: self, end: Token::MapEnd }) + } else { + assert_next_token!(self, StructVariant { name, variant, len }); + Ok(Variant { ser: self, end: Token::StructVariantEnd }) + } } } +pub struct Variant<'s, 'a: 's> { + ser: &'s mut Serializer<'a>, + end: Token, +} + impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> { type Ok = (); type Error = Error; @@ -312,7 +340,7 @@ impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> { } } -impl<'s, 'a> ser::SerializeTupleVariant for &'s mut Serializer<'a> { +impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> { type Ok = (); type Error = Error; @@ -320,11 +348,15 @@ impl<'s, 'a> ser::SerializeTupleVariant for &'s mut Serializer<'a> { where T: Serialize, { - value.serialize(&mut **self) + value.serialize(&mut *self.ser) } fn end(self) -> Result<(), Error> { - assert_next_token!(self, TupleVariantEnd); + match self.end { + Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd), + Token::SeqEnd => assert_next_token!(self.ser, SeqEnd), + _ => unreachable!(), + } Ok(()) } } @@ -375,7 +407,7 @@ impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> { } } -impl<'s, 'a> ser::SerializeStructVariant for &'s mut Serializer<'a> { +impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> { type Ok = (); type Error = Error; @@ -387,12 +419,16 @@ impl<'s, 'a> ser::SerializeStructVariant for &'s mut Serializer<'a> { where T: Serialize, { - try!(key.serialize(&mut **self)); - value.serialize(&mut **self) + try!(key.serialize(&mut *self.ser)); + value.serialize(&mut *self.ser) } fn end(self) -> Result<(), Self::Error> { - assert_next_token!(self, StructVariantEnd); + match self.end { + Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd), + Token::MapEnd => assert_next_token!(self.ser, MapEnd), + _ => unreachable!(), + } Ok(()) } } diff --git a/serde_test/src/token.rs b/serde_test/src/token.rs index 4a5a32c9..ebae739b 100644 --- a/serde_test/src/token.rs +++ b/serde_test/src/token.rs @@ -11,48 +11,141 @@ use std::fmt::{self, Debug, Display}; #[derive(Copy, Clone, PartialEq, Debug)] pub enum Token { /// A serialized `bool`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&true, &[Token::Bool(true)]); + /// ``` Bool(bool), /// A serialized `i8`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0i8, &[Token::I8(0)]); + /// ``` I8(i8), /// A serialized `i16`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0i16, &[Token::I16(0)]); + /// ``` I16(i16), /// A serialized `i32`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0i32, &[Token::I32(0)]); + /// ``` I32(i32), /// A serialized `i64`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0i64, &[Token::I64(0)]); + /// ``` I64(i64), /// A serialized `u8`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0u8, &[Token::U8(0)]); + /// ``` U8(u8), /// A serialized `u16`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0u16, &[Token::U16(0)]); + /// ``` U16(u16), /// A serialized `u32`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0u32, &[Token::U32(0)]); + /// ``` U32(u32), /// A serialized `u64`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0u64, &[Token::U64(0)]); + /// ``` U64(u64), /// A serialized `f32`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0f32, &[Token::F32(0.0)]); + /// ``` F32(f32), /// A serialized `f64`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&0f64, &[Token::F64(0.0)]); + /// ``` F64(f64), /// A serialized `char`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&'\n', &[Token::Char('\n')]); + /// ``` Char(char), /// A serialized `str`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// let s = String::from("transient"); + /// assert_tokens(&s, &[Token::Str("transient")]); + /// ``` Str(&'static str), /// A borrowed `str`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// let s: &str = "borrowed"; + /// assert_tokens(&s, &[Token::BorrowedStr("borrowed")]); + /// ``` BorrowedStr(&'static str), /// A serialized `String`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// let s = String::from("owned"); + /// assert_tokens(&s, &[Token::String("owned")]); + /// ``` String(&'static str), /// A serialized `[u8]` @@ -67,85 +160,394 @@ pub enum Token { /// The header to a serialized `Option` containing some value. /// /// The tokens of the value follow after this header. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// let opt = Some('c'); + /// assert_tokens(&opt, &[ + /// Token::Some, + /// Token::Char('c'), + /// ]); + /// ``` Some, /// A serialized `Option` containing none. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// let opt = None::; + /// assert_tokens(&opt, &[Token::None]); + /// ``` None, /// A serialized `()`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// assert_tokens(&(), &[Token::Unit]); + /// ``` Unit, /// A serialized unit struct of the given name. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// struct X; + /// + /// assert_tokens(&X, &[Token::UnitStruct { name: "X" }]); + /// # } + /// ``` UnitStruct { name: &'static str }, /// The header to a serialized newtype struct of the given name. /// - /// Newtype structs are serialized with this header, followed by the value contained in the - /// newtype struct. + /// After this header is the value contained in the newtype struct. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// struct N(String); + /// + /// let n = N("newtype".to_owned()); + /// assert_tokens(&n, &[ + /// Token::NewtypeStruct { name: "N" }, + /// Token::String("newtype"), + /// ]); + /// # } + /// ``` NewtypeStruct { name: &'static str }, /// The header to an enum of the given name. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// enum E { + /// A, + /// B(u8), + /// C(u8, u8), + /// D { d: u8 }, + /// } + /// + /// let a = E::A; + /// assert_tokens(&a, &[ + /// Token::Enum { name: "E" }, + /// Token::Str("A"), + /// Token::Unit, + /// ]); + /// + /// let b = E::B(0); + /// assert_tokens(&b, &[ + /// Token::Enum { name: "E" }, + /// Token::Str("B"), + /// Token::U8(0), + /// ]); + /// + /// let c = E::C(0, 0); + /// assert_tokens(&c, &[ + /// Token::Enum { name: "E" }, + /// Token::Str("C"), + /// Token::Seq { len: Some(2) }, + /// Token::U8(0), + /// Token::U8(0), + /// Token::SeqEnd, + /// ]); + /// + /// let d = E::D { d: 0 }; + /// assert_tokens(&d, &[ + /// Token::Enum { name: "E" }, + /// Token::Str("D"), + /// Token::Map { len: Some(1) }, + /// Token::Str("d"), + /// Token::U8(0), + /// Token::MapEnd, + /// ]); + /// # } + /// ``` Enum { name: &'static str }, - /// A unit variant of an enum of the given name, of the given name. + /// A unit variant of an enum. /// - /// The first string represents the name of the enum, and the second represents the name of the - /// variant. + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// enum E { + /// A, + /// } + /// + /// let a = E::A; + /// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]); + /// # } + /// ``` UnitVariant { name: &'static str, variant: &'static str }, - /// The header to a newtype variant of an enum of the given name, of the given name. + /// The header to a newtype variant of an enum. /// - /// The first string represents the name of the enum, and the second represents the name of the - /// variant. The value contained within this enum works the same as `StructNewType`. + /// After this header is the value contained in the newtype variant. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// enum E { + /// B(u8), + /// } + /// + /// let b = E::B(0); + /// assert_tokens(&b, &[ + /// Token::NewtypeVariant { name: "E", variant: "B" }, + /// Token::U8(0), + /// ]); + /// # } + /// ``` NewtypeVariant { name: &'static str, variant: &'static str }, - /// The header to a sequence of the given length. + /// The header to a sequence. /// - /// These are serialized via `serialize_seq`, which takes an optional length. After this - /// header is a list of elements, followed by `SeqEnd`. + /// After this header are the elements of the sequence, followed by + /// `SeqEnd`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// let vec = vec!['a', 'b', 'c']; + /// assert_tokens(&vec, &[ + /// Token::Seq { len: Some(3) }, + /// Token::Char('a'), + /// Token::Char('b'), + /// Token::Char('c'), + /// Token::SeqEnd, + /// ]); + /// ``` Seq { len: Option }, /// An indicator of the end of a sequence. SeqEnd, - /// The header to a tuple of the given length, similar to `SeqFixedSize`. + /// The header to a tuple. + /// + /// After this header are the elements of the tuple, followed by `TupleEnd`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// let tuple = ('a', 100); + /// assert_tokens(&tuple, &[ + /// Token::Tuple { len: 2 }, + /// Token::Char('a'), + /// Token::I32(100), + /// Token::TupleEnd, + /// ]); + /// ``` Tuple { len: usize }, - /// An indicator of the end of a tuple, similar to `SeqEnd`. + /// An indicator of the end of a tuple. TupleEnd, - /// The header to a tuple struct of the given name and length. + /// The header to a tuple struct. + /// + /// After this header are the fields of the tuple struct, followed by + /// `TupleStructEnd`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// struct T(u8, u8); + /// + /// let t = T(0, 0); + /// assert_tokens(&t, &[ + /// Token::TupleStruct { name: "T", len: 2 }, + /// Token::U8(0), + /// Token::U8(0), + /// Token::TupleStructEnd, + /// ]); + /// # } + /// ``` TupleStruct { name: &'static str, len: usize }, - /// An indicator of the end of a tuple struct, similar to `TupleEnd`. + /// An indicator of the end of a tuple struct. TupleStructEnd, - /// The header to a map of the given length. + /// The header to a map. /// - /// These are serialized via `serialize_map`, which takes an optional length. After this header - /// is a list of key-value pairs, followed by `MapEnd`. + /// After this header are the entries of the map, followed by `MapEnd`. + /// + /// ```rust + /// # use serde_test::{assert_tokens, Token}; + /// # + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert('A', 65); + /// map.insert('Z', 90); + /// + /// assert_tokens(&map, &[ + /// Token::Map { len: Some(2) }, + /// Token::Char('A'), + /// Token::I32(65), + /// Token::Char('Z'), + /// Token::I32(90), + /// Token::MapEnd, + /// ]); + /// ``` Map { len: Option }, /// An indicator of the end of a map. MapEnd, - /// The header of a struct of the given name and length, similar to `Map`. + /// The header of a struct. + /// + /// After this header are the fields of the struct, followed by `StructEnd`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// struct S { + /// a: u8, + /// b: u8, + /// } + /// + /// let s = S { a: 0, b: 0 }; + /// assert_tokens(&s, &[ + /// Token::Struct { name: "S", len: 2 }, + /// Token::Str("a"), + /// Token::U8(0), + /// Token::Str("b"), + /// Token::U8(0), + /// Token::StructEnd, + /// ]); + /// # } + /// ``` Struct { name: &'static str, len: usize }, - /// An indicator of the end of a struct, similar to `MapEnd`. + /// An indicator of the end of a struct. StructEnd, - /// The header to a tuple variant of an enum of the given name, of the given name and length. + /// The header to a tuple variant of an enum. + /// + /// After this header are the fields of the tuple variant, followed by + /// `TupleVariantEnd`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// enum E { + /// C(u8, u8), + /// } + /// + /// let c = E::C(0, 0); + /// assert_tokens(&c, &[ + /// Token::TupleVariant { name: "E", variant: "C", len: 2 }, + /// Token::U8(0), + /// Token::U8(0), + /// Token::TupleVariantEnd, + /// ]); + /// # } + /// ``` TupleVariant { name: &'static str, variant: &'static str, len: usize }, - /// An indicator of the end of a tuple variant, similar to `TupleEnd`. + /// An indicator of the end of a tuple variant. TupleVariantEnd, - /// The header of a struct variant of an enum of the given name, of the given name and length, - /// similar to `Struct`. + /// The header of a struct variant of an enum. + /// + /// After this header are the fields of the struct variant, followed by + /// `StructVariantEnd`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde_derive; + /// # + /// # extern crate serde; + /// # extern crate serde_test; + /// # + /// # use serde_test::{assert_tokens, Token}; + /// # + /// # fn main() { + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// enum E { + /// D { d: u8 }, + /// } + /// + /// let d = E::D { d: 0 }; + /// assert_tokens(&d, &[ + /// Token::StructVariant { name: "E", variant: "D", len: 1 }, + /// Token::Str("d"), + /// Token::U8(0), + /// Token::StructVariantEnd, + /// ]); + /// # } + /// ``` StructVariant { name: &'static str, variant: &'static str, len: usize }, - /// An indicator of the end of a struct, similar to `StructEnd`. + /// An indicator of the end of a struct variant. StructVariantEnd, }