blob: d1f602688fede032eff8e01b930d9b76d71409ac [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0
extern crate std;
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::fmt::Debug;
use ciborium::value::Value;
use ciborium::{cbor, de::from_reader, ser::into_writer};
use rstest::rstest;
use serde::{Deserialize, Serialize};
macro_rules! val {
($x:expr) => {
Value::try_from($x).unwrap()
};
}
macro_rules! hex {
($x:expr) => {
serde_bytes::ByteBuf::from(hex::decode($x).unwrap())
};
}
macro_rules! map {
($($k:expr => $v:expr),*) => {{
let mut map = BTreeMap::new();
$(
map.insert($k, $v);
)*
map
}}
}
// Keep the first "case" aligned to a line number ending in 1 for ease in finding tests.
#[allow(clippy::excessive_precision)]
#[rstest(input, value, bytes, alternate, equality,
case(0u8, val!(0u8), "00", false, same),
case(0u16, val!(0u16), "00", false, same),
case(0u32, val!(0u32), "00", false, same),
case(0u64, val!(0u64), "00", false, same),
case(0u128, val!(0u128), "00", false, same),
case(0i8, val!(0i8), "00", false, same),
case(0i16, val!(0i16), "00", false, same),
case(0i32, val!(0i32), "00", false, same),
case(0i64, val!(0i64), "00", false, same),
case(0i128, val!(0i128), "00", false, same),
case(1u8, val!(1u8), "01", false, same),
case(1u16, val!(1u16), "01", false, same),
case(1u32, val!(1u32), "01", false, same),
case(1u64, val!(1u64), "01", false, same),
case(1u128, val!(1u128), "01", false, same),
case(1i8, val!(1i8), "01", false, same),
case(1i16, val!(1i16), "01", false, same),
case(1i32, val!(1i32), "01", false, same),
case(1i64, val!(1i64), "01", false, same),
case(1i128, val!(1i128), "01", false, same),
case(1u8, val!(1u8), "1b0000000000000001", true, same),
case(1u16, val!(1u16), "1b0000000000000001", true, same),
case(1u32, val!(1u32), "1b0000000000000001", true, same),
case(1u64, val!(1u64), "1b0000000000000001", true, same),
case(1u128, val!(1u128), "1b0000000000000001", true, same),
case(1i8, val!(1i8), "1b0000000000000001", true, same),
case(1i16, val!(1i16), "1b0000000000000001", true, same),
case(1i32, val!(1i32), "1b0000000000000001", true, same),
case(1i64, val!(1i64), "1b0000000000000001", true, same),
case(1i128, val!(1i128), "1b0000000000000001", true, same),
case(1u8, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1u16, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1u32, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1u64, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1u128, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1i8, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1i16, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1i32, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1i64, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(1i128, bigint(), "c2540000000000000000000000000000000000000001", true, same), // Not In RFC
case(10u8, val!(10u8), "0a", false, same),
case(10u16, val!(10u16), "0a", false, same),
case(10u32, val!(10u32), "0a", false, same),
case(10u64, val!(10u64), "0a", false, same),
case(10u128, val!(10u128), "0a", false, same),
case(10i8, val!(10i8), "0a", false, same),
case(10i16, val!(10i16), "0a", false, same),
case(10i32, val!(10i32), "0a", false, same),
case(10i64, val!(10i64), "0a", false, same),
case(10i128, val!(10i128), "0a", false, same),
case(23u8, val!(23u8), "17", false, same),
case(23u16, val!(23u16), "17", false, same),
case(23u32, val!(23u32), "17", false, same),
case(23u64, val!(23u64), "17", false, same),
case(23u128, val!(23u128), "17", false, same),
case(23i8, val!(23i8), "17", false, same),
case(23i16, val!(23i16), "17", false, same),
case(23i32, val!(23i32), "17", false, same),
case(23i64, val!(23i64), "17", false, same),
case(23i128, val!(23i128), "17", false, same),
case(24u8, val!(24u8), "1818", false, same),
case(24u16, val!(24u16), "1818", false, same),
case(24u32, val!(24u32), "1818", false, same),
case(24u64, val!(24u64), "1818", false, same),
case(24u128, val!(24u128), "1818", false, same),
case(24i8, val!(24i8), "1818", false, same),
case(24i16, val!(24i16), "1818", false, same),
case(24i32, val!(24i32), "1818", false, same),
case(24i64, val!(24i64), "1818", false, same),
case(24i128, val!(24i128), "1818", false, same),
case(25u8, val!(25u8), "1819", false, same),
case(25u16, val!(25u16), "1819", false, same),
case(25u32, val!(25u32), "1819", false, same),
case(25u64, val!(25u64), "1819", false, same),
case(25u128, val!(25u128), "1819", false, same),
case(25i8, val!(25i8), "1819", false, same),
case(25i16, val!(25i16), "1819", false, same),
case(25i32, val!(25i32), "1819", false, same),
case(25i64, val!(25i64), "1819", false, same),
case(25i128, val!(25i128), "1819", false, same),
case(100u8, val!(100u8), "1864", false, same),
case(100u16, val!(100u16), "1864", false, same),
case(100u32, val!(100u32), "1864", false, same),
case(100u64, val!(100u64), "1864", false, same),
case(100u128, val!(100u128), "1864", false, same),
case(100i8, val!(100i8), "1864", false, same),
case(100i16, val!(100i16), "1864", false, same),
case(100i32, val!(100i32), "1864", false, same),
case(100i64, val!(100i64), "1864", false, same),
case(100i128, val!(100i128), "1864", false, same),
case(1000u16, val!(1000u16), "1903e8", false, same),
case(1000u32, val!(1000u32), "1903e8", false, same),
case(1000u64, val!(1000u64), "1903e8", false, same),
case(1000u128, val!(1000u128), "1903e8", false, same),
case(1000i16, val!(1000i16), "1903e8", false, same),
case(1000i32, val!(1000i32), "1903e8", false, same),
case(1000i64, val!(1000i64), "1903e8", false, same),
case(1000i128, val!(1000i128), "1903e8", false, same),
case(1000000u32, val!(1000000u32), "1a000f4240", false, same),
case(1000000u64, val!(1000000u64), "1a000f4240", false, same),
case(1000000u128, val!(1000000u128), "1a000f4240", false, same),
case(1000000i32, val!(1000000i32), "1a000f4240", false, same),
case(1000000i64, val!(1000000i64), "1a000f4240", false, same),
case(1000000i128, val!(1000000i128), "1a000f4240", false, same),
case(1000000000000u64, val!(1000000000000u64), "1b000000e8d4a51000", false, same),
case(1000000000000u128, val!(1000000000000u128), "1b000000e8d4a51000", false, same),
case(1000000000000i64, val!(1000000000000i64), "1b000000e8d4a51000", false, same),
case(1000000000000i128, val!(1000000000000i128), "1b000000e8d4a51000", false, same),
case(18446744073709551615u64, val!(18446744073709551615u64), "1bffffffffffffffff", false, same),
case(18446744073709551615u128, val!(18446744073709551615u128), "1bffffffffffffffff", false, same),
case(18446744073709551615i128, val!(18446744073709551615i128), "1bffffffffffffffff", false, same),
case(18446744073709551616u128, val!(18446744073709551616u128), "c249010000000000000000", false, same),
case(18446744073709551616i128, val!(18446744073709551616i128), "c249010000000000000000", false, same),
case(-18446744073709551617i128, val!(-18446744073709551617i128), "c349010000000000000000", false, same),
case(-18446744073709551616i128, val!(-18446744073709551616i128), "3bffffffffffffffff", false, same),
case(-1000i16, val!(-1000i16), "3903e7", false, same),
case(-1000i32, val!(-1000i32), "3903e7", false, same),
case(-1000i64, val!(-1000i64), "3903e7", false, same),
case(-1000i128, val!(-1000i128), "3903e7", false, same),
case(-100i8, val!(-100i8), "3863", false, same),
case(-100i16, val!(-100i16), "3863", false, same),
case(-100i32, val!(-100i32), "3863", false, same),
case(-100i64, val!(-100i64), "3863", false, same),
case(-100i128, val!(-100i128), "3863", false, same),
case(-10i8, val!(-10i8), "29", false, same),
case(-10i16, val!(-10i16), "29", false, same),
case(-10i32, val!(-10i32), "29", false, same),
case(-10i64, val!(-10i64), "29", false, same),
case(-10i128, val!(-10i128), "29", false, same),
case(-1i8, val!(-1i8), "20", false, same),
case(-1i16, val!(-1i16), "20", false, same),
case(-1i32, val!(-1i32), "20", false, same),
case(-1i64, val!(-1i64), "20", false, same),
case(-1i128, val!(-1i128), "20", false, same),
case(-1i8, val!(-1i8), "3b0000000000000000", true, same),
case(-1i16, val!(-1i16), "3b0000000000000000", true, same),
case(-1i32, val!(-1i32), "3b0000000000000000", true, same),
case(-1i64, val!(-1i64), "3b0000000000000000", true, same),
case(-1i128, val!(-1i128), "3b0000000000000000", true, same),
case(0.0f32, val!(0.0f32), "f90000", false, Float),
case(0.0f64, val!(0.0f64), "f90000", false, Float),
case(-0.0f32, val!(-0.0f32), "f98000", false, Float),
case(-0.0f64, val!(-0.0f64), "f98000", false, Float),
case(1.0f32, val!(1.0f32), "f93c00", false, Float),
case(1.0f64, val!(1.0f64), "f93c00", false, Float),
case(1.1f32, val!(1.1f32), "fa3f8ccccd", false, Float), // Not In RFC
case(1.1f64, val!(1.1f64), "fb3ff199999999999a", false, Float),
case(1.5f32, val!(1.5f32), "f93e00", false, Float),
case(1.5f64, val!(1.5f64), "f93e00", false, Float),
case(65504.0f32, val!(65504.0f32), "f97bff", false, Float),
case(65504.0f64, val!(65504.0f64), "f97bff", false, Float),
case(100000.0f32, val!(100000.0f32), "fa47c35000", false, Float),
case(100000.0f64, val!(100000.0f64), "fa47c35000", false, Float),
case(3.4028234663852886e+38f32, val!(3.4028234663852886e+38f32), "fa7f7fffff", false, Float),
case(3.4028234663852886e+38f64, val!(3.4028234663852886e+38f64), "fa7f7fffff", false, Float),
case(1.0e+300f64, val!(1.0e+300f64), "fb7e37e43c8800759c", false, Float),
case(5.960464477539063e-8f32, val!(5.960464477539063e-8f32), "f90001", false, Float),
case(5.960464477539063e-8f64, val!(5.960464477539063e-8f64), "f90001", false, Float),
case(0.00006103515625f32, val!(0.00006103515625f32), "f90400", false, Float),
case(0.00006103515625f64, val!(0.00006103515625f64), "f90400", false, Float),
case(-4.0f32, val!(-4.0f32), "f9c400", false, Float),
case(-4.0f64, val!(-4.0f64), "f9c400", false, Float),
case(-4.1f32, val!(-4.1f32), "fac0833333", false, Float), // Not In RFC
case(-4.1f64, val!(-4.1f64), "fbc010666666666666", false, Float),
case(core::f32::INFINITY, val!(core::f32::INFINITY), "f97c00", false, Float),
case(core::f64::INFINITY, val!(core::f64::INFINITY), "f97c00", false, Float),
case(core::f32::INFINITY, val!(core::f32::INFINITY), "fa7f800000", true, Float),
case(core::f64::INFINITY, val!(core::f64::INFINITY), "fa7f800000", true, Float),
case(core::f32::INFINITY, val!(core::f32::INFINITY), "fb7ff0000000000000", true, Float),
case(core::f64::INFINITY, val!(core::f64::INFINITY), "fb7ff0000000000000", true, Float),
case(-core::f32::INFINITY, val!(-core::f32::INFINITY), "f9fc00", false, Float),
case(-core::f64::INFINITY, val!(-core::f64::INFINITY), "f9fc00", false, Float),
case(-core::f32::INFINITY, val!(-core::f32::INFINITY), "faff800000", true, Float),
case(-core::f64::INFINITY, val!(-core::f64::INFINITY), "faff800000", true, Float),
case(-core::f32::INFINITY, val!(-core::f32::INFINITY), "fbfff0000000000000", true, Float),
case(-core::f64::INFINITY, val!(-core::f64::INFINITY), "fbfff0000000000000", true, Float),
case(core::f32::NAN, val!(core::f32::NAN), "f97e00", false, Float),
case(core::f64::NAN, val!(core::f64::NAN), "f97e00", false, Float),
case(core::f32::NAN, val!(core::f32::NAN), "fa7fc00000", true, Float),
case(core::f64::NAN, val!(core::f64::NAN), "fa7fc00000", true, Float),
case(core::f32::NAN, val!(core::f32::NAN), "fb7ff8000000000000", true, Float),
case(core::f64::NAN, val!(core::f64::NAN), "fb7ff8000000000000", true, Float),
case(-core::f32::NAN, val!(-core::f32::NAN), "f9fe00", false, Float), // Not In RFC
case(-core::f64::NAN, val!(-core::f64::NAN), "f9fe00", false, Float), // Not In RFC
case(-core::f32::NAN, val!(-core::f32::NAN), "faffc00000", true, Float), // Not In RFC
case(-core::f64::NAN, val!(-core::f64::NAN), "faffc00000", true, Float), // Not In RFC
case(-core::f32::NAN, val!(-core::f32::NAN), "fbfff8000000000000", true, Float), // Not In RFC
case(-core::f64::NAN, val!(-core::f64::NAN), "fbfff8000000000000", true, Float), // Not In RFC
case(false, val!(false), "f4", false, same),
case(true, val!(true), "f5", false, same),
case(Value::Null, Value::Null, "f6", false, same),
case(hex!(""), val!(&b""[..]), "40", false, same),
case(hex!("01020304"), val!(&b"\x01\x02\x03\x04"[..]), "4401020304", false, same),
case(hex!("0102030405"), val!(&b"\x01\x02\x03\x04\x05"[..]), "5f42010243030405ff", true, same),
case("", val!(""), "60", false, ToOwned::to_owned),
case("a", val!("a"), "6161", false, ToOwned::to_owned),
case('a', val!('a'), "6161", false, same),
case("IETF", val!("IETF"), "6449455446", false, ToOwned::to_owned),
case("\"\\", val!("\"\\"), "62225c", false, ToOwned::to_owned),
case("ü", val!("ü"), "62c3bc", false, ToOwned::to_owned),
case('ü', val!('ü'), "62c3bc", false, same),
case("水", val!("水"), "63e6b0b4", false, ToOwned::to_owned),
case('水', val!('水'), "63e6b0b4", false, same),
case("𐅑", val!("𐅑"), "64f0908591", false, ToOwned::to_owned),
case('𐅑', val!('𐅑'), "64f0908591", false, same),
case("streaming", val!("streaming"), "7f657374726561646d696e67ff", true, ToOwned::to_owned),
case(cbor!([]).unwrap(), Vec::<Value>::new().into(), "80", false, same),
case(cbor!([]).unwrap(), Vec::<Value>::new().into(), "9fff", true, same),
case(cbor!([1, 2, 3]).unwrap(), cbor!([1, 2, 3]).unwrap(), "83010203", false, same),
case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "8301820203820405", false, same),
case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "9f018202039f0405ffff", true, same),
case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "9f01820203820405ff", true, same),
case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "83018202039f0405ff", true, same),
case(cbor!([1, [2, 3], [4, 5]]).unwrap(), cbor!([1, [2, 3], [4, 5]]).unwrap(), "83019f0203ff820405", true, same),
case((1..=25).collect::<Vec<u8>>(), (1..=25).map(|x| x.into()).collect::<Vec<Value>>().into(), "98190102030405060708090a0b0c0d0e0f101112131415161718181819", false, same),
case((1..=25).collect::<Vec<u8>>(), (1..=25).map(|x| x.into()).collect::<Vec<Value>>().into(), "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff", true, same),
case(HashMap::<u8, u8>::new(), Value::Map(vec![]), "a0", false, same),
case(BTreeMap::<u8, u8>::new(), Value::Map(vec![]), "a0", false, same),
case(map!{1 => 2, 3 => 4}, cbor!({1 => 2, 3 => 4}).unwrap(), "a201020304", false, same),
case(cbor!({"a" => 1, "b" => [2, 3]}).unwrap(), cbor!({"a" => 1, "b" => [2, 3]}).unwrap(), "a26161016162820203", false, same),
case(cbor!({"a" => 1, "b" => [2, 3]}).unwrap(), cbor!({"a" => 1, "b" => [2, 3]}).unwrap(), "bf61610161629f0203ffff", true, same),
case(cbor!(["a", {"b" => "c"}]).unwrap(), cbor!(["a", {"b" => "c"}]).unwrap(), "826161a161626163", false, same),
case(cbor!(["a", {"b" => "c"}]).unwrap(), cbor!(["a", {"b" => "c"}]).unwrap(), "826161bf61626163ff", true, same),
case(cbor!({"Fun" => true, "Amt" => -2}).unwrap(), cbor!({"Fun" => true, "Amt" => -2}).unwrap(), "bf6346756ef563416d7421ff", true, same),
case(map_big(), vmap_big(), "a56161614161626142616361436164614461656145", false, same),
case(Option::<u8>::None, Value::Null, "f6", false, same), // Not In RFC
case(Option::Some(7u8), val!(7u8), "07", false, same), // Not In RFC
case((), Value::Null, "f6", false, same), // Not In RFC
case(UnitStruct, Value::Null, "f6", false, same), // Not In RFC
case(Newtype(123), val!(123u8), "187b", false, same), // Not In RFC
case((22u8, 23u16), cbor!([22, 23]).unwrap(), "821617", false, same), // Not In RFC
case(TupleStruct(33, 34), cbor!([33, 34]).unwrap(), "8218211822", false, same), // Not In RFC
case(Enum::Unit, cbor!("Unit").unwrap(), "64556e6974", false, same), // Not In RFC
case(Enum::Newtype(45), cbor!({"Newtype" => 45}).unwrap(), "a1674e657774797065182d", false, same), // Not In RFC
case(Enum::Tuple(56, 67), cbor!({"Tuple" => [56, 67]}).unwrap(), "a1655475706c658218381843", false, same), // Not In RFC
case(Enum::Struct { first: 78, second: 89 }, cbor!({ "Struct" => { "first" => 78, "second" => 89 }}).unwrap(), "a166537472756374a2656669727374184e667365636f6e641859", false, same), // Not In RFC
)]
fn codec<'de, T: Serialize + Clone, V: Debug + PartialEq + Deserialize<'de>, F: Fn(T) -> V>(
input: T,
value: Value,
bytes: &str,
alternate: bool,
equality: F,
) {
let bytes = hex::decode(bytes).unwrap();
if !alternate {
let mut encoded = Vec::new();
into_writer(&input, &mut encoded).unwrap();
eprintln!("{:x?} == {:x?}", bytes, encoded);
assert_eq!(bytes, encoded);
let mut encoded = Vec::new();
into_writer(&value, &mut encoded).unwrap();
eprintln!("{:x?} == {:x?}", bytes, encoded);
assert_eq!(bytes, encoded);
let encoded = Value::serialized(&input).unwrap();
eprintln!("{:x?} == {:x?}", &value, &encoded);
assert!(veq(&value, &encoded));
}
let decoded: V = from_reader(&bytes[..]).unwrap();
let answer = equality(input.clone());
eprintln!("{:x?} == {:x?}", answer, decoded);
assert_eq!(answer, decoded);
let decoded: Value = from_reader(&bytes[..]).unwrap();
eprintln!("{:x?} == {:x?}", &value, &decoded);
assert!(veq(&value, &decoded));
let decoded: V = value.deserialized().unwrap();
let answer = equality(input);
eprintln!("{:x?} == {:x?}", answer, decoded);
assert_eq!(answer, decoded);
}
#[inline]
fn veq(lhs: &Value, rhs: &Value) -> bool {
if let Value::Float(l) = lhs {
if let Value::Float(r) = rhs {
return Float(*l) == Float(*r);
}
}
lhs == rhs
}
#[inline]
fn same<T>(x: T) -> T {
x
}
#[derive(Debug, Deserialize)]
struct Float<T>(T);
impl PartialEq for Float<f32> {
fn eq(&self, other: &Float<f32>) -> bool {
if self.0.is_nan() && other.0.is_nan() {
return true;
}
self.0 == other.0
}
}
impl PartialEq for Float<f64> {
fn eq(&self, other: &Float<f64>) -> bool {
if self.0.is_nan() && other.0.is_nan() {
return true;
}
self.0 == other.0
}
}
#[inline]
fn map_big() -> BTreeMap<String, String> {
let mut map = BTreeMap::new();
map.insert("a".into(), "A".into());
map.insert("b".into(), "B".into());
map.insert("c".into(), "C".into());
map.insert("d".into(), "D".into());
map.insert("e".into(), "E".into());
map
}
#[inline]
fn vmap_big() -> Value {
Value::Map(
map_big()
.into_iter()
.map(|x| (x.0.into(), x.1.into()))
.collect(),
)
}
#[inline]
fn bigint() -> Value {
let bytes = hex::decode("0000000000000000000000000000000000000001").unwrap();
Value::Tag(2, Value::Bytes(bytes).into())
}
#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, Eq)]
struct UnitStruct;
#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, Eq)]
struct TupleStruct(u8, u16);
#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, Eq)]
struct Newtype(u8);
#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, Eq)]
enum Enum {
Unit,
Newtype(u8),
Tuple(u8, u16),
Struct { first: u8, second: u16 },
}