use std::{
any::{Any, TypeId},
mem::{size_of, MaybeUninit},
slice,
};
use std::boxed::Box as Ptr;
#[cfg(feature = "numeric")]
use std::fmt;
#[cfg(feature = "numeric")]
use num_traits::{cast, NumCast, Zero};
use crate::bytes::Bytes;
use crate::slice_copy::*;
use crate::value::*;
use crate::{ElementBytes, ElementBytesMut};
pub trait CopyElem: Any + Copy {}
impl<T> CopyElem for T where T: Any + Copy {}
#[derive(Clone, Debug)]
pub struct VecCopy<V = ()>
where
V: ?Sized,
{
pub(crate) data: Vec<MaybeUninit<u8>>,
pub(crate) element_size: usize,
pub(crate) element_type_id: TypeId,
pub(crate) vtable: Ptr<V>,
}
impl<V> VecCopy<V> {
#[inline]
pub fn with_type<T: CopyElem>() -> Self
where
V: VTable<T>,
{
unsafe { VecCopy::with_type_non_copy::<T>() }
}
#[inline]
pub(crate) unsafe fn with_type_non_copy<T: Any>() -> Self
where
V: VTable<T>,
{
let element_size = size_of::<T>();
assert_ne!(element_size, 0, "VecCopy doesn't support zero sized types.");
VecCopy {
data: Vec::new(),
element_size,
element_type_id: TypeId::of::<T>(),
vtable: Ptr::new(V::build_vtable()),
}
}
#[inline]
pub fn with_capacity<T: CopyElem>(n: usize) -> Self
where
V: VTable<T>,
{
unsafe { VecCopy::with_capacity_non_copy::<T>(n) }
}
#[inline]
pub(crate) unsafe fn with_capacity_non_copy<T: Any>(n: usize) -> Self
where
V: VTable<T>,
{
let element_size = size_of::<T>();
assert_ne!(element_size, 0, "VecCopy doesn't support zero sized types.");
VecCopy {
data: Vec::with_capacity(n * element_size),
element_size,
element_type_id: TypeId::of::<T>(),
vtable: Ptr::new(V::build_vtable()),
}
}
#[inline]
pub fn with_size<T: CopyElem>(n: usize, def: T) -> Self
where
V: VTable<T>,
{
Self::from_vec(vec![def; n])
}
pub fn from_vec<T: CopyElem>(vec: Vec<T>) -> Self
where
V: VTable<T>,
{
unsafe { Self::from_vec_non_copy(vec) }
}
pub(crate) unsafe fn from_vec_non_copy<T: Any>(vec: Vec<T>) -> Self
where
V: VTable<T>,
{
let element_size = size_of::<T>();
assert_ne!(element_size, 0, "VecCopy doesn't support zero sized types.");
let data = {
let mut md = std::mem::ManuallyDrop::new(vec);
let len_in_bytes = md.len() * element_size;
let capacity_in_bytes = md.capacity() * element_size;
let vec_ptr = md.as_mut_ptr() as *mut MaybeUninit<u8>;
Vec::from_raw_parts(vec_ptr, len_in_bytes, capacity_in_bytes)
};
VecCopy {
data,
element_size,
element_type_id: TypeId::of::<T>(),
vtable: Ptr::new(V::build_vtable()),
}
}
#[inline]
pub fn from_slice<T: CopyElem>(slice: &[T]) -> Self
where
V: VTable<T>,
{
let mut vec = Vec::with_capacity(slice.len());
vec.extend_from_slice(slice);
Self::from_vec(vec)
}
#[inline]
pub(crate) unsafe fn from_slice_non_copy<T: Any + Clone>(slice: &[T]) -> Self
where
V: VTable<T>,
{
let mut vec = Vec::with_capacity(slice.len());
vec.extend_from_slice(slice);
Self::from_vec_non_copy(vec)
}
}
impl<V: ?Sized> VecCopy<V> {
#[inline]
pub fn with_type_from(other: impl Into<Meta<Ptr<V>>>) -> Self {
let other = other.into();
VecCopy {
data: Vec::new(),
element_size: other.element_size,
element_type_id: other.element_type_id,
vtable: other.vtable,
}
}
#[inline]
pub unsafe fn from_raw_parts(
data: Vec<MaybeUninit<u8>>,
element_size: usize,
element_type_id: TypeId,
vtable: Ptr<V>,
) -> VecCopy<V> {
VecCopy {
data,
element_size,
element_type_id,
vtable,
}
}
#[inline]
pub fn into_raw_parts(self) -> (Vec<MaybeUninit<u8>>, usize, TypeId, Ptr<V>) {
let VecCopy {
data,
element_size,
element_type_id,
vtable,
} = self;
(data, element_size, element_type_id, vtable)
}
#[inline]
pub fn upcast<U: From<V>>(self) -> VecCopy<U>
where
V: Clone,
{
self.upcast_with(U::from)
}
#[inline]
pub fn upcast_with<U>(self, f: impl FnOnce(V) -> U) -> VecCopy<U>
where
V: Clone,
{
VecCopy {
data: self.data,
element_size: self.element_size,
element_type_id: self.element_type_id,
vtable: Ptr::new(f((*self.vtable).clone())),
}
}
#[inline]
pub fn resize<T: CopyElem>(&mut self, new_len: usize, value: T) -> Option<&mut Self> {
self.check_ref::<T>()?;
let size_t = size_of::<T>();
if new_len >= self.len() {
let diff = new_len - self.len();
self.reserve_bytes(diff * size_t);
for _ in 0..diff {
self.push_as(value.clone());
}
} else {
self.data
.resize(new_len * size_t, MaybeUninit::<u8>::uninit());
}
Some(self)
}
#[inline]
pub fn copy_from_slice<T: CopyElem>(&mut self, slice: &[T]) -> &mut Self {
let element_size = size_of::<T>();
assert_ne!(element_size, 0, "VecCopy doesn't support zero sized types.");
let bins = slice.len() * element_size;
let byte_slice =
unsafe { slice::from_raw_parts(slice.as_ptr() as *const MaybeUninit<u8>, bins) };
self.data.resize(bins, MaybeUninit::<u8>::uninit());
self.data.copy_from_slice(byte_slice);
self.element_size = element_size;
self.element_type_id = TypeId::of::<T>();
self
}
#[inline]
pub fn clear(&mut self) {
self.data.clear();
}
#[inline]
pub fn fill<T: CopyElem>(&mut self, def: T) -> Option<&mut Self> {
for v in self.iter_mut_as::<T>()? {
*v = def;
}
Some(self)
}
#[inline]
pub fn push_as<T: Any>(&mut self, element: T) -> Option<&mut Self> {
self.check_ref::<T>()?;
let bytes = element.as_bytes();
let result = unsafe { self.push_bytes(bytes) };
std::mem::forget(element);
result
}
#[inline]
pub fn check<T: Any>(self) -> Option<Self> {
if TypeId::of::<T>() != self.element_type_id() {
None
} else {
Some(self)
}
}
#[inline]
pub fn check_ref<T: Any>(&self) -> Option<&Self> {
if TypeId::of::<T>() != self.element_type_id() {
None
} else {
Some(self)
}
}
#[inline]
pub fn check_mut<T: Any>(&mut self) -> Option<&mut Self> {
if TypeId::of::<T>() != self.element_type_id() {
None
} else {
Some(self)
}
}
#[inline]
pub fn element_type_id(&self) -> TypeId {
self.element_type_id
}
#[inline]
pub fn len(&self) -> usize {
debug_assert_eq!(self.data.len() % self.element_size, 0);
self.data.len() / self.element_size }
#[inline]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[inline]
pub fn byte_capacity(&self) -> usize {
self.data.capacity()
}
#[inline]
pub fn iter_as<T: Any>(&self) -> Option<slice::Iter<T>> {
self.as_slice_as::<T>().map(|x| x.iter())
}
#[inline]
pub fn iter_mut_as<T: Any>(&mut self) -> Option<slice::IterMut<T>> {
self.as_mut_slice_as::<T>().map(|x| x.iter_mut())
}
#[inline]
pub fn append_copy_to_vec<'a, T: CopyElem>(
&self,
vec: &'a mut Vec<T>,
) -> Option<&'a mut Vec<T>> {
let iter = self.iter_as()?;
vec.reserve(self.len());
vec.extend(iter);
Some(vec)
}
#[inline]
pub fn copy_into_vec<T: CopyElem>(&self) -> Option<Vec<T>> {
let mut vec = Vec::new();
match self.append_copy_to_vec(&mut vec) {
Some(_) => Some(vec),
None => None,
}
}
#[inline]
pub fn into_vec<T: Any>(self) -> Option<Vec<T>> {
unsafe { self.check::<T>().map(|x| x.reinterpret_into_vec()) }
}
#[inline]
pub fn as_slice_as<T: Any>(&self) -> Option<&[T]> {
let ptr = self.check_ref::<T>()?.data.as_ptr() as *const T;
Some(unsafe { slice::from_raw_parts(ptr, self.len()) })
}
#[inline]
pub fn as_mut_slice_as<T: Any>(&mut self) -> Option<&mut [T]> {
let ptr = self.check_mut::<T>()?.data.as_mut_ptr() as *mut T;
Some(unsafe { slice::from_raw_parts_mut(ptr, self.len()) })
}
#[inline]
pub fn get_as<T: CopyElem>(&self, i: usize) -> Option<T> {
assert!(i < self.len());
let ptr = self.check_ref::<T>()?.data.as_ptr() as *const T;
Some(unsafe { *ptr.add(i) })
}
#[inline]
pub fn get_ref_as<T: Any>(&self, i: usize) -> Option<&T> {
assert!(i < self.len());
let ptr = self.check_ref::<T>()?.data.as_ptr() as *const T;
Some(unsafe { &*ptr.add(i) })
}
#[inline]
pub fn get_mut_as<T: Any>(&mut self, i: usize) -> Option<&mut T> {
assert!(i < self.len());
let ptr = self.check_mut::<T>()?.data.as_mut_ptr() as *mut T;
Some(unsafe { &mut *ptr.add(i) })
}
#[inline]
pub fn append(&mut self, buf: &mut VecCopy<V>) -> Option<&mut Self> {
if buf.element_type_id() == self.element_type_id() {
self.data.append(&mut buf.data);
Some(self)
} else {
None
}
}
#[inline]
pub fn rotate_left(&mut self, mid: usize) {
self.data.rotate_left(mid * self.element_size);
}
#[inline]
pub fn rotate_right(&mut self, k: usize) {
self.data.rotate_right(k * self.element_size);
}
#[inline]
pub fn get_ref(&self, i: usize) -> CopyValueRef<V> {
debug_assert!(i < self.len());
unsafe {
CopyValueRef::from_raw_parts(
self.get_bytes(i),
self.element_type_id(),
self.vtable.as_ref(),
)
}
}
#[inline]
pub fn get_mut(&mut self, i: usize) -> CopyValueMut<V> {
debug_assert!(i < self.len());
let type_id = self.element_type_id();
let element_bytes = self.index_byte_range(i);
unsafe {
CopyValueMut::from_raw_parts(
&mut self.data[element_bytes],
type_id,
self.vtable.as_ref(),
)
}
}
#[inline]
pub fn iter<'a>(&'a self) -> impl Iterator<Item = CopyValueRef<'a, V>> + 'a {
self.byte_chunks().map(move |bytes| unsafe {
CopyValueRef::from_raw_parts(bytes, self.element_type_id(), &*self.vtable)
})
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = CopyValueMut<V>> {
let &mut VecCopy {
ref mut data,
element_size,
element_type_id,
ref vtable,
} = self;
let vtable = vtable.as_ref();
data.chunks_exact_mut(element_size)
.map(move |bytes| unsafe {
CopyValueMut::from_raw_parts(bytes, element_type_id, vtable)
})
}
#[inline]
pub fn push<U>(&mut self, value: CopyValueRef<U>) -> Option<&mut Self> {
assert_eq!(value.size(), self.element_size());
if value.value_type_id() == self.element_type_id() {
self.data.extend_from_slice(value.bytes);
Some(self)
} else {
None
}
}
#[inline]
pub fn as_slice(&self) -> SliceCopy<V> {
let &VecCopy {
ref data,
element_size,
element_type_id,
ref vtable,
} = self;
unsafe { SliceCopy::from_raw_parts(data, element_size, element_type_id, vtable.as_ref()) }
}
#[inline]
pub fn as_mut_slice(&mut self) -> SliceCopyMut<V> {
let &mut VecCopy {
ref mut data,
element_size,
element_type_id,
ref vtable,
} = self;
unsafe {
SliceCopyMut::from_raw_parts(data, element_size, element_type_id, vtable.as_ref())
}
}
}
impl<V> VecCopy<V> {
#[cfg(feature = "numeric")]
pub fn cast_into_vec<T>(self) -> Vec<T>
where
T: CopyElem + NumCast + Zero,
{
unsafe fn convert_into_vec<I, O, V>(buf: VecCopy<V>) -> Vec<O>
where
I: CopyElem + Any + NumCast,
O: CopyElem + NumCast + Zero,
{
debug_assert_eq!(buf.element_type_id(), TypeId::of::<I>()); buf.reinterpret_into_vec()
.into_iter()
.map(|elem: I| cast(elem).unwrap_or_else(O::zero))
.collect()
}
call_numeric_buffer_fn!( convert_into_vec::<_, T, V>(self) or { Vec::new() } )
}
#[cfg(feature = "numeric")]
unsafe fn reinterpret_display<T: CopyElem + fmt::Display>(&self, f: &mut fmt::Formatter) {
debug_assert_eq!(self.element_type_id(), TypeId::of::<T>()); for item in self.reinterpret_iter::<T>() {
write!(f, "{} ", item).expect("Error occurred while writing an VecCopy.");
}
}
}
impl<'a, V: Clone + ?Sized + 'a> std::iter::FromIterator<CopyValueRef<'a, V>> for VecCopy<V> {
#[inline]
fn from_iter<T: IntoIterator<Item = CopyValueRef<'a, V>>>(iter: T) -> Self {
let mut iter = iter.into_iter();
let next = iter
.next()
.expect("VecCopy cannot be built from an empty untyped iterator.");
let mut data = Vec::with_capacity(next.size() * iter.size_hint().0);
data.extend_from_slice(next.bytes);
let mut buf = VecCopy {
data,
element_size: next.size(),
element_type_id: next.value_type_id(),
vtable: Ptr::new(next.vtable.take()),
};
buf.extend(iter);
buf
}
}
impl<'a, V: ?Sized + 'a> Extend<CopyValueRef<'a, V>> for VecCopy<V> {
#[inline]
fn extend<T: IntoIterator<Item = CopyValueRef<'a, V>>>(&mut self, iter: T) {
for value in iter {
assert_eq!(value.size(), self.element_size());
assert_eq!(value.value_type_id(), self.element_type_id());
self.data.extend_from_slice(value.bytes);
}
}
}
impl<V: ?Sized + Clone> VecCopy<V> {
pub(crate) fn clone_with(
&self,
clone: impl FnOnce(&[MaybeUninit<u8>]) -> Vec<MaybeUninit<u8>>,
) -> Self {
VecCopy {
data: clone(&self.data),
element_size: self.element_size,
element_type_id: self.element_type_id,
vtable: Ptr::clone(&self.vtable),
}
}
}
impl<V: ?Sized> VecCopy<V> {
#[inline]
pub fn reserve_bytes(&mut self, additional: usize) {
self.data.reserve(additional);
}
#[inline]
pub unsafe fn get_unchecked<T: CopyElem>(&self, i: usize) -> T {
let ptr = self.data.as_ptr() as *const T;
*ptr.add(i)
}
#[inline]
pub unsafe fn get_unchecked_ref<T: CopyElem>(&self, i: usize) -> &T {
let ptr = self.data.as_ptr() as *const T;
&*ptr.add(i)
}
#[inline]
pub unsafe fn get_unchecked_mut<T: CopyElem>(&mut self, i: usize) -> &mut T {
let ptr = self.data.as_mut_ptr() as *mut T;
&mut *ptr.add(i)
}
#[inline]
pub fn get_bytes(&self, i: usize) -> &[MaybeUninit<u8>] {
debug_assert!(i < self.len());
let element_size = self.element_size();
&self.data[i * element_size..(i + 1) * element_size]
}
#[inline]
pub unsafe fn get_bytes_mut(&mut self, i: usize) -> &mut [MaybeUninit<u8>] {
debug_assert!(i < self.len());
self.index_byte_slice_mut(i)
}
#[inline]
pub unsafe fn reinterpret_into_vec<T>(self) -> Vec<T> {
reinterpret::reinterpret_vec(self.data)
}
#[inline]
pub unsafe fn reinterpret_as_slice<T>(&self) -> &[T] {
reinterpret::reinterpret_slice(self.data.as_slice())
}
#[inline]
pub unsafe fn reinterpret_as_mut_slice<T>(&mut self) -> &mut [T] {
reinterpret::reinterpret_mut_slice(self.data.as_mut_slice())
}
#[inline]
pub unsafe fn reinterpret_iter<T>(&self) -> slice::Iter<T> {
self.reinterpret_as_slice().iter()
}
#[inline]
pub unsafe fn reinterpret_iter_mut<T>(&mut self) -> slice::IterMut<T> {
self.reinterpret_as_mut_slice().iter_mut()
}
#[inline]
pub fn as_bytes(&self) -> &[MaybeUninit<u8>] {
self.data.as_slice()
}
#[inline]
pub unsafe fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
self.data.as_mut_slice()
}
#[inline]
pub fn byte_chunks<'a>(&'a self) -> impl Iterator<Item = &'a [MaybeUninit<u8>]> + 'a {
let chunk_size = self.element_size();
self.data.chunks_exact(chunk_size)
}
#[inline]
pub unsafe fn byte_chunks_mut<'a>(
&'a mut self,
) -> impl Iterator<Item = &'a mut [MaybeUninit<u8>]> + 'a {
let chunk_size = self.element_size();
self.data.chunks_exact_mut(chunk_size)
}
#[inline]
pub unsafe fn push_bytes(&mut self, bytes: &[MaybeUninit<u8>]) -> Option<&mut Self> {
if bytes.len() == self.element_size() {
self.data.extend_from_slice(bytes);
Some(self)
} else {
None
}
}
#[inline]
pub unsafe fn extend_bytes(&mut self, bytes: &[MaybeUninit<u8>]) -> Option<&mut Self> {
let element_size = self.element_size();
if bytes.len() % element_size == 0 {
self.data.extend_from_slice(bytes);
Some(self)
} else {
None
}
}
#[inline]
pub unsafe fn append_bytes(&mut self, bytes: &mut Vec<MaybeUninit<u8>>) -> Option<&mut Self> {
let element_size = self.element_size();
if bytes.len() % element_size == 0 {
self.data.append(bytes);
Some(self)
} else {
None
}
}
}
impl<'a, V> From<&'a VecCopy<V>> for Meta<VTableRef<'a, V>> {
#[inline]
fn from(vec: &'a VecCopy<V>) -> Meta<VTableRef<'a, V>> {
Meta {
element_size: vec.element_size,
element_type_id: vec.element_type_id,
vtable: VTableRef::Ref(vec.vtable.as_ref()),
}
}
}
impl<'a, V> From<&'a VecCopy<V>> for Meta<Ptr<V>>
where
Ptr<V>: Clone,
{
#[inline]
fn from(vec: &'a VecCopy<V>) -> Meta<Ptr<V>> {
Meta {
element_size: vec.element_size,
element_type_id: vec.element_type_id,
vtable: vec.vtable.clone(),
}
}
}
impl<V: ?Sized> ElementBytes for VecCopy<V> {
fn element_size(&self) -> usize {
self.element_size
}
fn bytes(&self) -> &[MaybeUninit<u8>] {
self.data.as_ref()
}
}
impl<V: ?Sized> ElementBytesMut for VecCopy<V> {
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
self.data.as_mut()
}
}
impl<T, V> From<Vec<T>> for VecCopy<V>
where
T: CopyElem,
V: VTable<T>,
{
#[inline]
fn from(vec: Vec<T>) -> VecCopy<V> {
VecCopy::from_vec(vec)
}
}
impl<'a, T, V> From<&'a [T]> for VecCopy<V>
where
T: CopyElem,
V: VTable<T>,
{
#[inline]
fn from(slice: &'a [T]) -> VecCopy<V> {
VecCopy::from_slice(slice)
}
}
impl<T, V: ?Sized> Into<Option<Vec<T>>> for VecCopy<V>
where
T: CopyElem,
{
#[inline]
fn into(self) -> Option<Vec<T>> {
self.into_vec()
}
}
#[cfg(feature = "numeric")]
impl<V> fmt::Display for VecCopy<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
call_numeric_buffer_fn!( self.reinterpret_display::<_>(f) or {
println!("Unknown VecCopy type for pretty printing.");
} );
write!(f, "")
}
}
#[cfg(test)]
mod tests {
use super::*;
type VecUnit = super::VecCopy<()>;
#[test]
fn initialization_test() {
let a = VecUnit::with_type::<f32>();
assert_eq!(a.len(), 0);
assert_eq!(a.as_bytes().len(), 0);
assert_eq!(a.element_type_id(), TypeId::of::<f32>());
assert_eq!(a.byte_capacity(), 0);
let b = VecUnit::with_type_from(&a);
assert_eq!(b.len(), 0);
assert_eq!(b.as_bytes().len(), 0);
assert_eq!(b.element_type_id(), TypeId::of::<f32>());
assert_eq!(a.byte_capacity(), 0);
let a = VecUnit::with_capacity::<f32>(4);
assert_eq!(a.len(), 0);
assert_eq!(a.as_bytes().len(), 0);
assert_eq!(a.byte_capacity(), 4 * size_of::<f32>());
assert_eq!(a.element_type_id(), TypeId::of::<f32>());
}
#[test]
fn reserve_bytes() {
let mut a = VecUnit::with_type::<f32>();
assert_eq!(a.byte_capacity(), 0);
a.reserve_bytes(10);
assert_eq!(a.len(), 0);
assert_eq!(a.as_bytes().len(), 0);
assert!(a.byte_capacity() >= 10);
}
#[test]
fn resize() {
let mut a = VecUnit::with_type::<f32>();
a.resize(3, 1.0f32);
assert_eq!(a.len(), 3);
assert_eq!(a.as_bytes().len(), 12);
for i in 0..3 {
assert_eq!(a.get_as::<f32>(i).unwrap(), 1.0f32);
}
a.resize(2, 1.0f32);
assert_eq!(a.len(), 2);
assert_eq!(a.as_bytes().len(), 8);
for i in 0..2 {
assert_eq!(a.get_as::<f32>(i).unwrap(), 1.0f32);
}
}
#[test]
#[should_panic]
fn zero_size_with_type_test() {
let _a = VecUnit::with_type::<()>();
}
#[test]
#[should_panic]
fn zero_size_with_capacity_test() {
let _a = VecUnit::with_capacity::<()>(2);
}
#[test]
#[should_panic]
fn zero_size_from_vec_test() {
let _a = VecUnit::from_vec(vec![(); 3]);
}
#[test]
#[should_panic]
fn zero_size_with_size_test() {
let _a = VecUnit::with_size(3, ());
}
#[test]
#[should_panic]
fn zero_size_from_slice_test() {
let v = vec![(); 3];
let _a = VecUnit::from_slice(&v);
}
#[test]
#[should_panic]
fn zero_size_copy_from_slice_test() {
let v = vec![(); 3];
let mut a = VecUnit::with_size(0, 1i32);
a.copy_from_slice(&v);
}
#[test]
fn data_integrity_u8_test() {
let vec = vec![1u8, 3, 4, 1, 2];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<u8> = buf.copy_into_vec().unwrap(); assert_eq!(vec, nu_vec);
let vec = vec![1u8, 3, 4, 1, 2, 52, 1, 3, 41, 23, 2];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<u8> = buf.copy_into_vec().unwrap(); assert_eq!(vec, nu_vec);
}
#[test]
fn data_integrity_i16_test() {
let vec = vec![1i16, -3, 1002, -231, 32];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<i16> = buf.copy_into_vec().unwrap(); assert_eq!(vec, nu_vec);
let vec = vec![1i16, -3, 1002, -231, 32, 42, -123, 4];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<i16> = buf.copy_into_vec().unwrap(); assert_eq!(vec, nu_vec);
}
#[test]
fn data_integrity_i32_test() {
let vec = vec![1i32, -3, 1002, -231, 32];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<i32> = buf.into_vec().unwrap(); assert_eq!(vec, nu_vec);
let vec = vec![1i32, -3, 1002, -231, 32, 42, -123];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<i32> = buf.into_vec().unwrap(); assert_eq!(vec, nu_vec);
}
#[test]
fn data_integrity_f32_test() {
let vec = vec![1.0_f32, 23.0, 0.01, 42.0, 11.43];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<f32> = buf.into_vec().unwrap(); assert_eq!(vec, nu_vec);
let vec = vec![1.0_f32, 23.0, 0.01, 42.0, 11.43, 2e-1];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<f32> = buf.into_vec().unwrap(); assert_eq!(vec, nu_vec);
}
#[test]
fn data_integrity_f64_test() {
let vec = vec![1f64, -3.0, 10.02, -23.1, 32e-1];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<f64> = buf.copy_into_vec().unwrap(); assert_eq!(vec, nu_vec);
let vec = vec![1f64, -3.1, 100.2, -2.31, 3.2, 4e2, -1e23];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<f64> = buf.copy_into_vec().unwrap(); assert_eq!(vec, nu_vec);
}
#[cfg(feature = "numeric")]
#[test]
fn convert_float_test() {
let vecf64 = vec![1f64, -3.0, 10.02, -23.1, 32e-1];
let buf = VecUnit::from(vecf64.clone()); let nu_vec: Vec<f32> = buf.cast_into_vec(); let vecf32 = vec![1f32, -3.0, 10.02, -23.1, 32e-1];
assert_eq!(vecf32, nu_vec);
let buf = VecUnit::from(vecf32.clone()); let nu_vec: Vec<f64> = buf.cast_into_vec(); for (&a, &b) in vecf64.iter().zip(nu_vec.iter()) {
assert!((a - b).abs() < 1e-6f64 * f64::max(a, b).abs());
}
let vecf64 = vec![1f64, -3.1, 100.2, -2.31, 3.2, 4e2, -1e23];
let buf = VecUnit::from(vecf64.clone()); let nu_vec: Vec<f32> = buf.cast_into_vec(); let vecf32 = vec![1f32, -3.1, 100.2, -2.31, 3.2, 4e2, -1e23];
assert_eq!(vecf32, nu_vec);
let buf = VecUnit::from(vecf32.clone()); let nu_vec: Vec<f64> = buf.cast_into_vec(); for (&a, &b) in vecf64.iter().zip(nu_vec.iter()) {
assert!((a - b).abs() < 1e-6 * f64::max(a, b).abs());
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
struct Foo {
a: u8,
b: i64,
c: f32,
}
#[test]
fn from_empty_vec_test() {
let vec: Vec<u32> = Vec::new();
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<u32> = buf.into_vec().unwrap(); assert_eq!(vec, nu_vec);
let vec: Vec<Foo> = Vec::new();
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<Foo> = buf.into_vec().unwrap(); assert_eq!(vec, nu_vec);
}
#[test]
fn from_struct_test() {
let f1 = Foo {
a: 3,
b: -32,
c: 54.2,
};
let f2 = Foo {
a: 33,
b: -3342432412,
c: 323454.2,
};
let vec = vec![f1.clone(), f2.clone()];
let buf = VecUnit::from(vec.clone()); assert_eq!(f1, buf.get_ref_as::<Foo>(0).unwrap().clone());
assert_eq!(f2, buf.get_ref_as::<Foo>(1).unwrap().clone());
let nu_vec: Vec<Foo> = buf.into_vec().unwrap(); assert_eq!(vec, nu_vec);
}
#[test]
fn iter_test() {
let vec_f32 = vec![1.0_f32, 23.0, 0.01, 42.0, 11.43];
let buf = VecUnit::from(vec_f32.clone()); for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, vec_f32[i]);
}
let vec_u8 = vec![1u8, 3, 4, 1, 2, 4, 128, 32];
let buf = VecUnit::from(vec_u8.clone()); for (i, &val) in buf.iter_as::<u8>().unwrap().enumerate() {
assert_eq!(val, vec_u8[i]);
}
unsafe {
let vec_u32 = vec![17_040_129u32, 545_260_546]; let buf = VecUnit::from(vec_u8.clone()); for (i, &val) in buf.reinterpret_iter::<u32>().enumerate() {
assert_eq!(val, vec_u32[i]);
}
let mut buf2 = VecUnit::from(vec_u32); for (i, &val) in buf2.reinterpret_iter::<u8>().enumerate() {
assert_eq!(val, vec_u8[i]);
}
buf2.reinterpret_iter_mut::<u8>().for_each(|val| *val += 1);
let u8_check_vec = vec![2u8, 4, 5, 2, 3, 5, 129, 33];
assert_eq!(buf2.reinterpret_into_vec::<u8>(), u8_check_vec);
}
}
#[test]
fn large_sizes_test() {
for i in 1000000..1000010 {
let vec = vec![32u8; i];
let buf = VecUnit::from(vec.clone()); let nu_vec: Vec<u8> = buf.into_vec().unwrap(); assert_eq!(vec, nu_vec);
}
}
#[test]
fn wrong_type_test() {
let vec = vec![1.0_f32, 23.0, 0.01, 42.0, 11.43];
let mut buf = VecUnit::from(vec.clone()); assert_eq!(vec, buf.copy_into_vec::<f32>().unwrap());
assert!(buf.copy_into_vec::<f64>().is_none());
assert!(buf.as_slice_as::<f64>().is_none());
assert!(buf.as_mut_slice_as::<u8>().is_none());
assert!(buf.iter_as::<[f32; 3]>().is_none());
assert!(buf.get_as::<i32>(0).is_none());
assert!(buf.get_ref_as::<i32>(1).is_none());
assert!(buf.get_mut_as::<i32>(2).is_none());
}
#[test]
fn byte_chunks_test() {
let vec_f32 = vec![1.0_f32, 23.0, 0.01, 42.0, 11.43];
let buf = VecUnit::from(vec_f32.clone());
for (i, val) in buf.byte_chunks().enumerate() {
assert_eq!(
unsafe { reinterpret::reinterpret_slice::<_, f32>(val)[0] },
vec_f32[i]
);
}
}
#[test]
fn push_test() {
let mut vec_f32 = vec![1.0_f32, 23.0, 0.01];
let mut buf = VecUnit::from(vec_f32.clone()); for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, vec_f32[i]);
}
vec_f32.push(42.0f32);
buf.push_as(42.0f32).unwrap();
for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, vec_f32[i]);
}
vec_f32.push(11.43);
buf.push_as(11.43f32).unwrap();
for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, vec_f32[i]);
}
vec_f32.push(0.0);
vec_f32.push(0.0);
unsafe { buf.extend_bytes(&[MaybeUninit::new(0u8); 8]) }.unwrap();
for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, vec_f32[i]);
}
for i in 5..7 {
assert_eq!(
unsafe { std::mem::transmute::<_, &[u8]>(buf.get_bytes(i)) },
&[0u8; 4][..]
);
assert_eq!(
unsafe { std::mem::transmute::<_, &mut [u8]>(buf.get_bytes_mut(i)) },
&[0u8; 4][..]
);
}
vec_f32.push(0.0);
unsafe { buf.push_bytes(&[MaybeUninit::new(0); 4][..]) }.unwrap();
for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, vec_f32[i]);
}
}
#[test]
fn append_test() {
let mut buf = VecUnit::with_type::<f32>();
let data = vec![1.0_f32, 23.0, 0.01, 42.0, 11.43];
let mut other_buf = VecUnit::from_vec(data.clone());
buf.append(&mut other_buf);
assert!(other_buf.is_empty());
for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, data[i]);
}
}
#[test]
fn extend_append_bytes_test() {
let mut buf = VecUnit::with_type::<f32>();
let vec_f32 = vec![1.0_f32, 23.0, 0.01, 42.0, 11.43];
let mut vec_bytes: Vec<MaybeUninit<u8>> =
unsafe { reinterpret::reinterpret_vec(vec_f32.clone()) };
unsafe { buf.append_bytes(&mut vec_bytes) };
for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, vec_f32[i]);
}
buf.clear();
assert_eq!(buf.len(), 0);
unsafe { buf.append_bytes(&mut vec![MaybeUninit::new(0u8); 4]) };
assert_eq!(buf.get_as::<f32>(0).unwrap(), 0.0f32);
buf.clear();
assert_eq!(buf.len(), 0);
let slice_bytes: &[MaybeUninit<u8>] = unsafe { reinterpret::reinterpret_slice(&vec_f32) };
unsafe { buf.extend_bytes(slice_bytes) };
for (i, &val) in buf.iter_as::<f32>().unwrap().enumerate() {
assert_eq!(val, vec_f32[i]);
}
}
#[test]
fn dynamic_vtables() {
use crate::into_dyn;
let buf = VecUnit::with_type::<u8>();
let mut buf_dyn = into_dyn;
buf_dyn.push(CopyValueRef::<()>::new(&1u8));
buf_dyn.push(CopyValueRef::<()>::new(&100u8));
buf_dyn.push(CopyValueRef::<()>::new(&23u8));
let vec: Vec<u8> = buf_dyn.into_vec().unwrap();
assert_eq!(vec, vec![1u8, 100, 23]);
}
}