use rapira::{Rapira, RapiraFlags};
#[test]
fn ctx_flags_none_is_zero() {
assert_eq!(RapiraFlags::NONE.0, 0);
assert_eq!(RapiraFlags::default(), RapiraFlags::NONE);
}
#[test]
fn ctx_flags_operations() {
let flags = RapiraFlags::NONE.with(1).with(4);
assert!(flags.has(1));
assert!(flags.has(4));
assert!(!flags.has(2));
assert!(!flags.has(8));
}
#[test]
fn ctx_flags_with_is_or() {
let a = RapiraFlags::new(0b0101);
let b = a.with(0b1010);
assert_eq!(b.0, 0b1111);
}
#[test]
fn ctx_default_same_as_plain_u32() {
let val: u32 = 42;
let plain = rapira::serialize(&val);
let ctx = rapira::serialize_ctx(&val, RapiraFlags::NONE);
assert_eq!(plain, ctx);
let decoded: u32 = rapira::deserialize_ctx(&ctx, RapiraFlags::NONE).unwrap();
assert_eq!(decoded, val);
}
#[test]
fn ctx_default_same_as_plain_string() {
let val = String::from("hello rapira");
let plain = rapira::serialize(&val);
let ctx = rapira::serialize_ctx(&val, RapiraFlags::NONE);
assert_eq!(plain, ctx);
}
#[derive(rapira::Rapira, Debug, PartialEq)]
struct Msg {
x: u32,
name: String,
}
#[test]
fn ctx_default_struct() {
let msg = Msg {
x: 1,
name: "hello".into(),
};
let plain = rapira::serialize(&msg);
let ctx = rapira::serialize_ctx(&msg, RapiraFlags::NONE);
assert_eq!(plain, ctx);
let decoded: Msg = rapira::deserialize_ctx(&ctx, RapiraFlags::NONE).unwrap();
assert_eq!(decoded, msg);
}
#[derive(rapira::Rapira, Debug, PartialEq)]
struct Pair(u32, u64);
#[test]
fn ctx_default_unnamed_struct() {
let pair = Pair(10, 20);
let plain = rapira::serialize(&pair);
let ctx = rapira::serialize_ctx(&pair, RapiraFlags::NONE);
assert_eq!(plain, ctx);
let decoded: Pair = rapira::deserialize_ctx(&ctx, RapiraFlags::NONE).unwrap();
assert_eq!(decoded, pair);
}
#[derive(rapira::Rapira, Debug, PartialEq)]
enum Action {
Ping,
Send { data: Vec<u8> },
Echo(String),
}
#[test]
fn ctx_roundtrip_enum_unit() {
let val = Action::Ping;
let bytes = rapira::serialize_ctx(&val, RapiraFlags::NONE);
let decoded: Action = rapira::deserialize_ctx(&bytes, RapiraFlags::NONE).unwrap();
assert_eq!(decoded, val);
}
#[test]
fn ctx_roundtrip_enum_named() {
let val = Action::Send {
data: vec![1, 2, 3],
};
let plain = rapira::serialize(&val);
let ctx = rapira::serialize_ctx(&val, RapiraFlags::NONE);
assert_eq!(plain, ctx);
let decoded: Action = rapira::deserialize_ctx(&ctx, RapiraFlags::NONE).unwrap();
assert_eq!(decoded, val);
}
#[test]
fn ctx_roundtrip_enum_unnamed() {
let val = Action::Echo("test".into());
let bytes = rapira::serialize_ctx(&val, RapiraFlags::NONE);
let decoded: Action = rapira::deserialize_ctx(&bytes, RapiraFlags::NONE).unwrap();
assert_eq!(decoded, val);
}
const REVERSE: u64 = 1;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct RevU64(u64);
impl Rapira for RevU64 {
const STATIC_SIZE: Option<usize> = Some(8);
const MIN_SIZE: usize = 8;
fn size(&self) -> usize {
8
}
fn check_bytes(slice: &mut &[u8]) -> rapira::Result<()> {
<[u8; 8] as Rapira>::check_bytes(slice)
}
fn from_slice(slice: &mut &[u8]) -> rapira::Result<Self> {
let bytes = <[u8; 8] as Rapira>::from_slice(slice)?;
Ok(RevU64(u64::from_le_bytes(bytes)))
}
fn convert_to_bytes(&self, slice: &mut [u8], cursor: &mut usize) {
self.0.to_le_bytes().convert_to_bytes(slice, cursor)
}
fn convert_to_bytes_ctx(&self, slice: &mut [u8], cursor: &mut usize, flags: RapiraFlags) {
if flags.has(REVERSE) {
self.0.to_be_bytes().convert_to_bytes(slice, cursor)
} else {
self.convert_to_bytes(slice, cursor)
}
}
fn from_slice_ctx(slice: &mut &[u8], flags: RapiraFlags) -> rapira::Result<Self> {
let bytes = <[u8; 8] as Rapira>::from_slice(slice)?;
if flags.has(REVERSE) {
Ok(RevU64(u64::from_be_bytes(bytes)))
} else {
Ok(RevU64(u64::from_le_bytes(bytes)))
}
}
}
#[test]
fn ctx_reverse_flag_writes_be() {
let val = RevU64(0x0102030405060708);
let be_bytes = rapira::serialize_ctx(&val, RapiraFlags::new(REVERSE));
assert_eq!(be_bytes, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
let le_bytes = rapira::serialize(&val);
assert_eq!(le_bytes, [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
}
#[test]
fn ctx_reverse_flag_deserialize_without_flag_gives_raw() {
let val = RevU64(0x0102030405060708);
let be_bytes = rapira::serialize_ctx(&val, RapiraFlags::new(REVERSE));
let raw: RevU64 = rapira::deserialize(&be_bytes).unwrap();
assert_eq!(raw.0, 0x0807060504030201);
}
#[test]
fn ctx_reverse_flag_roundtrip() {
let val = RevU64(0x0102030405060708);
let be_bytes = rapira::serialize_ctx(&val, RapiraFlags::new(REVERSE));
let decoded: RevU64 = rapira::deserialize_ctx(&be_bytes, RapiraFlags::new(REVERSE)).unwrap();
assert_eq!(decoded.0, 0x0102030405060708);
}
#[test]
fn vec_ctx_propagates_to_elements() {
let items = vec![RevU64(1), RevU64(2), RevU64(3)];
let bytes = rapira::serialize_ctx(&items, RapiraFlags::new(REVERSE));
let decoded: Vec<RevU64> = rapira::deserialize_ctx(&bytes, RapiraFlags::new(REVERSE)).unwrap();
assert_eq!(
decoded.iter().map(|v| v.0).collect::<Vec<_>>(),
vec![1, 2, 3]
);
let wrong: Vec<RevU64> = rapira::deserialize(&bytes).unwrap();
assert_eq!(
wrong.iter().map(|v| v.0).collect::<Vec<_>>(),
vec![1u64.swap_bytes(), 2u64.swap_bytes(), 3u64.swap_bytes()]
);
}
#[test]
fn option_box_tuple_and_maps_ctx_propagate_to_elements() {
use std::collections::{BTreeMap, HashMap};
let opt = Some(RevU64(0x0102030405060708));
let decoded: Option<RevU64> = rapira::deserialize_ctx(
&rapira::serialize_ctx(&opt, RapiraFlags::new(REVERSE)),
RapiraFlags::new(REVERSE),
)
.unwrap();
assert_eq!(decoded.unwrap().0, opt.unwrap().0);
let boxed = Box::new(RevU64(55));
let decoded: Box<RevU64> = rapira::deserialize_ctx(
&rapira::serialize_ctx(&boxed, RapiraFlags::new(REVERSE)),
RapiraFlags::new(REVERSE),
)
.unwrap();
assert_eq!(decoded.0, 55);
let tuple = (RevU64(7), RevU64(8), RevU64(9), RevU64(10));
let decoded: (RevU64, RevU64, RevU64, RevU64) = rapira::deserialize_ctx(
&rapira::serialize_ctx(&tuple, RapiraFlags::new(REVERSE)),
RapiraFlags::new(REVERSE),
)
.unwrap();
assert_eq!(
(decoded.0.0, decoded.1.0, decoded.2.0, decoded.3.0),
(7, 8, 9, 10)
);
let mut bt = BTreeMap::new();
bt.insert(RevU64(1), RevU64(2));
let decoded: BTreeMap<RevU64, RevU64> = rapira::deserialize_ctx(
&rapira::serialize_ctx(&bt, RapiraFlags::new(REVERSE)),
RapiraFlags::new(REVERSE),
)
.unwrap();
assert_eq!(
decoded.iter().map(|(k, v)| (k.0, v.0)).collect::<Vec<_>>(),
vec![(1, 2)]
);
let mut hm = HashMap::new();
hm.insert(RevU64(3), RevU64(4));
let decoded: HashMap<RevU64, RevU64> = rapira::deserialize_ctx(
&rapira::serialize_ctx(&hm, RapiraFlags::new(REVERSE)),
RapiraFlags::new(REVERSE),
)
.unwrap();
assert_eq!(decoded.get(&RevU64(3)).unwrap().0, 4);
}
#[test]
fn arrayvec_ctx_propagates_to_elements() {
use arrayvec::ArrayVec;
let mut arr = ArrayVec::<RevU64, 3>::new();
arr.push(RevU64(11));
arr.push(RevU64(22));
arr.push(RevU64(33));
assert!(arr.is_full());
let bytes = rapira::serialize_ctx(&arr, RapiraFlags::new(REVERSE));
let decoded: ArrayVec<RevU64, 3> =
rapira::deserialize_ctx(&bytes, RapiraFlags::new(REVERSE)).unwrap();
assert_eq!(decoded.len(), 3);
assert!(decoded.is_full());
assert_eq!(decoded.capacity(), arr.capacity());
assert_eq!(decoded.as_slice()[0].0, 11);
assert_eq!(decoded.as_slice()[1].0, 22);
assert_eq!(decoded.as_slice()[2].0, 33);
let wrong: ArrayVec<RevU64, 3> = rapira::deserialize(&bytes).unwrap();
assert_eq!(
wrong.as_slice().iter().map(|v| v.0).collect::<Vec<_>>(),
vec![11u64.swap_bytes(), 22u64.swap_bytes(), 33u64.swap_bytes()],
);
}
#[cfg(feature = "smallvec")]
#[test]
fn smallvec_ctx_propagates_to_elements() {
use smallvec::SmallVec;
let mut sv: SmallVec<[RevU64; 4]> = SmallVec::new();
sv.push(RevU64(99));
sv.push(RevU64(100));
let bytes = rapira::serialize_ctx(&sv, RapiraFlags::new(REVERSE));
let decoded: SmallVec<[RevU64; 4]> =
rapira::deserialize_ctx(&bytes, RapiraFlags::new(REVERSE)).unwrap();
assert_eq!(decoded.len(), 2);
assert!(decoded.capacity() >= 2);
assert_eq!(decoded[0].0, 99);
assert_eq!(decoded[1].0, 100);
let wrong: SmallVec<[RevU64; 4]> = rapira::deserialize(&bytes).unwrap();
assert_eq!(wrong[0].0, 99u64.swap_bytes());
assert_eq!(wrong[1].0, 100u64.swap_bytes());
}
#[test]
fn ctx_size_matches_plain_size() {
let msg = Msg {
x: 42,
name: "test".into(),
};
assert_eq!(
rapira::size(&msg),
rapira::size_ctx(&msg, RapiraFlags::NONE)
);
}