use crate::prelude::*;
pub trait Pack: Sized {
fn pack(&self, writer: &mut impl Write) -> Result<usize>;
fn unpack(reader: &mut impl Read) -> Result<Self>;
#[inline(always)]
fn pack_slice(items: &[Self], writer: &mut impl Write) -> Result<usize> {
let mut total = 0;
for item in items {
total += item.pack(writer)?;
}
Ok(total)
}
#[inline(always)]
fn unpack_vec(reader: &mut impl Read, count: usize) -> Result<Vec<Self>> {
let mut vec = Vec::with_capacity(count);
for _ in 0..count {
vec.push(Self::unpack(reader)?);
}
Ok(vec)
}
}
impl<const N: usize, T: Pack + 'static> Pack for [T; N] {
#[inline(always)]
fn pack(&self, writer: &mut impl Write) -> Result<usize> {
if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
let bytes: &[u8] =
unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, N) };
if let Some(buf) = writer.buf_mut()
&& buf.len() >= N
{
unsafe {
core::ptr::copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), N);
}
writer.advance_mut(N);
return Ok(N);
}
return writer.write(bytes);
}
let mut total_bytes = 0;
for item in self.iter() {
total_bytes += item.pack(writer)?;
}
Ok(total_bytes)
}
#[inline(always)]
fn unpack(reader: &mut impl Read) -> Result<Self> {
if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
let mut arr: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
if let Some(buf) = reader.buf() {
if buf.len() >= N {
unsafe {
core::ptr::copy_nonoverlapping(
buf.as_ptr(),
arr.as_mut_ptr() as *mut u8,
N,
);
}
reader.advance(N);
return Ok(unsafe { arr.assume_init() });
}
return Err(Error::ReaderOutOfData);
}
let dst = unsafe { core::slice::from_raw_parts_mut(arr.as_mut_ptr() as *mut u8, N) };
let mut read = 0;
while read < N {
read += reader.read(&mut dst[read..])?;
}
return Ok(unsafe { arr.assume_init() });
}
let mut arr: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
let ptr = arr.as_mut_ptr() as *mut T;
for i in 0..N {
unsafe {
ptr.add(i).write(T::unpack(reader)?);
}
}
Ok(unsafe { arr.assume_init() })
}
#[inline(always)]
fn pack_slice(items: &[Self], writer: &mut impl Write) -> Result<usize> {
if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
let total = N * items.len();
let bytes: &[u8] =
unsafe { core::slice::from_raw_parts(items.as_ptr() as *const u8, total) };
return writer.write(bytes);
}
let mut total = 0;
for item in items {
total += item.pack(writer)?;
}
Ok(total)
}
#[inline(always)]
fn unpack_vec(reader: &mut impl Read, count: usize) -> Result<Vec<Self>> {
if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
let total = N * count;
if let Some(buf) = reader.buf() {
if buf.len() >= total {
let mut vec: Vec<Self> = Vec::with_capacity(count);
unsafe {
core::ptr::copy_nonoverlapping(
buf.as_ptr(),
vec.as_mut_ptr() as *mut u8,
total,
);
vec.set_len(count);
}
reader.advance(total);
return Ok(vec);
}
return Err(Error::ReaderOutOfData);
}
let mut vec: Vec<Self> = Vec::with_capacity(count);
let dst =
unsafe { core::slice::from_raw_parts_mut(vec.as_mut_ptr() as *mut u8, total) };
let mut read = 0;
while read < total {
read += reader.read(&mut dst[read..])?;
}
unsafe { vec.set_len(count) };
return Ok(vec);
}
let mut vec = Vec::with_capacity(count);
for _ in 0..count {
vec.push(Self::unpack(reader)?);
}
Ok(vec)
}
}
#[macro_export]
macro_rules! impl_pack_for_endianness_types {
($($t:ty),+ $(,)?) => {
$(
impl $crate::pack::Pack for $t {
#[inline(always)]
fn pack(&self, writer: &mut impl $crate::io::Write) -> $crate::Result<usize> {
writer.write(&endian_cast::Endianness::le_bytes(self))
}
#[inline]
fn unpack(reader: &mut impl $crate::io::Read) -> $crate::Result<Self> {
let size = core::mem::size_of::<Self>();
if let Some(buf) = reader.buf() {
if buf.len() >= size {
let mut ret = core::mem::MaybeUninit::<Self>::uninit();
let dst = ret.as_mut_ptr() as *mut u8;
#[cfg(target_endian = "little")]
unsafe {
core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, size);
}
#[cfg(target_endian = "big")]
unsafe {
for i in 0..size {
*dst.add(i) = buf[size - 1 - i];
}
}
reader.advance(size);
return Ok(unsafe { ret.assume_init() });
}
return Err($crate::io::Error::ReaderOutOfData);
}
let mut tmp = [0u8; core::mem::size_of::<Self>()];
let bytes_read = reader.read(&mut tmp[..])?;
if bytes_read != size {
return Err($crate::io::Error::ReaderOutOfData);
}
let mut ret = core::mem::MaybeUninit::<Self>::uninit();
let dst = ret.as_mut_ptr() as *mut u8;
#[cfg(target_endian = "little")]
unsafe {
core::ptr::copy_nonoverlapping(tmp.as_ptr(), dst, size);
}
#[cfg(target_endian = "big")]
unsafe {
for i in 0..size {
*dst.add(i) = tmp[size - 1 - i];
}
}
Ok(unsafe { ret.assume_init() })
}
}
)+
};
}
impl_pack_for_endianness_types!(
u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64
);
#[cfg(test)]
mod tests {
use super::*;
use crate::io::Cursor;
#[test]
fn test_macro_usage() {
let value: u32 = 0x12345678;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = value.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 4);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: u32 = u32::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, value);
}
}
#[test]
fn test_pack_unpack_u8() {
let original: u8 = 42;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 1);
assert_eq!(buffer[0], 42);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: u8 = u8::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_u16() {
let original: u16 = 0x1234;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 2);
assert_eq!(buffer[0], 0x34);
assert_eq!(buffer[1], 0x12);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: u16 = u16::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_u32() {
let original: u32 = 0x12345678;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 4);
assert_eq!(buffer[0], 0x78);
assert_eq!(buffer[1], 0x56);
assert_eq!(buffer[2], 0x34);
assert_eq!(buffer[3], 0x12);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: u32 = u32::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_u64() {
let original: u64 = 0x123456789abcdef0;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 8);
assert_eq!(buffer[0], 0xf0);
assert_eq!(buffer[1], 0xde);
assert_eq!(buffer[2], 0xbc);
assert_eq!(buffer[3], 0x9a);
assert_eq!(buffer[4], 0x78);
assert_eq!(buffer[5], 0x56);
assert_eq!(buffer[6], 0x34);
assert_eq!(buffer[7], 0x12);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: u64 = u64::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_u128() {
let original: u128 = 0x123456789abcdef0fedcba9876543210;
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 16);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: u128 = u128::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_i8() {
let original: i8 = -42;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 1);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: i8 = i8::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_i16() {
let original: i16 = -12345;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 2);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: i16 = i16::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_i32() {
let original: i32 = -123456789;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 4);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: i32 = i32::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_i64() {
let original: i64 = -1234567890123456789;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 8);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: i64 = i64::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_i128() {
let original: i128 = -123456789012345678901234567890123456789;
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 16);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: i128 = i128::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_f32() {
let original: f32 = 1.23456;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 4);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: f32 = f32::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_f64() {
let original: f64 = 1.234567890123456;
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 8);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: f64 = f64::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_extreme_values() {
for &value in &[u8::MIN, u8::MAX] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
assert_eq!(u8::unpack(&mut read_cursor).unwrap(), value);
}
for &value in &[u16::MIN, u16::MAX] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
assert_eq!(u16::unpack(&mut read_cursor).unwrap(), value);
}
for &value in &[u32::MIN, u32::MAX] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
assert_eq!(u32::unpack(&mut read_cursor).unwrap(), value);
}
for &value in &[u64::MIN, u64::MAX] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
assert_eq!(u64::unpack(&mut read_cursor).unwrap(), value);
}
}
#[test]
fn test_pack_unpack_signed_extremes() {
for &value in &[i8::MIN, -1, 0, 1, i8::MAX] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
assert_eq!(i8::unpack(&mut read_cursor).unwrap(), value);
}
for &value in &[i16::MIN, -1, 0, 1, i16::MAX] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
assert_eq!(i16::unpack(&mut read_cursor).unwrap(), value);
}
for &value in &[i32::MIN, -1, 0, 1, i32::MAX] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
assert_eq!(i32::unpack(&mut read_cursor).unwrap(), value);
}
for &value in &[i64::MIN, -1, 0, 1, i64::MAX] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
assert_eq!(i64::unpack(&mut read_cursor).unwrap(), value);
}
}
#[test]
fn test_pack_unpack_floating_point_special_values() {
for &value in &[f32::NEG_INFINITY, -0.0, 0.0, f32::INFINITY, f32::NAN] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked = f32::unpack(&mut read_cursor).unwrap();
if value.is_nan() {
assert!(unpacked.is_nan());
} else {
assert_eq!(unpacked, value);
}
}
for &value in &[f64::NEG_INFINITY, -0.0, 0.0, f64::INFINITY, f64::NAN] {
let mut buffer = [0u8; 10];
let mut cursor = Cursor::new(&mut buffer[..]);
value.pack(&mut cursor).unwrap();
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked = f64::unpack(&mut read_cursor).unwrap();
if value.is_nan() {
assert!(unpacked.is_nan());
} else {
assert_eq!(unpacked, value);
}
}
}
#[test]
fn test_pack_multiple_values() {
let mut buffer = [0u8; 100];
let mut cursor = Cursor::new(&mut buffer[..]);
let val1: u8 = 42;
let val2: u16 = 0x1234;
let val3: u32 = 0x12345678;
let val4: f32 = 1.23456;
let mut total_bytes = 0;
total_bytes += val1.pack(&mut cursor).unwrap();
total_bytes += val2.pack(&mut cursor).unwrap();
total_bytes += val3.pack(&mut cursor).unwrap();
total_bytes += val4.pack(&mut cursor).unwrap();
assert_eq!(total_bytes, 1 + 2 + 4 + 4);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked_val1: u8 = u8::unpack(&mut read_cursor).unwrap();
let unpacked_val2: u16 = u16::unpack(&mut read_cursor).unwrap();
let unpacked_val3: u32 = u32::unpack(&mut read_cursor).unwrap();
let unpacked_val4: f32 = f32::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked_val1, val1);
assert_eq!(unpacked_val2, val2);
assert_eq!(unpacked_val3, val3);
assert_eq!(unpacked_val4, val4);
}
#[test]
fn test_unpack_insufficient_data() {
let buffer = [0x12, 0x34];
let mut cursor = Cursor::new(&buffer[..]);
let result = u32::unpack(&mut cursor);
assert!(result.is_err());
match result.unwrap_err() {
Error::ReaderOutOfData => {}
_ => panic!("Expected ReaderOutOfData error"),
}
}
#[test]
fn test_pack_insufficient_space() {
let mut buffer = [0u8; 2];
let mut cursor = Cursor::new(&mut buffer[..]);
let value: u32 = 0x12345678;
let result = value.pack(&mut cursor);
assert!(result.is_err());
match result.unwrap_err() {
Error::WriterOutOfSpace => {}
_ => panic!("Expected WriterOutOfSpace error"),
}
}
#[test]
fn test_pack_unpack_with_vec_writer() {
let mut buffer = Vec::new();
let val1: u16 = 0x1234;
let val2: u32 = 0x56789abc;
val1.pack(&mut buffer).unwrap();
val2.pack(&mut buffer).unwrap();
assert_eq!(buffer.len(), 6);
assert_eq!(buffer[0], 0x34); assert_eq!(buffer[1], 0x12); assert_eq!(buffer[2], 0xbc); assert_eq!(buffer[3], 0x9a); assert_eq!(buffer[4], 0x78); assert_eq!(buffer[5], 0x56);
let mut cursor = Cursor::new(&buffer[..]);
let unpacked_val1: u16 = u16::unpack(&mut cursor).unwrap();
let unpacked_val2: u32 = u32::unpack(&mut cursor).unwrap();
assert_eq!(unpacked_val1, val1);
assert_eq!(unpacked_val2, val2);
}
#[test]
fn test_round_trip_consistency() {
fn test_round_trip<T: Pack + PartialEq + core::fmt::Debug + Copy>(value: T) {
let mut buffer = Vec::new();
value.pack(&mut buffer).unwrap();
let mut cursor = Cursor::new(&buffer[..]);
let unpacked = T::unpack(&mut cursor).unwrap();
assert_eq!(value, unpacked);
}
test_round_trip(0u8);
test_round_trip(255u8);
test_round_trip(0u16);
test_round_trip(65535u16);
test_round_trip(0u32);
test_round_trip(4294967295u32);
test_round_trip(0u64);
test_round_trip(18446744073709551615u64);
test_round_trip(-128i8);
test_round_trip(127i8);
test_round_trip(-32768i16);
test_round_trip(32767i16);
test_round_trip(-2147483648i32);
test_round_trip(2147483647i32);
test_round_trip(-9223372036854775808i64);
test_round_trip(9223372036854775807i64);
test_round_trip(0.0f32);
test_round_trip(1.0f32);
test_round_trip(-1.0f32);
test_round_trip(f32::MIN);
test_round_trip(f32::MAX);
test_round_trip(0.0f64);
test_round_trip(1.0f64);
test_round_trip(-1.0f64);
test_round_trip(f64::MIN);
test_round_trip(f64::MAX);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn test_pack_unpack_usize() {
let original: usize = 0x123456789abcdef0usize;
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, core::mem::size_of::<usize>());
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: usize = usize::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[cfg(target_pointer_width = "32")]
#[test]
fn test_pack_unpack_usize() {
let original: usize = 0x12345678usize;
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, core::mem::size_of::<usize>());
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: usize = usize::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_isize() {
let original: isize = -123456789;
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, core::mem::size_of::<isize>());
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: isize = isize::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_array_u8() {
let original: [u8; 4] = [0x12, 0x34, 0x56, 0x78];
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 4);
assert_eq!(buffer[0], 0x12);
assert_eq!(buffer[1], 0x34);
assert_eq!(buffer[2], 0x56);
assert_eq!(buffer[3], 0x78);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u8; 4] = <[u8; 4]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_array_u16() {
let original: [u16; 3] = [0x1234, 0x5678, 0x9abc];
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 6);
assert_eq!(buffer[0], 0x34); assert_eq!(buffer[1], 0x12); assert_eq!(buffer[2], 0x78); assert_eq!(buffer[3], 0x56); assert_eq!(buffer[4], 0xbc); assert_eq!(buffer[5], 0x9a);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u16; 3] = <[u16; 3]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_array_u32() {
let original: [u32; 2] = [0x12345678, 0x9abcdef0];
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 8);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u32; 2] = <[u32; 2]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_array_mixed_sizes() {
let arr1: [u8; 1] = [42];
let arr5: [u8; 5] = [1, 2, 3, 4, 5];
let arr10: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = arr1.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 1);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u8; 1] = <[u8; 1]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, arr1);
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = arr5.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 5);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u8; 5] = <[u8; 5]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, arr5);
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = arr10.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 10);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u8; 10] = <[u8; 10]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, arr10);
}
#[test]
fn test_pack_unpack_array_floating_point() {
let original: [f32; 3] = [1.23456, -2.34567, 0.0];
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 12);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [f32; 3] = <[f32; 3]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_array_signed_integers() {
let original: [i32; 4] = [-1000000, 0, 1000000, i32::MAX];
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 16);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [i32; 4] = <[i32; 4]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_pack_unpack_empty_array() {
let original: [u8; 0] = [];
let mut buffer = [0u8; 20];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 0);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u8; 0] = <[u8; 0]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_array_pack_with_vec_writer() {
let original: [u16; 3] = [0x1234, 0x5678, 0x9abc];
let mut buffer = Vec::new();
original.pack(&mut buffer).unwrap();
assert_eq!(buffer.len(), 6);
assert_eq!(buffer[0], 0x34); assert_eq!(buffer[1], 0x12); assert_eq!(buffer[2], 0x78); assert_eq!(buffer[3], 0x56); assert_eq!(buffer[4], 0xbc); assert_eq!(buffer[5], 0x9a);
let mut cursor = Cursor::new(&buffer[..]);
let unpacked: [u16; 3] = <[u16; 3]>::unpack(&mut cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_array_unpack_insufficient_data() {
let buffer = [0x12, 0x34, 0x56, 0x78]; let mut cursor = Cursor::new(&buffer[..]);
let result = <[u32; 2]>::unpack(&mut cursor);
assert!(result.is_err());
match result.unwrap_err() {
Error::ReaderOutOfData => {}
_ => panic!("Expected ReaderOutOfData error"),
}
}
#[test]
fn test_array_pack_insufficient_space() {
let original: [u32; 2] = [0x12345678, 0x9abcdef0];
let mut buffer = [0u8; 4]; let mut cursor = Cursor::new(&mut buffer[..]);
let result = original.pack(&mut cursor);
assert!(result.is_err());
match result.unwrap_err() {
Error::WriterOutOfSpace => {}
_ => panic!("Expected WriterOutOfSpace error"),
}
}
#[test]
fn test_array_round_trip_consistency() {
fn test_array_round_trip<
T: Pack + PartialEq + core::fmt::Debug + Copy + 'static,
const N: usize,
>(
value: [T; N],
) {
let mut buffer = Vec::new();
value.pack(&mut buffer).unwrap();
let mut cursor = Cursor::new(&buffer[..]);
let unpacked = <[T; N]>::unpack(&mut cursor).unwrap();
assert_eq!(value, unpacked);
}
test_array_round_trip([0u8, 255u8, 128u8]);
test_array_round_trip([u16::MIN, u16::MAX]);
test_array_round_trip([u32::MIN, 12345u32, u32::MAX]);
test_array_round_trip([u64::MIN, u64::MAX]);
test_array_round_trip([i8::MIN, 0i8, i8::MAX]);
test_array_round_trip([i16::MIN, -1i16, 0i16, 1i16, i16::MAX]);
test_array_round_trip([i32::MIN, i32::MAX]);
test_array_round_trip([i64::MIN, i64::MAX]);
test_array_round_trip([0.0f32, 1.0f32, -1.0f32]);
test_array_round_trip([f64::MIN, 0.0f64, f64::MAX]);
}
#[test]
fn test_large_array() {
let original: [u8; 100] = [42; 100];
let mut buffer = [0u8; 200];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 100);
for b in &buffer[..100] {
assert_eq!(*b, 42);
}
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u8; 100] = <[u8; 100]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}
#[test]
fn test_nested_array_concepts() {
let original: [u64; 8] = [
0x123456789abcdef0,
0x0fedcba987654321,
u64::MIN,
u64::MAX,
0,
1,
0x5555555555555555,
0xaaaaaaaaaaaaaaaa,
];
let mut buffer = [0u8; 100];
let mut cursor = Cursor::new(&mut buffer[..]);
let bytes_written = original.pack(&mut cursor).unwrap();
assert_eq!(bytes_written, 64);
let mut read_cursor = Cursor::new(&buffer[..]);
let unpacked: [u64; 8] = <[u64; 8]>::unpack(&mut read_cursor).unwrap();
assert_eq!(unpacked, original);
}