use std::fmt::Debug;
use std::marker::PhantomData;
use deser::adapters::DisplayFromStr;
use deser::de::{DeserializeDriver, DeserializeOwned};
use deser::ser::{Describe, SerializeDriver};
use deser::{Atom, Deserialize, Error, Event, Serialize};
fn without_len(event: Event<'static>) -> Event<'static> {
match event {
Event::MapStart(shape) => Event::MapStart(deser::ContainerShape::with_order(shape.order())),
Event::SeqStart(shape) => Event::SeqStart(deser::ContainerShape::with_order(shape.order())),
event => event,
}
}
fn deserialize<T: DeserializeOwned>(events: Vec<Event<'_>>) -> Result<T, Error> {
let mut out = None;
{
let mut driver = DeserializeDriver::new(&mut out);
for event in events {
driver.emit(event)?;
}
}
Ok(out.unwrap())
}
fn deserialize_lenient<T: DeserializeOwned>(events: Vec<Event<'_>>) -> Result<T, Error> {
let mut out = None;
{
let mut driver = DeserializeDriver::new(&mut out);
deser::de::LexicalRules::LENIENT.set(driver.state_mut());
for event in events {
driver.emit(event)?;
}
}
Ok(out.unwrap())
}
fn serialize<T: Serialize + ?Sized>(value: &T) -> Vec<Event<'static>> {
let mut events = Vec::new();
let mut driver = SerializeDriver::new(&value);
while let Some((event, _, _)) = driver.next().unwrap() {
events.push(without_len(event.to_static()));
}
events
}
fn check<T: Serialize + DeserializeOwned + PartialEq + Debug>(value: T, events: Vec<Event<'_>>) {
assert_eq!(
serialize(&value),
events.iter().map(|x| x.to_static()).collect::<Vec<_>>()
);
assert_eq!(deserialize::<T>(events).unwrap(), value);
}
#[derive(Default)]
struct Names(Vec<String>);
impl Describe for Names {
fn tuple_struct(&mut self, name: &str) {
self.0.push(format!("tuple struct {}", name));
}
fn unit_struct(&mut self, name: &str) {
self.0.push(format!("unit struct {}", name));
}
}
fn describe<T: Serialize + ?Sized>(value: &T) -> Vec<String> {
let mut names = Names::default();
T::describe(value, &mut names);
names.0
}
#[test]
fn test_tuple_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Pair(u32, String);
check(
Pair(1, "two".into()),
vec![Event::seq_start(), 1u64.into(), "two".into(), Event::SeqEnd],
);
assert_eq!(describe(&Pair(1, "two".into())), ["tuple struct Pair"]);
let err =
deserialize::<Pair>(vec![Event::seq_start(), 1u64.into(), Event::SeqEnd]).unwrap_err();
assert_eq!(err.message(), "not enough elements in tuple");
let err = deserialize::<Pair>(vec![
Event::seq_start(),
1u64.into(),
"two".into(),
"three".into(),
])
.unwrap_err();
assert_eq!(err.message(), "too many elements in tuple");
let err = deserialize::<Pair>(vec![Event::map_start()]).unwrap_err();
assert_eq!(err.message(), "unexpected map, expected tuple");
}
#[test]
fn test_tuple_struct_shape() {
#[derive(Serialize)]
struct Triple(u32, u32, u32);
let mut driver = SerializeDriver::new(&Triple(1, 2, 3));
let (event, _, _) = driver.next().unwrap().unwrap();
assert_eq!(
event.to_static(),
Event::SeqStart(deser::ContainerShape::with_len(3))
);
}
#[test]
fn test_tuple_struct_generic() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Pair<A, B>(A, B);
check(
Pair(1u32, Some(true)),
vec![Event::seq_start(), 1u64.into(), true.into(), Event::SeqEnd],
);
}
#[test]
fn test_tuple_struct_adapters() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Addr(#[deser(as = DisplayFromStr)] std::net::IpAddr, u16);
check(
Addr("127.0.0.1".parse().unwrap(), 80),
vec![
Event::seq_start(),
"127.0.0.1".into(),
80u64.into(),
Event::SeqEnd,
],
);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Generic<T>(#[deser(as = DisplayFromStr)] T, u16)
where
T: std::fmt::Display + std::str::FromStr,
T::Err: std::fmt::Display;
check(
Generic(42u32, 1),
vec![Event::seq_start(), "42".into(), 1u64.into(), Event::SeqEnd],
);
}
#[test]
fn test_tuple_struct_borrowed() {
#[derive(Debug, PartialEq, Deserialize)]
struct Borrowed<'a>(&'a str, u32);
let mut out = None::<Borrowed<'_>>;
{
let mut driver = DeserializeDriver::new(&mut out);
driver.emit(Event::seq_start()).unwrap();
driver
.emit_borrowed(Event::Atom(Atom::Str("borrowed".into())))
.unwrap();
driver.emit(1u64).unwrap();
driver.emit(Event::SeqEnd).unwrap();
}
assert_eq!(out.unwrap(), Borrowed("borrowed", 1));
}
#[test]
fn test_empty_tuple_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Empty();
check(Empty(), vec![Atom::Null.into()]);
assert_eq!(describe(&Empty()), ["unit struct Empty"]);
}
#[test]
fn test_unit_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Unit;
check(Unit, vec![Atom::Null.into()]);
assert_eq!(describe(&Unit), ["unit struct Unit"]);
assert_eq!(
deserialize_lenient::<Unit>(vec![Atom::Lexical("".into()).into()]).unwrap(),
Unit
);
let err = deserialize::<Unit>(vec![Atom::Lexical("".into()).into()]).unwrap_err();
assert_eq!(err.message(), "unexpected string, expected Unit");
let err = deserialize::<Unit>(vec![42u64.into()]).unwrap_err();
assert_eq!(err.message(), "unexpected unsigned integer, expected Unit");
let err = deserialize::<Unit>(vec![Event::seq_start()]).unwrap_err();
assert_eq!(err.message(), "unexpected sequence, expected Unit");
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[deser(rename = "Nothing")]
struct Renamed;
let err = deserialize::<Renamed>(vec![true.into()]).unwrap_err();
assert_eq!(err.message(), "unexpected bool, expected Nothing");
}
#[test]
fn test_unit_struct_in_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Marker;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Outer {
marker: Marker,
pair: (u32, Marker),
}
check(
Outer {
marker: Marker,
pair: (1, Marker),
},
vec![
Event::map_start(),
"marker".into(),
Atom::Null.into(),
"pair".into(),
Event::seq_start(),
1u64.into(),
Atom::Null.into(),
Event::SeqEnd,
Event::MapEnd,
],
);
}
#[test]
fn test_unit_struct_const_generic() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Version<const N: u32>;
check(Version::<2>, vec![Atom::Null.into()]);
}
#[test]
fn test_tuple_struct_phantom() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Tagged<T>(u32, PhantomData<T>);
check(
Tagged::<String>(1, PhantomData),
vec![
Event::seq_start(),
1u64.into(),
Atom::Null.into(),
Event::SeqEnd,
],
);
}
#[test]
fn test_skipped_fields() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Pair(u32, #[deser(skip)] String, u32);
check(
Pair(1, String::new(), 2),
vec![Event::seq_start(), 1u64.into(), 2u64.into(), Event::SeqEnd],
);
assert_eq!(
serialize(&Pair(1, "x".into(), 2)),
[Event::seq_start(), 1u64.into(), 2u64.into(), Event::SeqEnd]
);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Meters<U>(f64, #[deser(skip)] PhantomData<U>);
check(Meters::<()>(1.5, PhantomData), vec![1.5f64.into()]);
assert!(describe(&Meters::<()>(1.5, PhantomData)).is_empty());
#[derive(Debug, PartialEq, Deserialize)]
struct Defaults(
u32,
#[deser(skip_deserializing, default = 42)] u32,
#[deser(skip, default = "x")] String,
);
assert_eq!(
deserialize::<Defaults>(vec![7u64.into()]).unwrap(),
Defaults(7, 42, "x".into())
);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct OneWay(u32, #[deser(skip_serializing)] u32);
assert_eq!(serialize(&OneWay(1, 2)), [1u64.into()]);
assert_eq!(
deserialize::<OneWay>(vec![
Event::seq_start(),
1u64.into(),
2u64.into(),
Event::SeqEnd
])
.unwrap(),
OneWay(1, 2)
);
struct NotDeserializable;
#[derive(Deserialize)]
struct Generic<T>(u32, #[deser(skip, default = None)] Option<T>);
let value = deserialize::<Generic<NotDeserializable>>(vec![1u64.into()]).unwrap();
assert_eq!(value.0, 1);
assert!(value.1.is_none());
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Nothing(#[deser(skip)] u32);
check(Nothing(0), vec![Atom::Null.into()]);
}
#[test]
fn test_transparent() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[deser(transparent)]
struct Id {
value: u64,
}
check(Id { value: 42 }, vec![42u64.into()]);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[deser(transparent)]
struct Tagged<T> {
#[deser(as = DisplayFromStr)]
value: u32,
#[deser(skip)]
marker: PhantomData<T>,
#[deser(skip, default = 7)]
other: u32,
}
check(
Tagged::<String> {
value: 1,
marker: PhantomData,
other: 7,
},
vec!["1".into()],
);
#[derive(Debug, PartialEq, Deserialize)]
#[deser(transparent)]
struct Name<'a> {
name: &'a str,
}
let input = String::from("x");
let mut out = None::<Name<'_>>;
DeserializeDriver::new(&mut out)
.emit_borrowed(input.as_str())
.unwrap();
assert_eq!(out.unwrap(), Name { name: "x" });
}