use crate::Value;
fn check(value: &Value, expected: &[u8]) {
assert_eq!(value.encode(), expected, "encoding mismatch");
let decoded = Value::decode(expected).expect("decode failed");
assert_eq!(&decoded, value, "decoding mismatch");
}
fn check_bits(value: &Value, expected: &[u8]) {
assert_eq!(value.encode(), expected, "encoding mismatch");
let decoded = Value::decode(expected).expect("decode failed");
assert_eq!(decoded.encode(), expected, "roundtrip mismatch");
}
#[test]
fn int_0() {
check(&Value::from(0), &[0x00]);
}
#[test]
fn int_neg_1() {
check(&Value::from(-1), &[0x20]);
}
#[test]
fn int_23() {
check(&Value::from(23), &[0x17]);
}
#[test]
fn int_neg_24() {
check(&Value::from(-24), &[0x37]);
}
#[test]
fn int_24() {
check(&Value::from(24), &[0x18, 0x18]);
}
#[test]
fn int_neg_25() {
check(&Value::from(-25), &[0x38, 0x18]);
}
#[test]
fn int_255() {
check(&Value::from(255), &[0x18, 0xff]);
}
#[test]
fn int_neg_256() {
check(&Value::from(-256), &[0x38, 0xff]);
}
#[test]
fn int_256() {
check(&Value::from(256), &[0x19, 0x01, 0x00]);
}
#[test]
fn int_neg_257() {
check(&Value::from(-257), &[0x39, 0x01, 0x00]);
}
#[test]
fn int_65535() {
check(&Value::from(65535), &[0x19, 0xff, 0xff]);
}
#[test]
fn int_neg_65536() {
check(&Value::from(-65536), &[0x39, 0xff, 0xff]);
}
#[test]
fn int_65536() {
check(&Value::from(65536), &[0x1a, 0x00, 0x01, 0x00, 0x00]);
}
#[test]
fn int_neg_65537() {
check(&Value::from(-65537), &[0x3a, 0x00, 0x01, 0x00, 0x00]);
}
#[test]
fn int_4294967295() {
check(&Value::from(4294967295_u64), &[0x1a, 0xff, 0xff, 0xff, 0xff]);
}
#[test]
fn int_neg_4294967296() {
check(&Value::from(-4294967296_i64), &[0x3a, 0xff, 0xff, 0xff, 0xff]);
}
#[test]
fn int_4294967296() {
check(
&Value::from(4294967296_i64),
&[0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00],
);
}
#[test]
fn int_neg_4294967297() {
check(
&Value::from(-4294967297_i64),
&[0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00],
);
}
#[test]
fn int_u64_max() {
check(
&Value::from(u64::MAX),
&[0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn int_neg_u64_max_plus_1() {
check(
&Value::Negative(u64::MAX),
&[0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn bigint_pos_smallest() {
let v = Value::from(u64::MAX as u128 + 1);
check(&v, &[0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}
#[test]
fn bigint_neg_smallest() {
let v = Value::from(-(u64::MAX as i128) - 2);
check(&v, &[0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}
#[test]
fn float_zero() {
check(&Value::from(0.0), &[0xf9, 0x00, 0x00]);
}
#[test]
fn float_neg_zero() {
let v = Value::from(-0.0);
assert_eq!(v.encode(), [0xf9, 0x80, 0x00]);
let decoded = Value::decode([0xf9, 0x80, 0x00]).unwrap();
assert!(matches!(decoded, Value::Float(f) if f.to_f64().to_bits() == (-0.0_f64).to_bits()));
}
#[test]
fn float_infinity() {
check(&Value::from(f64::INFINITY), &[0xf9, 0x7c, 0x00]);
}
#[test]
fn float_neg_infinity() {
check(&Value::from(f64::NEG_INFINITY), &[0xf9, 0xfc, 0x00]);
}
#[test]
fn float_nan() {
check_bits(&Value::from(f64::NAN), &[0xf9, 0x7e, 0x00]);
}
#[test]
fn float_f16_smallest_subnormal() {
check(&Value::from(5.960464477539063e-8), &[0xf9, 0x00, 0x01]);
}
#[test]
fn float_f16_largest_subnormal() {
check(&Value::from(0.00006097555160522461), &[0xf9, 0x03, 0xff]);
}
#[test]
fn float_f16_smallest_normal() {
check(&Value::from(0.00006103515625), &[0xf9, 0x04, 0x00]);
}
#[test]
fn float_f16_largest() {
check(&Value::from(65504.0), &[0xf9, 0x7b, 0xff]);
}
#[test]
fn float_f32_smallest_subnormal() {
check(&Value::from(1.401298464324817e-45), &[0xfa, 0x00, 0x00, 0x00, 0x01]);
}
#[test]
fn float_f32_largest_subnormal() {
check(&Value::from(1.1754942106924411e-38), &[0xfa, 0x00, 0x7f, 0xff, 0xff]);
}
#[test]
fn float_f32_smallest_normal() {
check(&Value::from(1.1754943508222875e-38), &[0xfa, 0x00, 0x80, 0x00, 0x00]);
}
#[test]
fn float_f32_largest() {
check(&Value::from(3.4028234663852886e+38), &[0xfa, 0x7f, 0x7f, 0xff, 0xff]);
}
#[test]
fn float_f64_smallest_subnormal() {
check(
&Value::from(5.0e-324),
&[0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_f64_largest_subnormal() {
check(
&Value::from(2.225073858507201e-308),
&[0xfb, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_f64_smallest_normal() {
check(
&Value::from(2.2250738585072014e-308),
&[0xfb, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
);
}
#[test]
fn float_f64_largest() {
check(
&Value::from(1.7976931348623157e+308),
&[0xfb, 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_random_negative() {
check(
&Value::from(-0.0000033333333333333333),
&[0xfb, 0xbe, 0xcb, 0xf6, 0x47, 0x61, 0x2f, 0x36, 0x96],
);
}
#[test]
fn float_f32_random() {
check(&Value::from(10.559998512268066), &[0xfa, 0x41, 0x28, 0xf5, 0xc1]);
}
#[test]
fn float_f64_next_in_succession() {
check(
&Value::from(10.559998512268068),
&[0xfb, 0x40, 0x25, 0x1e, 0xb8, 0x20, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_2_pow_68() {
check(&Value::from(295147905179352830000.0), &[0xfa, 0x61, 0x80, 0x00, 0x00]);
}
#[test]
fn float_two() {
check(&Value::from(2.0), &[0xf9, 0x40, 0x00]);
}
#[test]
fn float_neg_f16_smallest_subnormal() {
check(&Value::from(-5.960464477539063e-8), &[0xf9, 0x80, 0x01]);
}
#[test]
fn float_adjacent_neg_f16_subnormal_lower() {
check(
&Value::from(-5.960464477539062e-8),
&[0xfb, 0xbe, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_adjacent_neg_f16_subnormal_upper() {
check(
&Value::from(-5.960464477539064e-8),
&[0xfb, 0xbe, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_adjacent_neg_f16_subnormal_f32() {
check(&Value::from(-5.960465188081798e-8), &[0xfa, 0xb3, 0x80, 0x00, 0x01]);
}
#[test]
fn float_adjacent_f16_largest_subnormal_lower() {
check(
&Value::from(0.0000609755516052246),
&[0xfb, 0x3f, 0x0f, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_adjacent_f16_largest_subnormal_upper() {
check(
&Value::from(0.000060975551605224616),
&[0xfb, 0x3f, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_adjacent_f16_largest_subnormal_f32() {
check(&Value::from(0.000060975555243203416), &[0xfa, 0x38, 0x7f, 0xc0, 0x01]);
}
#[test]
fn float_adjacent_f16_smallest_normal_lower() {
check(
&Value::from(0.00006103515624999999),
&[0xfb, 0x3f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_adjacent_f16_smallest_normal_upper() {
check(
&Value::from(0.00006103515625000001),
&[0xfb, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_adjacent_f16_smallest_normal_f32() {
check(&Value::from(0.00006103516352595761), &[0xfa, 0x38, 0x80, 0x00, 0x01]);
}
#[test]
fn float_adjacent_f16_largest_lower() {
check(
&Value::from(65503.99999999999),
&[0xfb, 0x40, 0xef, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_adjacent_f16_largest_upper() {
check(
&Value::from(65504.00000000001),
&[0xfb, 0x40, 0xef, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_adjacent_f16_largest_f32() {
check(&Value::from(65504.00390625), &[0xfa, 0x47, 0x7f, 0xe0, 0x01]);
}
#[test]
fn float_adjacent_f32_smallest_subnormal_lower() {
check(
&Value::from(1.4012984643248169e-45),
&[0xfb, 0x36, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_adjacent_f32_smallest_subnormal_upper() {
check(
&Value::from(1.4012984643248174e-45),
&[0xfb, 0x36, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_adjacent_f32_largest_subnormal_lower() {
check(
&Value::from(1.175494210692441e-38),
&[0xfb, 0x38, 0x0f, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_adjacent_f32_largest_subnormal_upper() {
check(
&Value::from(1.1754942106924412e-38),
&[0xfb, 0x38, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_adjacent_f32_smallest_normal_lower() {
check(
&Value::from(1.1754943508222874e-38),
&[0xfb, 0x38, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_adjacent_f32_smallest_normal_upper() {
check(
&Value::from(1.1754943508222878e-38),
&[0xfb, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
);
}
#[test]
fn float_adjacent_f32_largest_lower() {
check(
&Value::from(3.4028234663852882e+38),
&[0xfb, 0x47, 0xef, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff],
);
}
#[test]
fn float_adjacent_f32_largest_upper() {
check(
&Value::from(3.402823466385289e+38),
&[0xfb, 0x47, 0xef, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01],
);
}
#[test]
fn misc_true() {
check(&Value::from(true), &[0xf5]);
}
#[test]
fn misc_null() {
check(&Value::null(), &[0xf6]);
}
#[test]
fn misc_simple_99() {
check(&Value::simple_value(99), &[0xf8, 0x63]);
}
#[test]
fn misc_tagged_date() {
let v = Value::tag(0, "2025-03-30T12:24:16Z");
check(
&v,
&[
0xc0, 0x74, 0x32, 0x30, 0x32, 0x35, 0x2d, 0x30, 0x33, 0x2d, 0x33, 0x30, 0x54, 0x31, 0x32, 0x3a, 0x32, 0x34,
0x3a, 0x31, 0x36, 0x5a,
],
);
}
#[test]
fn misc_nested_arrays() {
let v = Value::from([Value::from(1), Value::array([2, 3]), Value::array([4, 5])]);
check(&v, &[0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05]);
}
#[test]
fn misc_map() {
use std::collections::BTreeMap;
let mut map = BTreeMap::new();
map.insert(Value::from("a"), Value::from(0));
map.insert(Value::from("b"), Value::from(1));
map.insert(Value::from("aa"), Value::from(2));
let v = Value::Map(map);
check(&v, &[0xa3, 0x61, 0x61, 0x00, 0x61, 0x62, 0x01, 0x62, 0x61, 0x61, 0x02]);
}
#[test]
fn misc_byte_string() {
let v = Value::from(b"Hello CBOR!");
check(
&v,
&[0x4b, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x43, 0x42, 0x4f, 0x52, 0x21],
);
}
#[test]
fn misc_text_string_emoji() {
let v = Value::from("🚀 science");
check(
&v,
&[
0x6c, 0xf0, 0x9f, 0x9a, 0x80, 0x20, 0x73, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x65,
],
);
}
#[test]
fn misc_nan_with_payload_f32() {
let v = Value::from(f32::from_bits(0x7f800001));
check_bits(&v, &[0xfa, 0x7f, 0x80, 0x00, 0x01]);
}
#[test]
fn misc_nan_with_payload_and_sign() {
let v = Value::from(f64::from_bits(0xfff0001230000000));
check_bits(&v, &[0xfb, 0xff, 0xf0, 0x00, 0x12, 0x30, 0x00, 0x00, 0x00]);
}
fn check_reject(bytes: &[u8]) {
assert!(
Value::decode(bytes).is_err(),
"expected decode to reject: {:02x?}",
bytes,
);
}
#[test]
fn invalid_improper_map_key_ordering() {
check_reject(&[0xa2, 0x61, 0x62, 0x01, 0x61, 0x61, 0x00]);
}
#[test]
fn invalid_array_length_leading_zero() {
check_reject(&[0x98, 0x02, 0x04, 0x05]);
}
#[test]
fn invalid_integer_leading_zero() {
check_reject(&[0x19, 0x00, 0xff]);
}
#[test]
fn invalid_bigint_leading_zero() {
check_reject(&[0xc3, 0x4a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}
#[test]
fn invalid_float_not_shortest_10_point_5() {
check_reject(&[0xfa, 0x41, 0x28, 0x00, 0x00]);
}
#[test]
fn invalid_float_not_shortest_nan() {
check_reject(&[0xfa, 0x7f, 0xc0, 0x00, 0x00]);
}
#[test]
fn invalid_float_not_shortest_nan_payload() {
check_reject(&[0xfa, 0x7f, 0xff, 0xe0, 0x00]);
}
#[test]
fn invalid_bigint_fits_in_u64() {
check_reject(&[0xc2, 0x43, 0x01, 0x00, 0x00]);
}
#[test]
fn invalid_indefinite_length() {
check_reject(&[0x5f, 0x41, 0x01, 0x42, 0x02, 0x03, 0xff]);
}
#[test]
fn invalid_reserved_info_byte() {
check_reject(&[0xfc]);
}
#[test]
fn invalid_simple_value_encoding() {
check_reject(&[0xf8, 0x18]);
}
#[test]
fn invalid_extremely_large_length() {
check_reject(&[0x5b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}