use binprot::macros::{BinProtRead, BinProtWrite};
use binprot::{BinProtRead, BinProtSize, BinProtWrite};
fn test_roundtrip<T>(t: T, sz: usize, vs: Option<&[u8]>)
where
T: BinProtRead + BinProtWrite + PartialEq + std::fmt::Debug,
{
assert_eq!(t.binprot_size(), sz);
let mut data: Vec<u8> = Vec::new();
t.binprot_write(&mut data).unwrap();
let mut slice = data.as_slice();
if let Some(vs) = vs {
assert_eq!(slice, vs);
}
let flipped = T::binprot_read(&mut slice).unwrap();
assert_eq!(t, flipped)
}
#[derive(BinProtRead, BinProtWrite, Debug, PartialEq)]
struct Pancakes(i64);
#[test]
fn breakfast1() {
test_roundtrip(Pancakes(12), 1, Some(&[12]));
test_roundtrip(Pancakes(0), 1, Some(&[0]));
test_roundtrip(Pancakes(-1), 2, Some(&[255, 255]));
test_roundtrip(Pancakes(12345678910111213), 9, Some(&[252, 237, 189, 242, 93, 84, 220, 43, 0]));
}
#[derive(BinProtRead, BinProtWrite, Debug, PartialEq)]
struct MorePancakes(i64, f64, i64);
#[test]
fn breakfast2() {
test_roundtrip(
MorePancakes(12, 3.141592, 1234567890123),
18,
Some(&[12, 122, 0, 139, 252, 250, 33, 9, 64, 252, 203, 4, 251, 113, 31, 1, 0, 0]),
);
}
#[derive(BinProtRead, BinProtWrite, Debug, PartialEq)]
struct Breakfasts {
pancakes: Pancakes,
more_pancakes: MorePancakes,
value1: i64,
value2: (f64, f64),
}
#[test]
fn breakfast3() {
let breakfasts = Breakfasts {
pancakes: Pancakes(12),
more_pancakes: MorePancakes(-123, 2.71828182846, 0),
value1: -1234567890123456,
value2: (3.141592, 6535.8979),
};
let expected = [
12, 255, 133, 207, 95, 20, 139, 10, 191, 5, 64, 0, 252, 64, 69, 117, 195, 42, 157, 251,
255, 122, 0, 139, 252, 250, 33, 9, 64, 20, 63, 198, 220, 229, 135, 185, 64,
];
test_roundtrip(breakfasts, 37, Some(&expected))
}
#[derive(BinProtWrite, BinProtRead, Debug, PartialEq)]
enum BreakfastMenu<T> {
Any(T),
Eggs(i64),
Pancakes(Pancakes),
MorePancakes(MorePancakes),
LotsOfPancakes(Pancakes, MorePancakes),
Everything { eggs: i64, pancakes: i64 },
Nothing,
}
#[test]
fn breakfast4() {
let breakfast: BreakfastMenu<BreakfastMenu<i64>> =
BreakfastMenu::Any(BreakfastMenu::Everything { eggs: 123, pancakes: 456 });
let expected = [0, 5, 123, 254, 200, 1];
test_roundtrip(breakfast, 6, Some(&expected));
test_roundtrip(BreakfastMenu::<i64>::Nothing, 1, None);
let expected = [1, 42];
test_roundtrip(BreakfastMenu::<i64>::Eggs(42), 2, Some(&expected));
test_roundtrip(binprot::WithLen(BreakfastMenu::<i64>::Eggs(42)), 3, Some(&[2, 1, 42]));
}
#[derive(BinProtWrite, BinProtRead, Debug, PartialEq)]
struct BreakfastItem {
name: String,
quantity: f64,
large: bool,
}
#[test]
fn breakfast5() {
let expected = [3, 101, 103, 103, 111, 18, 131, 192, 202, 33, 9, 64, 1];
test_roundtrip(
BreakfastItem { name: "egg".to_string(), quantity: 3.1415, large: true },
13,
Some(&expected),
);
let expected = [9, 99, 114, 111, 105, 115, 115, 97, 110, 116, 0, 0, 0, 0, 128, 28, 200, 192, 0];
test_roundtrip(
BreakfastItem { name: "croissant".to_string(), quantity: -12345., large: false },
19,
Some(&expected),
);
let expected = [
14, 80, 97, 105, 110, 65, 117, 67, 104, 111, 99, 111, 108, 97, 116, 0, 0, 0, 74, 120, 222,
177, 65, 0,
];
test_roundtrip(
BreakfastItem { name: "PainAuChocolat".to_string(), quantity: 299792458.0, large: false },
24,
Some(&expected),
);
}
#[derive(BinProtWrite, BinProtRead, Debug, PartialEq)]
#[polymorphic_variant]
enum BreakfastPoly<T> {
Any(T),
Eggs(i64),
Pancakes(Pancakes),
MorePancakes(MorePancakes),
LotsOfPancakes(Pancakes, MorePancakes),
Everything { eggs: i64, pancakes: i64 },
Nothing,
}
#[test]
fn breakfast6() {
let breakfast: BreakfastPoly<BreakfastPoly<i64>> =
BreakfastPoly::Any(BreakfastPoly::MorePancakes(MorePancakes(-123, 2.71828182846, 0)));
let expected =
[153, 101, 99, 0, 39, 152, 92, 190, 255, 133, 207, 95, 20, 139, 10, 191, 5, 64, 0];
test_roundtrip(breakfast, 19, Some(&expected));
test_roundtrip(BreakfastPoly::<i64>::Nothing, 4, None);
let expected = [93, 118, 212, 91, 42];
test_roundtrip(BreakfastPoly::<i64>::Eggs(42), 5, Some(&expected));
test_roundtrip(
binprot::WithLen(BreakfastPoly::<i64>::Eggs(42)),
6,
Some(&[5, 93, 118, 212, 91, 42]),
);
}
#[test]
fn breakfast7() {
let price_and_quantities: std::collections::HashMap<String, (i64, f64)> =
[("croissant", (4, 1.23)), ("JusDOrange", (1, 2.34)), ("PainAuChocolat", (2, 1.45))]
.iter()
.map(|(x, y)| (x.to_string(), *y))
.collect();
test_roundtrip(price_and_quantities.clone(), 64, None);
let price_and_quantities: std::collections::BTreeMap<String, (i64, f64)> =
price_and_quantities.into_iter().collect();
test_roundtrip(price_and_quantities, 64, None);
}
#[derive(BinProtRead, BinProtWrite, Debug, PartialEq)]
enum BreakfastRec {
Empty,
Cons(MorePancakes, Box<BreakfastRec>),
}
impl BreakfastRec {
fn create(size: i64) -> BreakfastRec {
let mut res = BreakfastRec::Empty;
for i in 0..size {
res = BreakfastRec::Cons(MorePancakes(i, 3.14, i * i), Box::new(res))
}
res
}
}
#[test]
fn breakfast_rec() {
let breakfast_rec = BreakfastRec::create(0);
let expected = [0];
test_roundtrip(breakfast_rec, 1, Some(&expected));
let breakfast_rec = BreakfastRec::create(1);
let expected = [1, 0, 31, 133, 235, 81, 184, 30, 9, 64, 0, 0];
test_roundtrip(breakfast_rec, 12, Some(&expected));
let breakfast_rec = BreakfastRec::create(5);
let expected = [
1, 4, 31, 133, 235, 81, 184, 30, 9, 64, 16, 1, 3, 31, 133, 235, 81, 184, 30, 9, 64, 9, 1,
2, 31, 133, 235, 81, 184, 30, 9, 64, 4, 1, 1, 31, 133, 235, 81, 184, 30, 9, 64, 1, 1, 0,
31, 133, 235, 81, 184, 30, 9, 64, 0, 0,
];
test_roundtrip(breakfast_rec, 56, Some(&expected));
let breakfast_rec = BreakfastRec::create(10);
test_roundtrip(breakfast_rec, 111, None);
let breakfast_rec = BreakfastRec::create(100);
test_roundtrip(breakfast_rec, 1277, None);
let breakfast_rec = BreakfastRec::create(1000);
test_roundtrip(breakfast_rec, 16357, None);
}
#[derive(BinProtRead, BinProtWrite, Debug, PartialEq)]
struct BreakfastStr {
str: String,
bytes: binprot::Bytes,
}
#[test]
fn breakfast_str() {
let breakfast_str =
BreakfastStr { str: "pancakes".to_string(), bytes: "more-pancakes".to_string().into() };
let expected = [
8, 112, 97, 110, 99, 97, 107, 101, 115, 13, 109, 111, 114, 101, 45, 112, 97, 110, 99, 97,
107, 101, 115,
];
test_roundtrip(breakfast_str, 23, Some(&expected));
let bytes: binprot::Bytes = vec![0, 255, 1, 254].into();
let mut data: Vec<u8> = Vec::new();
bytes.binprot_write(&mut data).unwrap();
let mut slice = data.as_slice();
assert_eq!(slice, [4, 0, 255, 1, 254]);
let bytes2 = binprot::Bytes::binprot_read(&mut slice).unwrap();
assert_eq!(bytes, bytes2);
let err = String::binprot_read(&mut data.as_slice());
assert!(err.is_err())
}