use std::fmt;
use std::vec::Vec;
use rust_alloc::vec;
use crate::context;
use crate::fixed::FixedBytes;
use crate::int::continuation as c;
use crate::int::zigzag as zig;
use crate::int::{Signed, Unsigned};
#[cfg(not(miri))]
const ITER: usize = 10000;
#[cfg(miri)]
const ITER: usize = 100;
#[test]
fn basic_continuation() {
crate::alloc::default(|alloc| {
let cx = context::new_in(alloc);
let mut bytes = FixedBytes::<8>::new();
c::encode(&cx, &mut bytes, 5000u32).unwrap();
assert_eq!(bytes.as_slice(), &[0b1000_1000, 0b0010_0111]);
let cx = context::new_in(alloc);
let number: u32 = c::decode(&cx, bytes.as_slice()).unwrap();
assert_eq!(number, 5000u32);
})
}
#[test]
fn test_continuation_encoding() {
use rand::prelude::*;
fn rt<T>(expected: T)
where
T: PartialEq<T> + fmt::Debug + Unsigned,
{
crate::alloc::default(|alloc| {
let mut out = Vec::new();
let cx = crate::context::new_in(alloc);
c::encode(&cx, &mut out, expected).unwrap();
c::encode(&cx, &mut out, expected).unwrap();
let mut data = out.as_slice();
let cx = context::new_in(alloc);
let a: T = c::decode(&cx, &mut data).unwrap();
let b: T = c::decode(&cx, &mut data).unwrap();
assert!(data.is_empty());
assert_eq!(a, expected);
assert_eq!(b, expected);
})
}
fn encode<T>(value: T) -> Vec<u8>
where
T: Unsigned,
{
crate::alloc::default(|alloc| {
let mut out = Vec::new();
let cx = crate::context::new_in(alloc);
c::encode(&cx, crate::wrap::wrap(&mut out), value).unwrap();
out
})
}
macro_rules! test {
($ty:ty) => {{
rt::<$ty>(0);
rt::<$ty>(1);
rt::<$ty>(42);
rt::<$ty>(127);
rt::<$ty>(128);
rt::<$ty>(128 << 8);
rt::<$ty>(<$ty>::MAX);
let mut rng = StdRng::seed_from_u64(0xfd80fd80fd80fd80);
for _ in 0..ITER {
let value = rng.random::<u64>() as usize;
rt(value);
}
}};
}
test!(usize);
test!(u16);
test!(u32);
test!(u64);
test!(u128);
assert_eq!(encode(1000u128), vec![232, 7]);
}
#[test]
fn test_zigzag() {
assert_eq!(super::zigzag::encode(-1i32), 1u32);
assert_eq!(super::zigzag::encode(-2i32), 3u32);
fn rt<T>(value: T, expected: T::Unsigned)
where
T: fmt::Debug + Signed + PartialEq,
T::Unsigned: fmt::Debug + PartialEq,
{
assert_eq!(zig::encode(value), expected);
assert_eq!(zig::decode(expected), value);
}
macro_rules! test {
($signed:ty, $unsigned:ty) => {
rt::<$signed>(0, 0);
rt::<$signed>(-1, 1);
rt::<$signed>(1, 2);
rt::<$signed>(-2, 3);
rt::<$signed>(2, 4);
rt::<$signed>(<$signed>::MAX, <$unsigned>::MAX - 1);
rt::<$signed>(<$signed>::MIN, <$unsigned>::MAX);
};
}
test!(isize, usize);
test!(i16, u16);
test!(i32, u32);
test!(i64, u64);
test!(i128, u128);
}