use msgpacker::{MsgPacker, MsgPackerBorrowed, Packable as _, Unpackable, UnpackableBorrowed};
use proptest::prelude::*;
mod utils;
#[test]
fn vec_u8_uses_binary_format() {
#[derive(Debug, PartialEq, Eq, MsgPacker)]
struct WithBytes {
data: Vec<u8>,
}
let val = WithBytes {
data: vec![0xde, 0xad, 0xbe, 0xef],
};
let mut bytes = vec![];
let n = val.pack(&mut bytes);
assert_eq!(n, bytes.len());
let tag = bytes[0];
assert!(
matches!(tag, 0xc4 | 0xc5 | 0xc6,),
"expected binary format tag (0xc4..=0xc6), got 0x{:02x}",
tag,
);
assert_eq!(bytes[0], 0xc4); assert_eq!(bytes[1], 4); assert_eq!(&bytes[2..6], &[0xde, 0xad, 0xbe, 0xef]);
let (o, deserialized) = WithBytes::unpack_with_ofs(&bytes).unwrap();
assert_eq!(o, n);
assert_eq!(val, deserialized);
let (p, deserialized_iter) = WithBytes::unpack_iter(bytes).unwrap();
assert_eq!(p, n);
assert_eq!(val, deserialized_iter);
}
#[test]
fn vec_string_uses_array_format() {
#[derive(Debug, PartialEq, Eq, MsgPacker)]
struct WithStrings {
data: Vec<String>,
}
let val = WithStrings {
data: vec!["hello".into(), "world".into()],
};
let mut bytes = vec![];
let n = val.pack(&mut bytes);
assert_eq!(n, bytes.len());
let tag = bytes[0];
assert!(
matches!(tag, 0x90..=0x9f | 0xdc | 0xdd),
"expected array format tag, got 0x{:02x}",
tag,
);
let (o, deserialized) = WithStrings::unpack_with_ofs(&bytes).unwrap();
assert_eq!(o, n);
assert_eq!(val, deserialized);
let (p, deserialized_iter) = WithStrings::unpack_iter(bytes).unwrap();
assert_eq!(p, n);
assert_eq!(val, deserialized_iter);
}
#[test]
fn empty_vec() {
let v: Vec<u8> = vec![];
let mut bytes = vec![];
let n = v.pack(&mut bytes);
let (o, x) = <Vec<u8> as Unpackable>::unpack_with_ofs(&bytes).unwrap();
let (p, y) = <Vec<u8> as Unpackable>::unpack_iter(bytes).unwrap();
assert_eq!(o, n);
assert_eq!(p, n);
assert_eq!(v, x);
assert_eq!(v, y);
}
#[test]
fn empty_str() {
let s = "";
let mut bytes = vec![];
let n = s.pack(&mut bytes);
let (o, x) = String::unpack_with_ofs(&bytes).unwrap();
let (p, y) = String::unpack_iter(bytes).unwrap();
assert_eq!(o, n);
assert_eq!(p, n);
assert_eq!(s, x);
assert_eq!(s, y);
}
proptest! {
#[test]
fn vec(v: Vec<u8>) {
utils::case(v);
}
#[test]
fn str(s: String) {
utils::case(s);
}
#[test]
#[ignore]
fn large_vec(v in prop::collection::vec(any::<u8>(), 0..=u16::MAX as usize * 2)) {
utils::case(v);
}
#[test]
#[ignore]
fn large_str(v in prop::collection::vec(any::<char>(), 0..=u16::MAX as usize * 2)) {
utils::case(v.into_iter().collect::<String>());
}
}
#[test]
fn binary_attr_named_field() {
#[derive(Debug, PartialEq, Eq, MsgPacker)]
struct Wrap {
#[msgpacker(binary)]
data: Vec<u8>,
}
let val = Wrap {
data: vec![0xde, 0xad, 0xbe, 0xef],
};
let bytes = val.pack_to_vec();
assert!(
matches!(bytes[0], 0xc4 | 0xc5 | 0xc6),
"expected BIN tag, got 0x{:02x}",
bytes[0]
);
assert_eq!(bytes[0], 0xc4);
assert_eq!(bytes[1], 4);
assert_eq!(&bytes[2..6], &[0xde, 0xad, 0xbe, 0xef]);
let (n, got) = Wrap::unpack_with_ofs(&bytes).unwrap();
assert_eq!(n, bytes.len());
assert_eq!(val, got);
let (n, got_iter) = Wrap::unpack_iter(bytes).unwrap();
assert_eq!(n, got_iter.data.len() + 2); assert_eq!(val, got_iter);
}
#[test]
fn binary_attr_tuple_field() {
#[derive(Debug, PartialEq, Eq, MsgPacker)]
struct Wrap(#[msgpacker(binary)] Vec<u8>);
let val = Wrap(vec![1, 2, 3]);
let bytes = val.pack_to_vec();
assert!(matches!(bytes[0], 0xc4 | 0xc5 | 0xc6));
let (n, got) = Wrap::unpack_with_ofs(&bytes).unwrap();
assert_eq!(n, bytes.len());
assert_eq!(val, got);
let (n, got_iter) = Wrap::unpack_iter(bytes).unwrap();
assert_eq!(n, got.0.len() + 2);
assert_eq!(val, got_iter);
}
#[test]
fn binary_attr_enum_variant() {
#[derive(Debug, PartialEq, Eq, MsgPacker)]
enum Msg {
Raw {
#[msgpacker(binary)]
payload: Vec<u8>,
},
Text(String),
}
let val = Msg::Raw {
payload: vec![0x01, 0x02, 0x03],
};
let bytes = val.pack_to_vec();
assert!(matches!(bytes[1], 0xc4 | 0xc5 | 0xc6));
let (n, got) = Msg::unpack_with_ofs(&bytes).unwrap();
assert_eq!(n, bytes.len());
assert_eq!(val, got);
let (n2, got_iter) = Msg::unpack_iter(bytes).unwrap();
assert_eq!(n, n2);
assert_eq!(val, got_iter);
}
#[test]
fn binary_attr_option_vec_u8() {
#[derive(Debug, PartialEq, Eq, MsgPacker)]
struct Wrap {
#[msgpacker(binary)]
data: Option<Vec<u8>>,
}
let some = Wrap {
data: Some(vec![0x01, 0x02, 0x03]),
};
let bytes = some.pack_to_vec();
assert!(
matches!(bytes[0], 0xc4 | 0xc5 | 0xc6),
"Some should produce BIN tag, got 0x{:02x}",
bytes[0]
);
let (n, got) = Wrap::unpack_with_ofs(&bytes).unwrap();
assert_eq!(n, bytes.len());
assert_eq!(some, got);
let (_, got_iter) = Wrap::unpack_iter(bytes).unwrap();
assert_eq!(some, got_iter);
let none = Wrap { data: None };
let bytes = none.pack_to_vec();
assert_eq!(bytes[0], 0xc0, "None should produce nil");
let (n, got) = Wrap::unpack_with_ofs(&bytes).unwrap();
assert_eq!(n, bytes.len());
assert_eq!(none, got);
let (_, got_iter) = Wrap::unpack_iter(bytes).unwrap();
assert_eq!(none, got_iter);
}
#[test]
fn binary_attr_borrowed() {
#[derive(Debug, PartialEq, MsgPackerBorrowed)]
struct Wrap {
#[msgpacker(binary)]
data: Vec<u8>,
}
let val = Wrap {
data: vec![0xaa, 0xbb],
};
let bytes = val.pack_to_vec();
assert!(matches!(bytes[0], 0xc4 | 0xc5 | 0xc6));
let (n, got) = Wrap::unpack_with_ofs(&bytes).unwrap();
assert_eq!(n, bytes.len());
assert_eq!(val, got);
}