use std::collections::BTreeMap;
use std::fmt::Debug;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
fn roundtrip<T: Serialize + DeserializeOwned + PartialEq + Debug>(value: T) {
let bytes = cbor2::to_vec(&value).unwrap();
let back: T = cbor2::from_slice(&bytes).unwrap();
assert_eq!(value, back);
}
fn assert_wire<T: Serialize>(value: T, hex: &str) {
assert_eq!(hex::encode(cbor2::to_vec(&value).unwrap()), hex);
}
#[test]
fn primitives() {
roundtrip(false);
roundtrip(true);
roundtrip(0u8);
roundtrip(23u8);
roundtrip(255u8);
roundtrip(u16::MAX);
roundtrip(u32::MAX);
roundtrip(u64::MAX);
roundtrip(i8::MIN);
roundtrip(i16::MIN);
roundtrip(i32::MIN);
roundtrip(i64::MIN);
roundtrip(0.0f32);
roundtrip(1.625f32);
roundtrip(core::f64::consts::PI);
roundtrip('a');
roundtrip('\u{6c34}');
roundtrip(String::from("hello, world"));
roundtrip(());
}
#[test]
fn big_integers() {
roundtrip(u128::MAX);
roundtrip(i128::MAX);
roundtrip(i128::MIN);
roundtrip(u64::MAX as u128 + 1);
roundtrip(-(u64::MAX as i128) - 2);
assert_wire(1u128, "01");
assert_wire(-1i128, "20");
assert_wire(u64::MAX as u128 + 1, "c249010000000000000000");
let small_bignum = hex::decode("c24101").unwrap(); assert_eq!(cbor2::from_slice::<u8>(&small_bignum).unwrap(), 1);
}
#[test]
fn widening_and_narrowing() {
let one = cbor2::to_vec(&1u8).unwrap();
assert_eq!(cbor2::from_slice::<u64>(&one).unwrap(), 1);
assert_eq!(cbor2::from_slice::<i8>(&one).unwrap(), 1);
assert_eq!(cbor2::from_slice::<u128>(&one).unwrap(), 1);
let big = cbor2::to_vec(&300u64).unwrap();
assert!(cbor2::from_slice::<u8>(&big).is_err());
let neg = cbor2::to_vec(&-1i8).unwrap();
assert!(cbor2::from_slice::<u64>(&neg).is_err());
let f = cbor2::to_vec(&1.5f32).unwrap();
assert_eq!(cbor2::from_slice::<f64>(&f).unwrap(), 1.5);
}
#[test]
fn options() {
roundtrip(Option::<u32>::None);
roundtrip(Some(42u32));
assert_wire(Option::<u32>::None, "f6");
let bytes = cbor2::to_vec(&Some(Option::<String>::None)).unwrap();
assert_eq!(
cbor2::from_slice::<Option<Option<String>>>(&bytes).unwrap(),
None
);
assert_eq!(cbor2::from_slice::<Option<u32>>(&[0xf7]).unwrap(), None);
}
#[test]
fn sequences_and_maps() {
roundtrip(vec![1u32, 2, 3]);
roundtrip((1u8, String::from("x"), 1.5f64));
roundtrip([0u8; 0].to_vec());
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![1u8]);
roundtrip(intmap);
}
#[test]
fn byte_strings() {
let bytes = serde_bytes::ByteBuf::from(vec![1u8, 2, 3, 4]);
let encoded = cbor2::to_vec(&bytes).unwrap();
assert_eq!(hex::encode(&encoded), "4401020304");
let back: serde_bytes::ByteBuf = cbor2::from_slice(&encoded).unwrap();
assert_eq!(back, bytes);
let v: Vec<u8> = cbor2::from_slice(&encoded).unwrap();
assert_eq!(v, vec![1, 2, 3, 4]);
let array = cbor2::to_vec(&vec![1u8, 2, 3, 4]).unwrap();
assert_eq!(hex::encode(&array), "8401020304");
let back: serde_bytes::ByteBuf = cbor2::from_slice(&array).unwrap();
assert_eq!(back, bytes);
}
#[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);
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct TupleStruct(u32, String);
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Unit;
#[test]
fn structs() {
roundtrip(Plain {
name: "x".into(),
size: 42,
tags: vec!["a".into()],
ratio: None,
});
roundtrip(Newtype(99));
roundtrip(TupleStruct(1, "two".into()));
roundtrip(Unit);
assert_wire(Newtype(7), "07"); assert_wire(Unit, "f6"); }
#[derive(Debug, PartialEq, Deserialize, Serialize)]
enum Enum {
Unit,
Newtype(u32),
Tuple(u32, u32),
Struct { x: u32 },
}
#[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_wire(Enum::Unit, "64556e6974"); assert_wire(Enum::Newtype(42), "a1674e657774797065182a"); assert_wire(Enum::Tuple(1, 2), "a1655475706c65820102"); assert_wire(Enum::Struct { x: 7 }, "a166537472756374a1617807"); }
#[test]
fn skipped_and_unknown_fields() {
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Small {
name: String,
}
let full = cbor2::to_vec(&Plain {
name: "x".into(),
size: 42,
tags: vec![],
ratio: Some(0.5),
})
.unwrap();
let small: Small = cbor2::from_slice(&full).unwrap();
assert_eq!(small, Small { name: "x".into() });
}
#[test]
fn indefinite_containers_decode() {
let bytes = hex::decode("9f0102ff").unwrap();
assert_eq!(cbor2::from_slice::<Vec<u32>>(&bytes).unwrap(), vec![1, 2]);
let bytes = hex::decode("bf616101ff").unwrap();
let map: BTreeMap<String, u32> = cbor2::from_slice(&bytes).unwrap();
assert_eq!(map.len(), 1);
assert_eq!(map["a"], 1);
let bytes = hex::decode("7f657374726561646d696e67ff").unwrap();
assert_eq!(cbor2::from_slice::<String>(&bytes).unwrap(), "streaming");
let bytes = hex::decode("5f42010243030405ff").unwrap();
let buf: serde_bytes::ByteBuf = cbor2::from_slice(&bytes).unwrap();
assert_eq!(buf.as_ref(), &[1, 2, 3, 4, 5]);
}
#[test]
fn unknown_tags_are_transparent() {
let bytes = hex::decode("d912676178").unwrap();
assert_eq!(cbor2::from_slice::<String>(&bytes).unwrap(), "x");
let bytes = hex::decode("c11a514b67b0").unwrap();
assert_eq!(cbor2::from_slice::<u64>(&bytes).unwrap(), 1363896240);
}
#[test]
fn stream_of_items() {
let mut buffer = Vec::new();
cbor2::to_writer(&1u32, &mut buffer).unwrap();
cbor2::to_writer(&"two", &mut buffer).unwrap();
cbor2::to_writer(&vec![3u8], &mut buffer).unwrap();
let mut iter = cbor2::de::Deserializer::from_reader(&buffer[..]).into_iter::<cbor2::Value>();
assert_eq!(iter.next().unwrap().unwrap(), cbor2::Value::from(1));
assert_eq!(iter.next().unwrap().unwrap(), cbor2::Value::from("two"));
assert_eq!(
iter.next().unwrap().unwrap(),
cbor2::Value::Array(vec![cbor2::Value::from(3)])
);
assert!(iter.next().is_none());
let mut truncated = Vec::new();
cbor2::to_writer(&1u32, &mut truncated).unwrap();
truncated.extend_from_slice(&[0x19, 0x01]);
let mut iter = cbor2::de::Deserializer::from_reader(&truncated[..]).into_iter::<u32>();
assert_eq!(iter.next().unwrap().unwrap(), 1);
assert!(iter.next().unwrap().is_err());
}
#[test]
fn integer_wire_forms() {
assert_wire(7i8, "07");
assert_wire(7i64, "07");
assert_wire(2i128, "02");
assert_wire(-2i128, "21");
}
struct Unsized;
impl Serialize for Unsized {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.collect_seq((1u8..=3).filter(|_| true))
}
}
struct UnsizedMap;
impl Serialize for UnsizedMap {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeMap;
let mut acc = serializer.serialize_map(None)?;
acc.serialize_entry(&1u8, &2u8)?;
acc.end()
}
}
#[test]
fn indefinite_containers_encode() {
assert_wire(Unsized, "9f010203ff");
assert_eq!(
cbor2::from_slice::<Vec<u8>>(&cbor2::to_vec(&Unsized).unwrap()).unwrap(),
vec![1, 2, 3]
);
assert_wire(UnsizedMap, "bf0102ff");
let map: BTreeMap<u8, u8> = cbor2::from_slice(&cbor2::to_vec(&UnsizedMap).unwrap()).unwrap();
assert_eq!(map, [(1, 2)].into());
}