diff --git a/rust/radixbuf/src/serialize.rs b/rust/radixbuf/src/serialize.rs --- a/rust/radixbuf/src/serialize.rs +++ b/rust/radixbuf/src/serialize.rs @@ -6,6 +6,8 @@ use std::mem::transmute; use std::ops::DerefMut; use std::rc::Rc; +use vlqencoding::{VLQEncode, VLQDecode}; + /// Minimal serializable abstraction. pub trait Serialize: Sized { @@ -68,6 +70,46 @@ } } +#[derive(Debug, PartialEq, Copy, Clone)] +pub struct TwentyBytes([u8; 20]); + +impl TwentyBytes { + pub fn new(bytes: [u8; 20]) -> Self { TwentyBytes(bytes) } +} + +impl Serialize for TwentyBytes { + fn write_to(&self, w: &mut W) -> io::Result<()> { w.write_all(&self.0) } + + fn read_from(r: &mut R) -> io::Result { + let mut buf = [0u8; 20]; + r.read_exact(&mut buf)?; + Ok(TwentyBytes(buf)) + } +} + +impl FixedSizedSerialize for TwentyBytes {} + +#[derive(Debug, PartialEq, Clone)] +pub struct VariantBytes(Vec); + +impl VariantBytes { + pub fn new(bytes: Vec) -> Self { VariantBytes(bytes) } +} + +impl Serialize for VariantBytes { + fn write_to(&self, w: &mut W) -> io::Result<()> { + w.write_vlq(self.0.len())?; + w.write_all(&self.0) + } + + fn read_from(r: &mut R) -> io::Result { + let len: usize = r.read_vlq()?; + let mut buf = vec![0u8; len]; + r.read_exact(&mut buf)?; + Ok(VariantBytes(buf)) + } +} + macro_rules! impl_serialize_unsigned { ($T: ty, $S: expr) => { impl Serialize for $T { @@ -94,6 +136,7 @@ #[cfg(test)] mod tests { + use quickcheck::{Arbitrary, Gen}; use serialize::*; use std::boxed::Box; use std::cell::RefCell; @@ -101,6 +144,44 @@ use std::io::Cursor; use std::rc::Rc; + impl Arbitrary for TwentyBytes { + fn arbitrary(gen: &mut G) -> Self { + let x = u64::arbitrary(gen); + let y = u64::arbitrary(gen); + let z = u32::arbitrary(gen); + TwentyBytes::new( + [ + ((z >> 24) & 0xff) as u8, + ((z >> 16) & 0xff) as u8, + ((z >> 8) & 0xff) as u8, + ((z >> 0) & 0xff) as u8, + ((y >> 56) & 0xff) as u8, + ((y >> 48) & 0xff) as u8, + ((y >> 40) & 0xff) as u8, + ((y >> 32) & 0xff) as u8, + ((y >> 24) & 0xff) as u8, + ((y >> 16) & 0xff) as u8, + ((y >> 8) & 0xff) as u8, + ((y >> 0) & 0xff) as u8, + ((x >> 56) & 0xff) as u8, + ((x >> 48) & 0xff) as u8, + ((x >> 40) & 0xff) as u8, + ((x >> 32) & 0xff) as u8, + ((x >> 24) & 0xff) as u8, + ((x >> 16) & 0xff) as u8, + ((x >> 8) & 0xff) as u8, + ((x >> 0) & 0xff) as u8, + ], + ) + } + fn shrink(&self) -> Box> { unimplemented!() } + } + + impl Arbitrary for VariantBytes { + fn arbitrary(gen: &mut G) -> Self { VariantBytes::new(Vec::::arbitrary(gen)) } + fn shrink(&self) -> Box> { unimplemented!() } + } + fn check_round_trip(keys: Vec) -> bool { let mut buf = Buffer(Rc::new(RefCell::new(Cursor::new(vec![])))); let mut offsets: Vec> = vec![]; @@ -117,6 +198,14 @@ } quickcheck! { + fn test_round_trip_twentybytes(v: Vec) -> bool { + check_round_trip(v) + } + + fn test_round_trip_variantbytes(v: Vec) -> bool { + check_round_trip(v) + } + fn test_round_trip_u8(v: Vec) -> bool { check_round_trip(v) }