use crate::error::ResourceStorageError;
use crate::structs::Struct;
pub trait SliceExt<'a>
where
Self: Sized,
{
fn from_bytes(data: &'a [u8]) -> Result<Self, ResourceStorageError>;
fn as_bytes(&self) -> &'a [u8];
}
impl<'a, T> SliceExt<'a> for &'a [T]
where
T: Struct,
{
fn from_bytes(mut data: &[u8]) -> Result<Self, ResourceStorageError> {
if data.len() % T::SIZE_IN_BYTES != 0 {
return Err(ResourceStorageError::UnexpectedDataSize);
}
if T::IS_OVERLAPPING_WITH_NEXT {
if data.len() < T::SIZE_IN_BYTES {
return Err(ResourceStorageError::UnexpectedDataSize);
}
data = &data[..data.len() - T::SIZE_IN_BYTES];
}
unsafe {
Ok(std::slice::from_raw_parts(
data.as_ptr() as *const T,
data.len() / T::SIZE_IN_BYTES,
))
}
}
fn as_bytes(&self) -> &'a [u8] {
let len = if T::IS_OVERLAPPING_WITH_NEXT {
self.len() + 1
} else {
self.len()
};
unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, len * T::SIZE_IN_BYTES) }
}
}
#[cfg(test)]
#[allow(dead_code)]
mod test {
use super::*;
use crate::{
structs::Struct,
test::{A, B, R},
Vector,
};
#[test]
fn range() {
let mut vec: Vector<R> = Vector::with_len(3);
vec[0].set_first_x(10);
vec[1].set_first_x(20);
vec[2].set_first_x(30);
assert_eq!(vec.len(), 3);
assert_eq!(vec[0].x(), 10..20);
assert_eq!(vec[1].x(), 20..30);
assert_eq!(vec[2].x(), 30..0);
assert_eq!(vec[0..1].len(), 1);
assert_eq!(vec[0..1][0].x(), 10..20);
let view = vec.as_view();
assert_eq!(view.len(), 2);
assert_eq!(view[0].x(), 10..20);
assert_eq!(view[1].x(), 20..30);
assert_eq!(vec[0..1].len(), 1);
assert_eq!(vec[0..1][0].x(), 10..20);
}
#[test]
fn into_iter() {
for _ in create_values(10).as_view() {}
}
#[test]
fn new_and_clone() {
let mut buffer = vec![255_u8; A::SIZE_IN_BYTES];
buffer.extend(vec![0_u8; A::SIZE_IN_BYTES * 10]);
let data = &buffer[..];
let view = <&[A]>::from_bytes(&data).unwrap();
assert_eq!(11, view.len());
let first = &view[0];
assert_eq!(65535, first.x());
assert_eq!(65535, first.y());
for x in view.iter().skip(1) {
assert_eq!(0, x.x());
assert_eq!(0, x.y());
}
let x = {
let view_copy = view.clone();
&view_copy[0]
};
assert_eq!(65535, x.x());
assert_eq!(65535, x.y());
let x = {
let view_copy = view.clone();
view_copy.iter().next().unwrap()
};
assert_eq!(65535, x.x());
assert_eq!(65535, x.y());
}
fn create_values(size: usize) -> Vector<B> {
let mut v: Vector<B> = Vector::with_len(size);
for i in 0..size as u32 {
let a = &mut v[i as usize];
a.set_id(i);
}
v
}
#[test]
fn reverse() {
let v = create_values(10);
let iter = v.as_view().iter().rev();
let data: Vec<_> = iter.map(|x| x.id()).collect();
assert_eq!(data, [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
}
fn test_fused_iterator(mut iter: impl Iterator, size: usize) {
for _ in 0..size {
iter.next().unwrap();
}
if let Some(_) = iter.next() {
assert!(false, "Iterator did not end properly");
}
if let Some(_) = iter.next() {
assert!(false, "Iterator did not fuse properly");
}
}
#[test]
fn fused() {
let v = create_values(100);
test_fused_iterator(v.as_view().iter(), 100);
test_fused_iterator(v.as_view().iter().rev(), 100);
}
#[test]
fn slice() {
let v = create_values(10);
let view = v.as_view();
assert_eq!(view.len(), 10);
assert_eq!(view[2..].len(), 8);
assert_eq!(view[2..].iter().next().unwrap().id(), 2);
assert_eq!(view[..8].len(), 8);
assert_eq!(view[..8].iter().next().unwrap().id(), 0);
assert_eq!(view[2..8].len(), 6);
assert_eq!(view[2..8].iter().next().unwrap().id(), 2);
}
#[test]
fn debug() {
let v = create_values(10);
let view = v.as_view();
let content = "[\
B { id: 0 }, \
B { id: 1 }, \
B { id: 2 }, \
B { id: 3 }, \
B { id: 4 }, \
B { id: 5 }, \
B { id: 6 }, \
B { id: 7 }, \
B { id: 8 }, \
B { id: 9 }\
]";
assert_eq!(format!("{:?}", view), content);
assert_eq!(
format!("{:?}", view.iter()),
"Iter(".to_string() + content + ")"
);
let mut iter = view.iter();
for _ in 0..9 {
iter.next();
}
assert_eq!(format!("{:?}", iter), "Iter([B { id: 9 }])");
}
}