Add an example to the Configure trait

This commit is contained in:
Markus Westerlind
2017-11-03 16:12:43 +01:00
parent 1b9a096fa7
commit aad7a7987f
10 changed files with 157 additions and 186 deletions
+5 -38
View File
@@ -6,7 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use de::Deserializer;
use ser::Serializer;
@@ -47,20 +47,8 @@ pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Serialize + Deserialize<'de> + PartialEq + Debug,
{
assert_tokens_readable(value, tokens, None);
}
// Not public API
#[doc(hidden)]
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
///
/// See: `assert_tokens`
pub fn assert_tokens_readable<'de, T>(value: &T, tokens: &'de [Token], human_readable: Option<bool>)
where
T: Serialize + Deserialize<'de> + PartialEq + Debug,
{
assert_ser_tokens_readable(value, tokens, human_readable);
assert_de_tokens_readable(value, tokens, human_readable);
assert_ser_tokens(value, tokens);
assert_de_tokens(value, tokens);
}
/// Asserts that `value` serializes to the given `tokens`.
@@ -96,19 +84,7 @@ pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where
T: Serialize,
{
assert_ser_tokens_readable(value, tokens, None)
}
// Not public API
#[doc(hidden)]
/// Asserts that `value` serializes to the given `tokens`.
///
/// See: `assert_ser_tokens`
pub fn assert_ser_tokens_readable<T>(value: &T, tokens: &[Token], human_readable: Option<bool>)
where
T: Serialize,
{
let mut ser = Serializer::readable(tokens, human_readable);
let mut ser = Serializer::new(tokens);
match value.serialize(&mut ser) {
Ok(_) => {}
Err(err) => panic!("value failed to serialize: {}", err),
@@ -207,16 +183,7 @@ pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Deserialize<'de> + PartialEq + Debug,
{
assert_de_tokens_readable(value, tokens, None)
}
// Not public API
#[doc(hidden)]
pub fn assert_de_tokens_readable<'de, T>(value: &T, tokens: &'de [Token], human_readable: Option<bool>)
where
T: Deserialize<'de> + PartialEq + Debug,
{
let mut de = Deserializer::readable(tokens, human_readable);
let mut de = Deserializer::new(tokens);
match T::deserialize(&mut de) {
Ok(v) => assert_eq!(v, *value),
Err(e) => panic!("tokens failed to deserialize: {}", e),
+70 -4
View File
@@ -4,19 +4,85 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Readable<T: ?Sized>(T);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Compact<T: ?Sized>(T);
pub trait Configure {
fn readable(&self) -> Readable<&Self> {
/// Trait which lets values mark wheter they should serialize or deserialize to or from their
/// human-readable or compact representation.
///
/// ```
/// extern crate serde;
/// extern crate serde_test;
///
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// use serde_test::{Configure, Token, assert_tokens};
///
/// #[derive(Debug, PartialEq)]
/// struct Example(u8, u8);
///
/// impl Serialize for Example {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer,
/// {
/// if serializer.is_human_readable() {
/// format!("{}.{}", self.0, self.1).serialize(serializer)
/// } else {
/// (self.0, self.1).serialize(serializer)
/// }
/// }
/// }
///
/// impl<'de> Deserialize<'de> for Example {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de>,
/// {
/// use serde::de::Error;
/// if deserializer.is_human_readable() {
/// let s = String::deserialize(deserializer)?;
/// let parts: Vec<_> = s.split('.').collect();
/// Ok(Example(
/// parts[0].parse().map_err(D::Error::custom)?,
/// parts[1].parse().map_err(D::Error::custom)?,
/// ))
/// } else {
/// let (x, y) = Deserialize::deserialize(deserializer)?;
/// Ok(Example(x, y))
/// }
/// }
/// }
///
/// fn main() {
/// assert_tokens(
/// &Example(1, 0).compact(),
/// &[
/// Token::Tuple { len: 2 },
/// Token::U8(1),
/// Token::U8(0),
/// Token::TupleEnd,
/// ],
/// );
/// assert_tokens(
/// &Example(1, 0).readable(),
/// &[
/// Token::Str("1.0"),
/// ],
/// );
/// }
/// ```
pub trait Configure : Sized {
/// Marks `self` as using `is_human_readable == true`
fn readable(self) -> Readable<Self> {
Readable(self)
}
fn compact(&self) -> Compact<&Self> {
/// Marks `self` as using `is_human_readable == false`
fn compact(self) -> Compact<Self> {
Compact(self)
}
}
impl<T: ?Sized> Configure for T {}
impl<T> Configure for T {}
impl<T: ?Sized> Serialize for Readable<T>
where
+5 -17
View File
@@ -16,7 +16,6 @@ use token::Token;
#[derive(Debug)]
pub struct Deserializer<'de> {
tokens: &'de [Token],
is_human_readable: Option<bool>,
}
macro_rules! assert_next_token {
@@ -49,13 +48,7 @@ macro_rules! end_of_tokens {
impl<'de> Deserializer<'de> {
pub fn new(tokens: &'de [Token]) -> Self {
Deserializer::readable(tokens, None)
}
// Not public API
#[doc(hidden)]
pub fn readable(tokens: &'de [Token], is_human_readable: Option<bool>) -> Self {
Deserializer { tokens: tokens, is_human_readable: is_human_readable }
Deserializer { tokens: tokens }
}
fn peek_token_opt(&self) -> Option<Token> {
@@ -373,15 +366,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
}
fn is_human_readable(&self) -> bool {
match self.is_human_readable {
Some(is) => is,
None => {
panic!("There is no serde_test API currently for testing types \
that have different human-readable and compact \
representation. See \
https://github.com/serde-rs/serde/issues/1065.");
}
}
panic!(
"Types which have different human-readable and compact representations\
must explicitly mark their test cases with `serde_test::Configure`"
);
}
}
+3 -7
View File
@@ -169,14 +169,10 @@ mod token;
mod assert;
pub use token::Token;
pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error,
assert_de_tokens, assert_de_tokens_error};
pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
assert_ser_tokens_error, assert_tokens};
pub use configure::{Configure, Compact, Readable};
// Not public API.
#[doc(hidden)]
pub use assert::{assert_tokens_readable, assert_de_tokens_readable, assert_ser_tokens_readable};
pub use configure::{Compact, Configure, Readable};
// Not public API.
#[doc(hidden)]
+21 -21
View File
@@ -15,19 +15,12 @@ use token::Token;
#[derive(Debug)]
pub struct Serializer<'a> {
tokens: &'a [Token],
is_human_readable: Option<bool>,
}
impl<'a> Serializer<'a> {
/// Creates the serializer.
pub fn new(tokens: &'a [Token]) -> Self {
Serializer::readable(tokens, None)
}
// Not public API
#[doc(hidden)]
pub fn readable(tokens: &'a [Token], is_human_readable: Option<bool>) -> Self {
Serializer { tokens: tokens, is_human_readable: is_human_readable }
Serializer { tokens: tokens }
}
/// Pulls the next token off of the serializer, ignoring it.
@@ -254,10 +247,16 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
assert_next_token!(self, Str(variant));
let len = Some(len);
assert_next_token!(self, Seq { len });
Ok(Variant { ser: self, end: Token::SeqEnd })
Ok(Variant {
ser: self,
end: Token::SeqEnd,
})
} else {
assert_next_token!(self, TupleVariant { name, variant, len });
Ok(Variant { ser: self, end: Token::TupleVariantEnd })
Ok(Variant {
ser: self,
end: Token::TupleVariantEnd,
})
}
}
@@ -283,23 +282,24 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
assert_next_token!(self, Str(variant));
let len = Some(len);
assert_next_token!(self, Map { len });
Ok(Variant { ser: self, end: Token::MapEnd })
Ok(Variant {
ser: self,
end: Token::MapEnd,
})
} else {
assert_next_token!(self, StructVariant { name, variant, len });
Ok(Variant { ser: self, end: Token::StructVariantEnd })
Ok(Variant {
ser: self,
end: Token::StructVariantEnd,
})
}
}
fn is_human_readable(&self) -> bool {
match self.is_human_readable {
Some(is) => is,
None => {
panic!("There is no serde_test API currently for testing types \
that have different human-readable and compact \
representation. See \
https://github.com/serde-rs/serde/issues/1065.");
}
}
panic!(
"Types which have different human-readable and compact representations\
must explicitly mark their test cases with `serde_test::Configure`"
);
}
}