use std::{mem, ptr};
use light_bounded_vec::{
BoundedVec, BoundedVecMetadata, CyclicBoundedVec, CyclicBoundedVecMetadata,
};
pub unsafe fn read_value_at<T>(bytes: &[u8], offset: &mut usize) -> T
where
T: Clone,
{
let size = mem::size_of::<T>();
let ptr = bytes[*offset..*offset + size].as_ptr() as *const T;
*offset += size;
ptr::read(ptr)
}
pub unsafe fn read_bounded_vec_at<T>(
bytes: &[u8],
offset: &mut usize,
metadata: &BoundedVecMetadata,
) -> BoundedVec<T>
where
T: Clone,
{
let size = mem::size_of::<T>() * metadata.capacity();
let ptr = bytes[*offset..*offset + size].as_ptr() as *const T;
let mut vec = BoundedVec::with_metadata(metadata);
let dst_ptr: *mut T = vec.as_mut_ptr();
for i in 0..metadata.length() {
let val = ptr::read(ptr.add(i));
unsafe { ptr::write(dst_ptr.add(i), val) };
}
*offset += size;
vec
}
pub unsafe fn read_cyclic_bounded_vec_at<T>(
bytes: &[u8],
offset: &mut usize,
metadata: &CyclicBoundedVecMetadata,
) -> CyclicBoundedVec<T>
where
T: Clone,
{
let size = mem::size_of::<T>() * metadata.capacity();
let src_ptr = bytes[*offset..*offset + size].as_ptr() as *const T;
let mut vec = CyclicBoundedVec::with_metadata(metadata);
let dst_ptr: *mut T = vec.as_mut_ptr();
for i in 0..metadata.length() {
let val = ptr::read(src_ptr.add(i));
unsafe { ptr::write(dst_ptr.add(i), val) };
}
*offset += size;
vec
}
#[cfg(test)]
mod test {
use std::slice;
use super::*;
use bytemuck::{Pod, Zeroable};
use memoffset::offset_of;
#[test]
fn test_value_at() {
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)]
struct TestStruct {
a: isize,
b: usize,
c: i64,
d: u64,
e: i32,
f: u32,
g: i16,
_padding_1: [u8; 2],
h: u16,
_padding_2: [u8; 2],
i: i8,
_padding_3: [i8; 3],
j: u8,
_padding_4: [i8; 3],
}
let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
let s = buf.as_mut_ptr() as *mut TestStruct;
unsafe {
(*s).a = isize::MIN;
(*s).b = usize::MAX;
(*s).c = i64::MIN;
(*s).d = u64::MAX;
(*s).e = i32::MIN;
(*s).f = u32::MAX;
(*s).g = i16::MIN;
(*s).h = u16::MAX;
(*s).i = i8::MIN;
(*s).j = u8::MAX;
let mut offset = offset_of!(TestStruct, a);
assert_eq!(offset, 0);
assert_eq!(read_value_at::<isize>(&buf, &mut offset), isize::MIN);
assert_eq!(offset, 8);
let mut offset = offset_of!(TestStruct, b);
assert_eq!(offset, 8);
assert_eq!(read_value_at::<usize>(&buf, &mut offset), usize::MAX);
assert_eq!(offset, 16);
let mut offset = offset_of!(TestStruct, c);
assert_eq!(offset, 16);
assert_eq!(read_value_at::<i64>(&buf, &mut offset), i64::MIN);
assert_eq!(offset, 24);
let mut offset = offset_of!(TestStruct, d);
assert_eq!(offset, 24);
assert_eq!(read_value_at::<u64>(&buf, &mut offset), u64::MAX);
assert_eq!(offset, 32);
let mut offset = offset_of!(TestStruct, e);
assert_eq!(offset, 32);
assert_eq!(read_value_at::<i32>(&buf, &mut offset), i32::MIN);
assert_eq!(offset, 36);
let mut offset = offset_of!(TestStruct, f);
assert_eq!(offset, 36);
assert_eq!(read_value_at::<u32>(&buf, &mut offset), u32::MAX);
assert_eq!(offset, 40);
let mut offset = offset_of!(TestStruct, g);
assert_eq!(offset, 40);
assert_eq!(read_value_at::<i16>(&buf, &mut offset), i16::MIN);
assert_eq!(offset, 42);
let mut offset = offset_of!(TestStruct, h);
assert_eq!(offset, 44);
assert_eq!(read_value_at::<u16>(&buf, &mut offset), u16::MAX);
assert_eq!(offset, 46);
let mut offset = offset_of!(TestStruct, i);
assert_eq!(offset, 48);
assert_eq!(read_value_at::<i8>(&buf, &mut offset), i8::MIN);
assert_eq!(offset, 49);
let mut offset = offset_of!(TestStruct, j);
assert_eq!(offset, 52);
assert_eq!(read_value_at::<u8>(&buf, &mut offset), u8::MAX);
assert_eq!(offset, 53);
}
}
#[test]
fn test_read_bounded_vec_at() {
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)]
struct TestStruct {
a: [i64; 32],
b: [u64; 32],
c: [[u8; 32]; 32],
}
let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
let s = buf.as_mut_ptr() as *mut TestStruct;
unsafe {
for (i, element) in (*s).a.iter_mut().enumerate() {
*element = -(i as i64);
}
for (i, element) in (*s).b.iter_mut().enumerate() {
*element = i as u64;
}
for (i, element) in (*s).c.iter_mut().enumerate() {
*element = [i as u8; 32];
}
let metadata = BoundedVecMetadata::new_with_length(32, 32);
let mut offset = offset_of!(TestStruct, a);
assert_eq!(offset, 0);
let vec: BoundedVec<i64> = read_bounded_vec_at(&buf, &mut offset, &metadata);
for (i, element) in vec.iter().enumerate() {
assert_eq!(i as i64, -(*element as i64));
}
assert_eq!(offset, 256);
let metadata = BoundedVecMetadata::new_with_length(32, 32);
let mut offset = offset_of!(TestStruct, b);
assert_eq!(offset, 256);
let vec: BoundedVec<u64> = read_bounded_vec_at(&buf, &mut offset, &metadata);
for (i, element) in vec.iter().enumerate() {
assert_eq!(i as u64, *element as u64);
}
assert_eq!(offset, 512);
let metadata = BoundedVecMetadata::new_with_length(32, 32);
let mut offset = offset_of!(TestStruct, c);
assert_eq!(offset, 512);
let vec: BoundedVec<[u8; 32]> = read_bounded_vec_at(&buf, &mut offset, &metadata);
for (i, element) in vec.iter().enumerate() {
assert_eq!(&[i as u8; 32], element);
}
assert_eq!(offset, 1536);
}
}
#[test]
fn test_read_cyclic_bounded_vec_at() {
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)]
struct TestStruct {
a: [i64; 32],
b: [u64; 32],
c: [[u8; 32]; 32],
}
let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
let s = buf.as_mut_ptr() as *mut TestStruct;
unsafe {
for (i, element) in (*s).a.iter_mut().enumerate() {
*element = -(i as i64);
}
for (i, element) in (*s).b.iter_mut().enumerate() {
*element = i as u64;
}
for (i, element) in (*s).c.iter_mut().enumerate() {
*element = [i as u8; 32];
}
let metadata = CyclicBoundedVecMetadata::new_with_indices(32, 32, 14, 13);
let mut offset = offset_of!(TestStruct, a);
assert_eq!(offset, 0);
let vec: CyclicBoundedVec<i64> =
read_cyclic_bounded_vec_at(&buf, &mut offset, &metadata);
assert_eq!(vec.capacity(), 32);
assert_eq!(vec.len(), 32);
assert_eq!(vec.first_index(), 14);
assert_eq!(vec.last_index(), 13);
assert_eq!(
vec.iter().collect::<Vec<_>>().as_slice(),
&[
&-14, &-15, &-16, &-17, &-18, &-19, &-20, &-21, &-22, &-23, &-24, &-25, &-26,
&-27, &-28, &-29, &-30, &-31, &-0, &-1, &-2, &-3, &-4, &-5, &-6, &-7, &-8, &-9,
&-10, &-11, &-12, &-13
]
);
assert_eq!(offset, 256);
let metadata = CyclicBoundedVecMetadata::new_with_indices(32, 32, 14, 13);
let mut offset = offset_of!(TestStruct, b);
assert_eq!(offset, 256);
let vec: CyclicBoundedVec<u64> =
read_cyclic_bounded_vec_at(&buf, &mut offset, &metadata);
assert_eq!(vec.capacity(), 32);
assert_eq!(vec.len(), 32);
assert_eq!(vec.first_index(), 14);
assert_eq!(vec.last_index(), 13);
assert_eq!(
vec.iter().collect::<Vec<_>>().as_slice(),
&[
&14, &15, &16, &17, &18, &19, &20, &21, &22, &23, &24, &25, &26, &27, &28, &29,
&30, &31, &0, &1, &2, &3, &4, &5, &6, &7, &8, &9, &10, &11, &12, &13
]
);
assert_eq!(offset, 512);
let metadata = CyclicBoundedVecMetadata::new_with_indices(32, 32, 14, 13);
let mut offset = offset_of!(TestStruct, c);
assert_eq!(offset, 512);
let vec: CyclicBoundedVec<[u8; 32]> =
read_cyclic_bounded_vec_at(&buf, &mut offset, &metadata);
assert_eq!(vec.capacity(), 32);
assert_eq!(vec.len(), 32);
assert_eq!(vec.first_index(), 14);
assert_eq!(vec.last_index(), 13);
assert_eq!(
vec.iter().collect::<Vec<_>>().as_slice(),
&[
&[14_u8; 32],
&[15_u8; 32],
&[16_u8; 32],
&[17_u8; 32],
&[18_u8; 32],
&[19_u8; 32],
&[20_u8; 32],
&[21_u8; 32],
&[22_u8; 32],
&[23_u8; 32],
&[24_u8; 32],
&[25_u8; 32],
&[26_u8; 32],
&[27_u8; 32],
&[28_u8; 32],
&[29_u8; 32],
&[30_u8; 32],
&[31_u8; 32],
&[0_u8; 32],
&[1_u8; 32],
&[2_u8; 32],
&[3_u8; 32],
&[4_u8; 32],
&[5_u8; 32],
&[6_u8; 32],
&[7_u8; 32],
&[8_u8; 32],
&[9_u8; 32],
&[10_u8; 32],
&[11_u8; 32],
&[12_u8; 32],
&[13_u8; 32],
]
);
assert_eq!(offset, 1536);
}
}
#[test]
fn test_read_cyclic_bounded_vec_first_last() {
let mut vec = CyclicBoundedVec::<u32>::with_capacity(2);
vec.push(0);
vec.push(37);
vec.push(49);
let metadata_bytes = vec.metadata().to_ne_bytes();
let metadata = CyclicBoundedVecMetadata::from_ne_bytes(metadata_bytes);
let bytes = unsafe {
slice::from_raw_parts(
vec.as_mut_ptr() as *mut u8,
mem::size_of::<u32>() * vec.capacity(),
)
};
let mut offset = 0;
let vec_copy: CyclicBoundedVec<u32> =
unsafe { read_cyclic_bounded_vec_at(bytes, &mut offset, &metadata) };
assert_eq!(*vec.first().unwrap(), 37);
assert_eq!(vec.first(), vec_copy.first()); assert_eq!(*vec.last().unwrap(), 49);
assert_eq!(vec.last(), vec_copy.last()); }
}