use binprot::macros::{BinProtRead, BinProtWrite}; use binprot::{BinProtRead, BinProtSize, BinProtWrite}; fn test_roundtrip(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 = 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), }; // Generated in ocaml. 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 { Any(T), Eggs(i64), Pancakes(Pancakes), MorePancakes(MorePancakes), LotsOfPancakes(Pancakes, MorePancakes), Everything { eggs: i64, pancakes: i64 }, Nothing, } #[test] fn breakfast4() { let breakfast: BreakfastMenu> = 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::::Nothing, 1, None); let expected = [1, 42]; test_roundtrip(BreakfastMenu::::Eggs(42), 2, Some(&expected)); test_roundtrip(binprot::WithLen(BreakfastMenu::::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 { Any(T), Eggs(i64), Pancakes(Pancakes), MorePancakes(MorePancakes), LotsOfPancakes(Pancakes, MorePancakes), Everything { eggs: i64, pancakes: i64 }, Nothing, } #[test] fn breakfast6() { let breakfast: BreakfastPoly> = 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::::Nothing, 4, None); let expected = [93, 118, 212, 91, 42]; test_roundtrip(BreakfastPoly::::Eggs(42), 5, Some(&expected)); test_roundtrip( binprot::WithLen(BreakfastPoly::::Eggs(42)), 6, Some(&[5, 93, 118, 212, 91, 42]), ); } #[test] fn breakfast7() { let price_and_quantities: std::collections::HashMap = [("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 = price_and_quantities.into_iter().collect(); test_roundtrip(price_and_quantities, 64, None); } #[derive(BinProtRead, BinProtWrite, Debug, PartialEq)] enum BreakfastRec { Empty, Cons(MorePancakes, Box), } 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 = 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); // The bytes data is not utf8 encoded so result in an error when using String. let err = String::binprot_read(&mut data.as_slice()); assert!(err.is_err()) }