use crate::common;
use std::collections::{BTreeMap, HashMap};
use std::fmt::Debug;
use common::{Value, de, hex, ser};
use deser::de::DeserializeOwned;
use deser::{Deserialize, Serialize};
use deser_msgpack::SerializerConfig;
const CANONICAL: SerializerConfig = SerializerConfig::builder().canonical(true).build();
fn roundtrip<T: Serialize + DeserializeOwned + PartialEq + Debug>(value: T) {
let bytes = deser_msgpack::to_vec(&value).unwrap();
assert_eq!(deser_msgpack::from_slice::<T>(&bytes).unwrap(), value);
let dynamic: Value = deser_msgpack::from_slice(&bytes).unwrap();
assert_eq!(
deser_msgpack::to_vec(&dynamic).unwrap(),
bytes,
"{:?}",
value
);
if !matches!(dynamic, Value::Map(_)) {
assert_eq!(CANONICAL.to_vec(&value).unwrap(), bytes);
}
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
pub enum Enum {
Unit,
Newtype(u32),
Tuple(u32, u32),
Struct { x: u32 },
}
#[test]
fn primitives() {
roundtrip(false);
roundtrip(true);
roundtrip(0u8);
roundtrip(127u8);
roundtrip(255u8);
roundtrip(u16::MAX);
roundtrip(u32::MAX);
roundtrip(u64::MAX);
roundtrip(i8::MIN);
roundtrip(i16::MIN);
roundtrip(i32::MIN);
roundtrip(i64::MIN);
roundtrip(i64::MAX);
roundtrip(0.0f32);
roundtrip(1.625f32);
roundtrip(0.1f32);
roundtrip(core::f64::consts::PI);
roundtrip(f64::MAX);
roundtrip(f64::MIN_POSITIVE);
roundtrip(f32::MAX);
roundtrip('a');
roundtrip('\u{6c34}');
roundtrip(String::from("hello, world"));
roundtrip(());
}
#[test]
fn integer_wire_forms() {
assert_eq!(ser(&0u8), "00");
assert_eq!(ser(&127u8), "7f");
assert_eq!(ser(&128u8), "cc80");
assert_eq!(ser(&255u8), "ccff");
assert_eq!(ser(&256u16), "cd0100");
assert_eq!(ser(&65535u32), "cdffff");
assert_eq!(ser(&65536u32), "ce00010000");
assert_eq!(ser(&u32::MAX), "ceffffffff");
assert_eq!(ser(&(u32::MAX as u64 + 1)), "cf0000000100000000");
assert_eq!(ser(&7i8), "07");
assert_eq!(ser(&7i64), "07");
assert_eq!(ser(&200i64), "ccc8");
assert_eq!(ser(&-1i8), "ff");
assert_eq!(ser(&-32i8), "e0");
assert_eq!(ser(&-33i8), "d0df");
assert_eq!(ser(&-128i16), "d080");
assert_eq!(ser(&-129i16), "d1ff7f");
assert_eq!(ser(&-32768i32), "d18000");
assert_eq!(ser(&-32769i32), "d2ffff7fff");
assert_eq!(ser(&(i32::MIN as i64 - 1)), "d3ffffffff7fffffff");
assert_eq!(ser(&i64::MIN), "d38000000000000000");
assert_eq!(ser(&2i128), "02");
assert_eq!(ser(&-2i128), "fe");
}
#[test]
fn big_integers() {
roundtrip(u64::MAX as u128);
roundtrip(i64::MIN as i128);
assert_eq!(de::<u128>("cfffffffffffffffff").unwrap(), u64::MAX as u128);
assert_eq!(de::<i128>("d38000000000000000").unwrap(), i64::MIN as i128);
}
#[test]
fn widening_and_narrowing() {
let one = deser_msgpack::to_vec(&1u8).unwrap();
assert_eq!(deser_msgpack::from_slice::<u64>(&one).unwrap(), 1);
assert_eq!(deser_msgpack::from_slice::<i8>(&one).unwrap(), 1);
assert_eq!(deser_msgpack::from_slice::<u128>(&one).unwrap(), 1);
let big = deser_msgpack::to_vec(&300u64).unwrap();
assert!(deser_msgpack::from_slice::<u8>(&big).is_err());
let neg = deser_msgpack::to_vec(&-1i8).unwrap();
assert!(deser_msgpack::from_slice::<u64>(&neg).is_err());
let f = deser_msgpack::to_vec(&1.5f32).unwrap();
assert_eq!(deser_msgpack::from_slice::<f64>(&f).unwrap(), 1.5);
assert_eq!(deser_msgpack::from_slice::<f32>(&f).unwrap(), 1.5);
let f = deser_msgpack::to_vec(&1.5f64).unwrap();
assert_eq!(deser_msgpack::from_slice::<f32>(&f).unwrap(), 1.5);
}
#[test]
fn options() {
roundtrip(Option::<u32>::None);
roundtrip(Some(42u32));
assert_eq!(ser(&Option::<u32>::None), "c0");
let bytes = deser_msgpack::to_vec(&Some(Option::<String>::None)).unwrap();
assert_eq!(common::to_hex(&bytes), "c0");
assert_eq!(
deser_msgpack::from_slice::<Option<Option<String>>>(&bytes).unwrap(),
Some(None)
);
}
#[test]
fn sequences_and_maps() {
roundtrip(vec![1u32, 2, 3]);
roundtrip((1u8, String::from("x"), 1.5f64));
roundtrip(Vec::<u32>::new());
roundtrip(vec![vec![1u32], vec![], vec![2, 3]]);
roundtrip([1u16, 2, 3]);
let mut map = BTreeMap::new();
map.insert(String::from("a"), 1u32);
map.insert(String::from("b"), 2u32);
roundtrip(map);
let mut intmap = BTreeMap::new();
intmap.insert(-1i64, vec![1u32]);
intmap.insert(1i64, vec![]);
roundtrip(intmap.clone());
assert_eq!(ser(&intmap), "82ff9101 0190".replace(' ', ""));
let mut boolmap = BTreeMap::new();
boolmap.insert(false, 1u32);
boolmap.insert(true, 2u32);
roundtrip(boolmap);
let mut vecmap = BTreeMap::new();
vecmap.insert(vec![1u32, 2], "x".to_string());
roundtrip(vecmap);
}
#[test]
fn binary_data() {
let bytes = vec![1u8, 2, 3, 4];
let encoded = deser_msgpack::to_vec(&bytes).unwrap();
assert_eq!(common::to_hex(&encoded), "c40401020304");
let back: Vec<u8> = deser_msgpack::from_slice(&encoded).unwrap();
assert_eq!(back, bytes);
roundtrip(bytes);
roundtrip(Vec::<u8>::new());
let back: Vec<u8> = de("9401020304").unwrap();
assert_eq!(back, vec![1, 2, 3, 4]);
let back: [u8; 4] = de("c40401020304").unwrap();
assert_eq!(back, [1, 2, 3, 4]);
let big = vec![0xabu8; if cfg!(miri) { 300 } else { 70_000 }];
roundtrip(big);
let text = "雨".repeat(if cfg!(miri) { 100 } else { 20_000 });
roundtrip(text);
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Plain {
name: String,
size: u64,
tags: Vec<String>,
ratio: Option<f64>,
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Newtype(u32);
#[test]
fn structs() {
roundtrip(Plain {
name: "x".into(),
size: 42,
tags: vec!["a".into()],
ratio: None,
});
roundtrip(Newtype(99));
assert_eq!(
ser(&Plain {
name: "x".into(),
size: 42,
tags: vec![],
ratio: Some(0.5),
}),
"84 a46e616d65 a178 a473697a65 2a a474616773 90 a5726174696f cb3fe0000000000000"
.replace(' ', "")
);
assert_eq!(ser(&Newtype(7)), "07");
}
#[test]
fn enums() {
roundtrip(Enum::Unit);
roundtrip(Enum::Newtype(42));
roundtrip(Enum::Tuple(1, 2));
roundtrip(Enum::Struct { x: 7 });
roundtrip(vec![Enum::Unit, Enum::Newtype(0)]);
assert_eq!(ser(&Enum::Unit), "a4556e6974"); assert_eq!(ser(&Enum::Newtype(42)), "81a74e6577747970652a"); assert_eq!(ser(&Enum::Tuple(1, 2)), "81a55475706c65920102"); assert_eq!(ser(&Enum::Struct { x: 7 }), "81a653747275637481a17807");
assert_eq!(
de::<Enum>("de0001d9074e6577747970652a").unwrap(),
Enum::Newtype(42)
);
assert_eq!(
de::<Enum>("df00000001a55475706c65dd000000020102").unwrap(),
Enum::Tuple(1, 2)
);
assert!(de::<Enum>("a74e657774797065").is_err());
assert!(de::<Enum>("a55475706c65").is_err());
assert!(de::<Enum>("82a74e6577747970652aa155c0").is_err());
assert!(de::<Enum>("80").is_err());
}
#[test]
fn internally_tagged_enums_buffer_non_string_keys() {
#[derive(Debug, PartialEq, Deserialize, Serialize)]
#[deser(tag = "t")]
enum Message {
Stats {
counts: HashMap<u32, u32>,
total: u64,
at: deser::ext::Timestamp,
},
}
let bytes = hex(
"84 a6636f756e7473 810102 a5746f74616c cfffffffffffffffff a26174 d6ff00000001 a174 a55374617473",
);
let msg: Message = deser_msgpack::from_slice(&bytes).unwrap();
assert_eq!(
msg,
Message::Stats {
counts: [(1, 2)].into_iter().collect(),
total: u64::MAX,
at: deser::ext::Timestamp {
seconds: 1,
nanosecond: 0
},
}
);
}
#[test]
fn skipped_and_unknown_fields() {
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Small {
name: String,
}
let full = deser_msgpack::to_vec(&Plain {
name: "x".into(),
size: 42,
tags: vec!["a".into(), "b".into()],
ratio: Some(0.5),
})
.unwrap();
let small: Small = deser_msgpack::from_slice(&full).unwrap();
assert_eq!(small, Small { name: "x".into() });
let small: Small = de("83 a178 92 01 81 c3 c0 a46e616d65 a178 a179 d40701 ").unwrap();
assert_eq!(small, Small { name: "x".into() });
}
#[test]
fn stream_of_items() {
let mut buffer = Vec::new();
buffer.extend(deser_msgpack::to_vec(&1u32).unwrap());
buffer.extend(deser_msgpack::to_vec(&"two").unwrap());
buffer.extend(deser_msgpack::to_vec(&vec![3u32]).unwrap());
let mut de = deser_msgpack::Deserializer::from_slice(&buffer);
let mut iter = de.iter::<Value>();
assert_eq!(iter.next().unwrap().unwrap(), Value::from(1u64));
assert_eq!(iter.next().unwrap().unwrap(), Value::from("two"));
assert_eq!(iter.next().unwrap().unwrap(), array![3u64]);
assert!(iter.next().is_none());
assert!(deser_msgpack::from_slice::<u32>(&buffer).is_err());
let mut truncated = deser_msgpack::to_vec(&1u32).unwrap();
truncated.extend_from_slice(&[0xcd, 0x01]);
let mut de = deser_msgpack::Deserializer::from_slice(&truncated);
let mut iter = de.iter::<u32>();
assert_eq!(iter.next().unwrap().unwrap(), 1);
assert!(iter.next().unwrap().is_err());
assert!(iter.next().is_none());
let mut de = deser_msgpack::Deserializer::from_slice(&[]);
assert!(de.iter::<u32>().next().is_none());
let mut de = deser_msgpack::Deserializer::from_slice(&[0x01, 0xc1, 0x02]);
let mut iter = de.iter::<u32>();
assert_eq!(iter.next().unwrap().unwrap(), 1);
let err = iter.next().unwrap().unwrap_err();
assert!(err.to_string().contains("offset 1"), "{}", err);
assert!(iter.next().is_none());
}
#[test]
fn deserializer_offset() {
let bytes = deser_msgpack::to_vec(&(1u64, "ab")).unwrap();
let mut de = deser_msgpack::Deserializer::from_slice(&bytes);
assert_eq!(de.offset(), 0);
let _: (u64, String) = de.deserialize().unwrap();
assert_eq!(de.offset(), bytes.len());
assert!(de.is_end());
de.end().unwrap();
}