#![cfg(feature = "specialised-vectors")]
use crate::DeserializeRevisioned;
use crate::Error;
use crate::Revisioned;
use crate::SerializeRevisioned;
use std::io::ErrorKind::UnexpectedEof;
use std::io::{Read, Write};
pub trait SerializeRevisionedSpecialised: Revisioned + SerializeRevisioned {
fn serialize_revisioned_specialised<W: Write>(&self, w: &mut W) -> Result<(), Error>;
}
pub trait DeserializeRevisionedSpecialised: Revisioned + DeserializeRevisioned {
fn deserialize_revisioned_specialised<R: Read>(r: &mut R) -> Result<Self, Error>
where
Self: Sized;
}
macro_rules! impl_revisioned_specialised_vec {
($ty:ty) => {
impl SerializeRevisionedSpecialised for Vec<$ty> {
#[inline]
fn serialize_revisioned_specialised<W: Write>(
&self,
writer: &mut W,
) -> Result<(), Error> {
let len = self.len();
len.serialize_revisioned(writer)?;
if len == 0 {
return Ok(());
}
if cfg!(target_endian = "little") {
unsafe {
let byte_slice = std::slice::from_raw_parts(
self.as_ptr().cast::<u8>(),
len * std::mem::size_of::<$ty>(),
);
writer.write_all(byte_slice).map_err(Error::Io)
}
} else {
for value in self.iter() {
writer.write_all(&value.to_le_bytes()).map_err(Error::Io)?;
}
Ok(())
}
}
}
impl DeserializeRevisionedSpecialised for Vec<$ty> {
#[inline]
fn deserialize_revisioned_specialised<R: Read>(reader: &mut R) -> Result<Self, Error> {
let len = usize::deserialize_revisioned(reader)?;
if len == 0 {
return Ok(Self::new());
}
if cfg!(target_endian = "little") {
let byte_len = len
.checked_mul(std::mem::size_of::<$ty>())
.ok_or(Error::IntegerOverflow)?;
let mut vec = vec![<$ty>::default(); len];
unsafe {
let byte_slice =
std::slice::from_raw_parts_mut(vec.as_mut_ptr().cast::<u8>(), byte_len);
reader.read_exact(byte_slice).map_err(Error::Io)?;
}
Ok(vec)
} else {
let mut vec = Self::with_capacity(len);
for _ in 0..len {
let mut b = [0u8; std::mem::size_of::<$ty>()];
reader.read_exact(&mut b).map_err(Error::Io)?;
let v = <$ty>::from_le_bytes(b);
unsafe { std::hint::assert_unchecked(vec.len() < vec.capacity()) };
vec.push(v);
}
Ok(vec)
}
}
}
};
}
impl SerializeRevisionedSpecialised for Vec<u8> {
#[inline]
fn serialize_revisioned_specialised<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
super::vecs::serialize_bytes(self, writer)
}
}
impl DeserializeRevisionedSpecialised for Vec<u8> {
#[inline]
fn deserialize_revisioned_specialised<R: Read>(reader: &mut R) -> Result<Self, Error> {
let len = usize::deserialize_revisioned(reader)?;
if len == 0 {
return Ok(Self::new());
}
let mut vec: Vec<u8> = Vec::with_capacity(len);
let mut bytes = reader.take(len as u64);
if len != bytes.read_to_end(&mut vec).map_err(Error::Io)? {
return Err(Error::Io(UnexpectedEof.into()));
}
Ok(vec)
}
}
impl SerializeRevisionedSpecialised for Vec<i8> {
#[inline]
fn serialize_revisioned_specialised<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let len = self.len();
len.serialize_revisioned(writer)?;
if len == 0 {
return Ok(());
}
unsafe {
let byte_slice = std::slice::from_raw_parts(self.as_ptr().cast::<u8>(), self.len());
writer.write_all(byte_slice).map_err(Error::Io)
}
}
}
impl DeserializeRevisionedSpecialised for Vec<i8> {
#[inline]
fn deserialize_revisioned_specialised<R: Read>(reader: &mut R) -> Result<Self, Error> {
let len = usize::deserialize_revisioned(reader)?;
if len == 0 {
return Ok(Self::new());
}
let mut vec: Vec<u8> = Vec::with_capacity(len);
let mut bytes = reader.take(len as u64);
if len != bytes.read_to_end(&mut vec).map_err(Error::Io)? {
return Err(Error::Io(UnexpectedEof.into()));
}
let (ptr, len, cap) = (vec.as_mut_ptr(), vec.len(), vec.capacity());
std::mem::forget(vec);
let vec = unsafe { Vec::from_raw_parts(ptr.cast::<i8>(), len, cap) };
Ok(vec)
}
}
impl SerializeRevisionedSpecialised for Vec<bool> {
#[inline]
fn serialize_revisioned_specialised<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let len = self.len();
len.serialize_revisioned(writer)?;
if len == 0 {
return Ok(());
}
let num_bytes = len.div_ceil(8);
let mut buffer = Vec::with_capacity(num_bytes);
for chunk in self.chunks(8) {
let mut byte = 0u8;
for (i, &b) in chunk.iter().enumerate() {
if b {
byte |= 1 << i;
}
}
buffer.push(byte);
}
writer.write_all(&buffer).map_err(Error::Io)
}
}
impl DeserializeRevisionedSpecialised for Vec<bool> {
#[inline]
fn deserialize_revisioned_specialised<R: Read>(reader: &mut R) -> Result<Self, Error> {
let len = usize::deserialize_revisioned(reader)?;
if len == 0 {
return Ok(Self::new());
}
let num_bytes = len.div_ceil(8);
let mut buffer = vec![0u8; num_bytes];
reader.read_exact(&mut buffer).map_err(Error::Io)?;
let mut vec = Vec::with_capacity(len);
for (i, &byte) in buffer.iter().enumerate() {
let bits_in_this_byte = std::cmp::min(8, len - i * 8);
for bit in 0..bits_in_this_byte {
vec.push((byte >> bit) & 1 == 1);
}
}
Ok(vec)
}
}
impl_revisioned_specialised_vec!(u16);
impl_revisioned_specialised_vec!(u32);
impl_revisioned_specialised_vec!(u64);
impl_revisioned_specialised_vec!(u128);
impl_revisioned_specialised_vec!(i16);
impl_revisioned_specialised_vec!(i32);
impl_revisioned_specialised_vec!(i64);
impl_revisioned_specialised_vec!(i128);
impl_revisioned_specialised_vec!(f32);
impl_revisioned_specialised_vec!(f64);
#[cfg(test)]
mod tests {
use crate::{DeserializeRevisioned, SerializeRevisioned};
#[test]
fn test_vec_i8() {
let val = vec![i8::MIN, -1, 0, 1, i8::MAX];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<i8> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_u8() {
let val = vec![0, 1, 127, 255];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<u8> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_i16() {
let val = vec![i16::MIN, -1000, 0, 1000, i16::MAX];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<i16> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_u16() {
let val = vec![0, 1000, 32767, 65535];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<u16> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_i32() {
let val = vec![i32::MIN, -100000, 0, 100000, i32::MAX];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<i32> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_u32() {
let val = vec![0, 100000, 2147483647, 4294967295];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<u32> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_i64() {
let val = vec![i64::MIN, -1000000000, 0, 1000000000, i64::MAX];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<i64> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_u64() {
let val = vec![0, 1000000000, 9223372036854775807, 18446744073709551615];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<u64> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_i128() {
let val = vec![i128::MIN, -1000000000000000000, 0, 1000000000000000000, i128::MAX];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<i128> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_u128() {
let val = vec![0, 1000000000000000000, u128::MAX / 2, u128::MAX];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<u128> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_f32() {
let val = vec![f32::MIN, -std::f32::consts::PI, 0.0, std::f32::consts::PI, f32::MAX];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<f32> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_f64() {
let val = vec![f64::MIN, -std::f64::consts::PI, 0.0, std::f64::consts::PI, f64::MAX];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<f64> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_empty() {
let empty_i8: Vec<i8> = vec![];
let empty_u8: Vec<u8> = vec![];
let empty_i32: Vec<i32> = vec![];
let empty_f64: Vec<f64> = vec![];
let mut mem: Vec<u8> = vec![];
empty_i8.serialize_revisioned(&mut mem).unwrap();
let out_i8 =
<Vec<i8> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(empty_i8, out_i8);
mem.clear();
empty_u8.serialize_revisioned(&mut mem).unwrap();
let out_u8 =
<Vec<u8> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(empty_u8, out_u8);
mem.clear();
empty_i32.serialize_revisioned(&mut mem).unwrap();
let out_i32 =
<Vec<i32> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(empty_i32, out_i32);
mem.clear();
empty_f64.serialize_revisioned(&mut mem).unwrap();
let out_f64 =
<Vec<f64> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(empty_f64, out_f64);
}
#[test]
fn test_vec_large() {
let large_u8: Vec<u8> = (0..=255).collect();
let mut mem: Vec<u8> = vec![];
large_u8.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<u8> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(large_u8, out);
let large_i32: Vec<i32> = (0..1000).map(|i| i * 2 - 500).collect();
mem.clear();
large_i32.serialize_revisioned(&mut mem).unwrap();
let out_i32 =
<Vec<i32> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(large_i32, out_i32);
}
#[test]
fn test_vec_edge_cases() {
let single_u8 = vec![42u8];
let mut mem: Vec<u8> = vec![];
single_u8.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<u8> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(single_u8, out);
let float_specials =
vec![f64::NEG_INFINITY, f64::MIN, -0.0, 0.0, f64::MAX, f64::INFINITY, f64::NAN];
mem.clear();
float_specials.serialize_revisioned(&mut mem).unwrap();
let out_floats =
<Vec<f64> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(out_floats.len(), float_specials.len());
for (i, (&expected, &actual)) in float_specials.iter().zip(out_floats.iter()).enumerate() {
if expected.is_nan() {
assert!(actual.is_nan(), "Element {} should be NaN", i);
} else {
assert_eq!(expected, actual, "Element {} mismatch", i);
}
}
}
#[test]
fn test_vec_f32_special_values() {
let float_specials = vec![
f32::NEG_INFINITY,
f32::MIN,
-0.0f32,
0.0f32,
f32::MIN_POSITIVE,
f32::MAX,
f32::INFINITY,
f32::NAN,
];
let mut mem: Vec<u8> = vec![];
float_specials.serialize_revisioned(&mut mem).unwrap();
let out_floats =
<Vec<f32> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(out_floats.len(), float_specials.len());
for (i, (&expected, &actual)) in float_specials.iter().zip(out_floats.iter()).enumerate() {
if expected.is_nan() {
assert!(actual.is_nan(), "Element {} should be NaN", i);
} else {
assert_eq!(expected, actual, "Element {} mismatch", i);
}
}
}
#[test]
fn test_vec_i8_bulk() {
let val: Vec<i8> = (-128..=127).collect();
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
#[cfg(not(feature = "fixed-width-encoding"))]
assert_eq!(mem.len(), 3 + 256);
#[cfg(feature = "fixed-width-encoding")]
assert_eq!(mem.len(), 8 + 256);
let out = <Vec<i8> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_bool_bitpacked() {
let val = vec![true, false, true, true, false, false, true, false];
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
#[cfg(not(feature = "fixed-width-encoding"))]
assert_eq!(mem.len(), 2, "Bit-packing should use 2 bytes for 8 bools");
#[cfg(feature = "fixed-width-encoding")]
assert_eq!(mem.len(), 9, "Bit-packing with fixed-width length: 8 + 1 bytes");
let out = <Vec<bool> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out);
}
#[test]
fn test_vec_bool_bitpacked_patterns() {
let all_false = vec![false; 100];
let mut mem: Vec<u8> = vec![];
all_false.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<bool> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(all_false, out);
let all_true = vec![true; 100];
mem.clear();
all_true.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<bool> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(all_true, out);
let alternating: Vec<bool> = (0..100).map(|i| i % 2 == 0).collect();
mem.clear();
alternating.serialize_revisioned(&mut mem).unwrap();
let out = <Vec<bool> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(alternating, out);
}
#[test]
fn test_vec_bool_bitpacked_sizes() {
for size in [0usize, 1, 7, 8, 9, 15, 16, 17, 63, 64, 65, 100, 255, 256, 1000] {
let val: Vec<bool> = (0..size).map(|i| (i * 7) % 3 == 0).collect();
let mut mem: Vec<u8> = vec![];
val.serialize_revisioned(&mut mem).unwrap();
if size > 0 {
let expected_data_bytes = size.div_ceil(8);
#[cfg(not(feature = "fixed-width-encoding"))]
let len_bytes = if size < 251 {
1
} else if size < 65536 {
3
} else {
5
};
#[cfg(feature = "fixed-width-encoding")]
let len_bytes = 8;
assert_eq!(
mem.len(),
len_bytes + expected_data_bytes,
"Size mismatch for {} bools",
size
);
}
let out =
<Vec<bool> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(val, out, "Mismatch for size {}", size);
}
}
#[test]
fn test_vec_bool_bitpacked_empty() {
let empty: Vec<bool> = vec![];
let mut mem: Vec<u8> = vec![];
empty.serialize_revisioned(&mut mem).unwrap();
#[cfg(not(feature = "fixed-width-encoding"))]
assert_eq!(mem.len(), 1, "Empty vec should only have length byte");
#[cfg(feature = "fixed-width-encoding")]
assert_eq!(mem.len(), 8, "Empty vec with fixed-width length encoding");
let out = <Vec<bool> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(empty, out);
}
#[test]
fn test_vec_bool_bitpacked_space_efficiency() {
let large_bool_vec = vec![true; 10000];
let mut mem: Vec<u8> = vec![];
large_bool_vec.serialize_revisioned(&mut mem).unwrap();
assert!(
mem.len() < 1300,
"Bit-packed 10000 bools should be under 1300 bytes, got {}",
mem.len()
);
let out = <Vec<bool> as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice())
.unwrap();
assert_eq!(large_bool_vec, out);
}
}