#![allow(dead_code)]
use std::{
any::{Any, TypeId},
fmt,
mem::{ManuallyDrop, MaybeUninit},
slice,
};
use std::boxed::Box as Ptr;
#[cfg(feature = "numeric")]
use num_traits::{cast, NumCast, Zero};
use crate::slice_drop::*;
use crate::traits::*;
use crate::value::*;
use crate::ElementBytes;
use crate::VecCopy;
pub trait Elem: Any + DropBytes {}
impl<T> Elem for T where T: Any + DropBytes {}
pub struct VecDrop<V = (DropFn, ())>
where
V: ?Sized + HasDrop,
{
data: ManuallyDrop<VecCopy<V>>,
}
impl<V: ?Sized + HasDrop> Drop for VecDrop<V> {
fn drop(&mut self) {
unsafe {
{
let VecCopy {
data,
vtable,
element_size,
..
} = &mut *self.data;
let chunks_iter = data.chunks_exact_mut(*element_size);
for elem_bytes in chunks_iter {
vtable.drop_fn()(elem_bytes);
}
}
ManuallyDrop::drop(&mut self.data);
}
}
}
impl<V: ?Sized + Clone + HasDrop + HasClone> Clone for VecDrop<V> {
fn clone(&self) -> Self {
let data_clone = |bytes: &[MaybeUninit<u8>]| {
let mut new_data = bytes.to_vec();
self.data
.byte_chunks()
.zip(new_data.chunks_exact_mut(self.data.element_size()))
.for_each(|(src, dst)| unsafe {
self.data.vtable.clone_into_raw_fn()(src, dst)
});
new_data
};
VecDrop {
data: ManuallyDrop::new(self.data.clone_with(data_clone)),
}
}
}
impl<V: ?Sized + HasDrop + HasPartialEq> PartialEq for VecDrop<V> {
fn eq(&self, other: &Self) -> bool {
self.iter()
.zip(other.iter())
.all(|(this, that)| this == that)
}
}
impl<V: ?Sized + HasDrop + HasEq> Eq for VecDrop<V> {}
impl<V: ?Sized + HasDrop + HasHash> std::hash::Hash for VecDrop<V> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.iter().for_each(|elem| elem.hash(state));
}
}
impl<V: ?Sized + HasDrop + HasDebug> fmt::Debug for VecDrop<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
unsafe impl<V: ?Sized + HasDrop + HasSend> Send for VecDrop<V> {}
unsafe impl<V: ?Sized + HasDrop + HasSync> Sync for VecDrop<V> {}
impl<V: HasDrop> VecDrop<V> {
#[inline]
pub fn with_type<T: Elem>() -> Self
where
V: VTable<T>,
{
VecDrop {
data: ManuallyDrop::new(unsafe { VecCopy::with_type_non_copy::<T>() }),
}
}
#[inline]
pub fn with_capacity<T: Elem>(n: usize) -> Self
where
V: VTable<T>,
{
VecDrop {
data: ManuallyDrop::new(unsafe { VecCopy::with_capacity_non_copy::<T>(n) }),
}
}
pub fn from_vec<T: Elem>(vec: Vec<T>) -> Self
where
V: VTable<T>,
{
VecDrop {
data: ManuallyDrop::new(unsafe { VecCopy::from_vec_non_copy(vec) }),
}
}
}
impl<V: ?Sized + HasDrop> VecDrop<V> {
#[inline]
pub fn with_type_from(other: impl Into<Meta<Ptr<V>>>) -> Self {
VecDrop {
data: ManuallyDrop::new(VecCopy::with_type_from(other.into())),
}
}
#[inline]
pub unsafe fn from_raw_parts(
data: Vec<MaybeUninit<u8>>,
element_size: usize,
element_type_id: TypeId,
vtable: Ptr<V>,
) -> VecDrop<V> {
VecDrop {
data: ManuallyDrop::new(VecCopy {
data,
element_size,
element_type_id,
vtable,
}),
}
}
#[inline]
pub fn into_raw_parts(self) -> (Vec<MaybeUninit<u8>>, usize, TypeId, Ptr<V>) {
unsafe {
let mut md = ManuallyDrop::new(self);
let VecCopy {
data,
element_size,
element_type_id,
vtable,
} = ManuallyDrop::take(&mut md.data);
(data, element_size, element_type_id, vtable)
}
}
pub fn vtable(&self) -> &V {
&self.data.vtable
}
#[inline]
pub fn upcast<U: HasDrop + From<V>>(self) -> VecDrop<U>
where
V: Clone,
{
let mut md = ManuallyDrop::new(self);
let data = unsafe { ManuallyDrop::take(&mut md.data) };
VecDrop {
data: ManuallyDrop::new(data.upcast()),
}
}
#[inline]
pub fn clear(&mut self) {
unsafe {
let VecCopy {
data,
vtable,
element_size,
..
} = &mut *self.data;
let chunks_iter = data.chunks_exact_mut(*element_size);
for elem_bytes in chunks_iter {
vtable.drop_fn()(elem_bytes);
}
data.clear();
}
}
#[inline]
pub fn push_as<T: Elem>(&mut self, element: T) -> Option<&mut Self> {
if self.data.push_as(element).is_some() {
Some(self)
} else {
None
}
}
#[inline]
pub fn check<T: Elem>(self) -> Option<Self> {
if self.data.check_ref::<T>().is_some() {
Some(self)
} else {
None
}
}
#[inline]
pub fn check_ref<T: Elem>(&self) -> Option<&Self> {
self.data.check_ref::<T>().map(|_| self)
}
#[inline]
pub fn check_mut<T: Elem>(&mut self) -> Option<&mut Self> {
if self.data.check_mut::<T>().is_some() {
Some(self)
} else {
None
}
}
#[inline]
pub fn element_type_id(&self) -> TypeId {
self.data.element_type_id()
}
#[inline]
pub fn len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[inline]
pub fn byte_capacity(&self) -> usize {
self.data.byte_capacity()
}
#[inline]
pub fn element_size(&self) -> usize {
self.data.element_size()
}
#[inline]
pub fn iter_as<T: Elem>(&self) -> Option<slice::Iter<T>> {
self.data.iter_as::<T>()
}
#[inline]
pub fn iter_mut_as<T: Elem>(&mut self) -> Option<slice::IterMut<T>> {
self.data.iter_mut_as::<T>()
}
#[inline]
pub fn into_vec<T: Elem>(self) -> Option<Vec<T>> {
unsafe {
let mut no_drop = ManuallyDrop::new(self);
ManuallyDrop::take(&mut no_drop.data).into_vec()
}
}
#[inline]
pub fn as_slice_as<T: Elem>(&self) -> Option<&[T]> {
self.data.as_slice_as()
}
#[inline]
pub fn as_mut_slice_as<T: Elem>(&mut self) -> Option<&mut [T]> {
self.data.as_mut_slice_as()
}
#[inline]
pub fn get_ref_as<T: Elem>(&self, i: usize) -> Option<&T> {
self.data.get_ref_as::<T>(i)
}
#[inline]
pub fn get_mut_as<T: Elem>(&mut self, i: usize) -> Option<&mut T> {
self.data.get_mut_as::<T>(i)
}
#[inline]
pub fn append(&mut self, buf: &mut VecDrop<V>) -> Option<&mut Self> {
if self.data.append(&mut buf.data).is_some() {
Some(self)
} else {
None
}
}
#[inline]
pub fn rotate_left(&mut self, mid: usize) {
self.data.rotate_left(mid)
}
#[inline]
pub fn rotate_right(&mut self, k: usize) {
self.data.rotate_right(k)
}
#[inline]
pub fn push<U: ?Sized + HasDrop>(&mut self, value: BoxValue<U>) -> Option<&mut Self> {
if self.element_type_id() == value.value_type_id() {
let (bytes, _, _) = value.into_raw_parts();
self.data.data.extend_from_slice(&*bytes);
Some(self)
} else {
None
}
}
#[inline]
pub fn push_cloned(&mut self, value: ValueRef<V>) -> Option<&mut Self>
where
V: HasClone,
{
if self.element_type_id() == value.value_type_id() {
let orig_len = self.data.data.len();
self.data
.data
.resize(orig_len + value.bytes.len(), MaybeUninit::<u8>::uninit());
unsafe {
self.data.vtable.clone_into_raw_fn()(value.bytes, &mut self.data.data[orig_len..]);
}
Some(self)
} else {
None
}
}
#[inline]
pub fn get(&self, i: usize) -> ValueRef<V> {
debug_assert!(i < self.len());
unsafe {
ValueRef::from_raw_parts(
self.data.get_bytes(i),
self.element_type_id(),
self.data.vtable.as_ref(),
)
}
}
#[inline]
pub fn iter<'a>(&'a self) -> impl Iterator<Item = ValueRef<'a, V>> + 'a {
let &Self { ref data, .. } = self;
let VecCopy {
data,
element_size,
element_type_id,
vtable,
} = &**data;
data.chunks_exact(*element_size).map(move |bytes| unsafe {
ValueRef::from_raw_parts(bytes, *element_type_id, vtable.as_ref())
})
}
#[inline]
pub fn get_mut(&mut self, i: usize) -> ValueMut<V> {
debug_assert!(i < self.len());
let Self { data, .. } = self;
let element_bytes = data.index_byte_range(i);
let &mut VecCopy {
ref mut data,
element_type_id,
ref vtable,
..
} = &mut **data;
unsafe {
ValueMut::from_raw_parts(&mut data[element_bytes], element_type_id, vtable.as_ref())
}
}
#[inline]
pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = ValueMut<'a, V>> + 'a
where
V: Clone,
{
let VecCopy {
ref mut data,
element_size,
element_type_id,
ref vtable,
} = *self.data;
let vtable = vtable.as_ref();
data.chunks_exact_mut(element_size)
.map(move |bytes| unsafe { ValueMut::from_raw_parts(bytes, element_type_id, vtable) })
}
pub fn as_slice(&self) -> SliceDrop<V> {
let VecCopy {
ref data,
element_size,
element_type_id,
ref vtable,
} = *self.data;
unsafe { SliceDrop::from_raw_parts(data, element_size, element_type_id, vtable.as_ref()) }
}
pub fn as_mut_slice(&mut self) -> SliceDropMut<V> {
let VecCopy {
ref mut data,
element_size,
element_type_id,
ref vtable,
} = *self.data;
unsafe {
SliceDropMut::from_raw_parts(data, element_size, element_type_id, vtable.as_ref())
}
}
#[inline]
pub unsafe fn get_unchecked_ref<T: Any>(&self, i: usize) -> &T {
let ptr = self.data.data.as_ptr() as *const T;
&*ptr.add(i)
}
#[inline]
pub unsafe fn get_unchecked_mut<T: Any>(&mut self, i: usize) -> &mut T {
let ptr = self.data.data.as_mut_ptr() as *mut T;
&mut *ptr.add(i)
}
}
impl<V: HasDrop + HasClone> VecDrop<V> {
#[inline]
pub fn with_size<T: Elem + Clone>(n: usize, def: T) -> Self
where
V: VTable<T>,
{
VecDrop {
data: ManuallyDrop::new(unsafe { VecCopy::from_vec_non_copy(vec![def; n]) }),
}
}
#[inline]
pub fn from_slice<T: Elem + Clone>(slice: &[T]) -> Self
where
V: VTable<T>,
{
VecDrop {
data: ManuallyDrop::new(unsafe { VecCopy::from_slice_non_copy::<T>(slice) }),
}
}
}
impl<V: HasDrop> VecDrop<V> {
#[cfg(feature = "numeric")]
pub fn cast_into_vec<T>(&self) -> Option<Vec<T>>
where
T: Elem + Copy + NumCast + Zero,
{
use crate::CopyElem;
unsafe fn convert_into_vec<I, O, V>(buf: &VecCopy<V>) -> Option<Vec<O>>
where
I: CopyElem + Any + NumCast,
O: CopyElem + NumCast + Zero,
{
debug_assert_eq!(buf.element_type_id(), TypeId::of::<I>());
Some(
buf.reinterpret_as_slice()
.iter()
.map(|elem: &I| cast(*elem).unwrap_or_else(O::zero))
.collect(),
)
}
call_numeric_buffer_fn!( convert_into_vec::<_, T, V>(&self.data) or { None } )
}
}
impl<V: ?Sized + HasDrop + HasClone> VecDrop<V> {
#[inline]
pub fn resize<T: Elem + Clone>(&mut self, new_len: usize, value: T) -> Option<&mut Self> {
self.check_ref::<T>()?;
let size_t = std::mem::size_of::<T>();
if new_len >= self.len() {
let diff = new_len - self.len();
self.data.reserve_bytes(diff * size_t);
for _ in 0..diff {
self.data.push_as(value.clone());
}
} else {
unsafe {
let VecCopy {
data,
vtable,
element_size,
..
} = &mut *self.data;
let chunks_iter = data.chunks_exact_mut(*element_size);
for elem_bytes in chunks_iter.skip(new_len) {
vtable.drop_fn()(elem_bytes);
}
}
self.data
.data
.resize(new_len * size_t, MaybeUninit::<u8>::uninit());
}
Some(self)
}
#[inline]
pub fn fill<T: Elem + Clone>(&mut self, def: T) -> Option<&mut Self> {
for v in self.iter_mut_as::<T>()? {
*v = def.clone();
}
Some(self)
}
#[inline]
pub fn append_cloned_to_vec<'a, T: Elem + Clone>(
&self,
vec: &'a mut Vec<T>,
) -> Option<&'a mut Vec<T>> {
let slice = self.as_slice_as()?;
vec.reserve(self.len());
vec.extend_from_slice(slice);
Some(vec)
}
#[inline]
pub fn clone_into_vec<T: Elem + Clone>(&self) -> Option<Vec<T>> {
let mut vec = Vec::new();
match self.append_cloned_to_vec(&mut vec) {
Some(_) => Some(vec),
None => None,
}
}
}
impl<'a, V: Clone + HasDrop> From<&'a VecDrop<V>> for Meta<Ptr<V>> {
#[inline]
fn from(v: &'a VecDrop<V>) -> Self {
Meta::from(&*v.data)
}
}
impl<'a, V: Clone + HasDrop> From<&'a VecDrop<V>> for Meta<VTableRef<'a, V>> {
#[inline]
fn from(v: &'a VecDrop<V>) -> Self {
Meta::from(&*v.data)
}
}
impl<T: Elem, V: HasDrop + VTable<T>> From<Vec<T>> for VecDrop<V> {
#[inline]
fn from(vec: Vec<T>) -> VecDrop<V> {
VecDrop::from_vec(vec)
}
}
impl<'a, T, V> From<&'a [T]> for VecDrop<V>
where
T: Elem + Clone,
V: HasDrop + VTable<T> + HasClone,
{
#[inline]
fn from(slice: &'a [T]) -> VecDrop<V> {
VecDrop::from_slice(slice)
}
}
impl<T: Elem, V: ?Sized + HasDrop + VTable<T>> Into<Option<Vec<T>>> for VecDrop<V> {
#[inline]
fn into(self) -> Option<Vec<T>> {
self.into_vec()
}
}
#[cfg(test)]
mod tests {
use super::*;
use dync_derive::dync_trait;
use rand::prelude::*;
use std::mem::size_of;
use std::rc::Rc;
#[dync_trait(dync_crate_name = "crate")]
pub trait AllTrait: Clone + PartialEq + Eq + std::hash::Hash + std::fmt::Debug {}
impl<T> AllTrait for T where T: Clone + PartialEq + Eq + std::hash::Hash + std::fmt::Debug {}
type VecCopyAll = VecCopy<AllTraitVTable>;
type VecDropAll = VecDrop<AllTraitVTable>;
#[inline]
fn compute(x: i64, y: i64, z: i64) -> [i64; 3] {
[x - 2 * y + z * 2, y - 2 * z + x * 2, z - 2 * x + y * 2]
}
#[inline]
fn make_random_vec_copy(n: usize) -> VecCopyAll {
make_random_vec(n).into()
}
#[inline]
fn make_random_vec_dyn(n: usize) -> VecDropAll {
make_random_vec(n).into()
}
#[inline]
fn make_random_vec(n: usize) -> Vec<[i64; 3]> {
let mut rng: StdRng = SeedableRng::from_seed([3; 32]);
let between = rand::distributions::Uniform::from(1i64..5);
(0..n).map(move |_| [between.sample(&mut rng); 3]).collect()
}
#[inline]
fn vec_copy_compute<V>(v: &mut VecCopy<V>) {
for a in v.iter_mut() {
let a = a.downcast::<[i64; 3]>().unwrap();
let res = compute(a[0], a[1], a[2]);
a[0] = res[0];
a[1] = res[1];
a[2] = res[2];
}
}
#[inline]
fn vec_dyn_compute<V: Clone + HasDrop>(v: &mut VecDrop<V>) {
for a in v.iter_mut() {
let a = a.downcast::<[i64; 3]>().unwrap();
let res = compute(a[0], a[1], a[2]);
a[0] = res[0];
a[1] = res[1];
a[2] = res[2];
}
}
#[inline]
fn vec_compute(v: &mut Vec<[i64; 3]>) {
for a in v.iter_mut() {
let res = compute(a[0], a[1], a[2]);
a[0] = res[0];
a[1] = res[1];
a[2] = res[2];
}
}
#[test]
fn downcast_value_mut() {
use std::time::Instant;
let size = 90_000;
let mut v: VecDropAll = make_random_vec_dyn(size);
let start = Instant::now();
vec_dyn_compute(&mut v);
eprintln!("vec_dyn: {} millis", start.elapsed().as_millis());
let mut v: VecCopyAll = make_random_vec_copy(size);
let start = Instant::now();
vec_copy_compute(&mut v);
eprintln!("vec_copy: {} millis", start.elapsed().as_millis());
let mut v: Vec<[i64; 3]> = make_random_vec(size);
let start = Instant::now();
vec_compute(&mut v);
eprintln!("vec: {} millis", start.elapsed().as_millis());
}
#[test]
fn clone_from_test() {
use std::collections::HashSet;
let vec_rc: Vec<_> = vec![1, 23, 2, 42, 23, 1, 13534653]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec_rc.clone());
let mut hashset: HashSet<BoxValue<AllTraitVTable>> = HashSet::new();
for rc_ref in buf.iter().take(4) {
assert!(hashset.insert(rc_ref.clone_value()));
}
assert!(!hashset.insert(BoxValue::new(Rc::clone(&vec_rc[4]))));
assert!(!hashset.insert(BoxValue::new(Rc::clone(&vec_rc[5]))));
assert_eq!(hashset.len(), 4);
assert!(hashset.contains(&BoxValue::new(Rc::new(1))));
assert!(hashset.contains(&BoxValue::new(Rc::new(23))));
assert!(hashset.contains(&BoxValue::new(Rc::new(2))));
assert!(hashset.contains(&BoxValue::new(Rc::new(42))));
assert!(!hashset.contains(&BoxValue::new(Rc::new(13534653))));
}
#[test]
fn clone_from_small_test() {
use std::collections::HashSet;
let vec_rc: Vec<_> = vec![1, 23, 2, 42, 23, 1, 13534653]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec_rc.clone());
let mut hashset: HashSet<SmallValue<AllTraitVTable>> = HashSet::new();
for rc_ref in buf.iter().take(4) {
assert!(hashset.insert(rc_ref.clone_small_value()));
}
assert!(!hashset.insert(SmallValue::new(Rc::clone(&vec_rc[4]))));
assert!(!hashset.insert(SmallValue::new(Rc::clone(&vec_rc[5]))));
assert_eq!(hashset.len(), 4);
assert!(hashset.contains(&SmallValue::new(Rc::new(1))));
assert!(hashset.contains(&SmallValue::new(Rc::new(23))));
assert!(hashset.contains(&SmallValue::new(Rc::new(2))));
assert!(hashset.contains(&SmallValue::new(Rc::new(42))));
assert!(!hashset.contains(&SmallValue::new(Rc::new(13534653))));
}
#[test]
fn iter() {
let vec: Vec<_> = vec![1, 23, 2, 42, 11].into_iter().map(Rc::new).collect();
{
let buf = VecDropAll::from(vec.clone());
let orig = Rc::new(100);
let mut rc = Rc::clone(&orig);
assert_eq!(Rc::strong_count(&rc), 2);
for val in buf.iter() {
ValueMut::new(&mut rc).clone_from_other(val).unwrap();
}
assert_eq!(Rc::strong_count(&orig), 1);
assert_eq!(Rc::strong_count(&rc), 3);
assert_eq!(Rc::strong_count(&vec[4]), 3);
assert!(vec.iter().take(4).all(|x| Rc::strong_count(x) == 2));
assert_eq!(rc, Rc::new(11));
}
assert!(vec.iter().all(|x| Rc::strong_count(x) == 1));
}
#[test]
fn initialization_test() {
let a = VecDropAll::with_type::<Rc<u8>>();
assert_eq!(a.len(), 0);
assert_eq!(a.element_type_id(), TypeId::of::<Rc<u8>>());
assert_eq!(a.byte_capacity(), 0);
let b = VecDropAll::with_type_from(&a);
assert_eq!(b.len(), 0);
assert_eq!(b.element_type_id(), TypeId::of::<Rc<u8>>());
assert_eq!(a.byte_capacity(), 0);
let a = VecDropAll::with_capacity::<Rc<u8>>(4);
assert_eq!(a.len(), 0);
assert_eq!(a.byte_capacity(), 4 * size_of::<Rc<u8>>());
assert_eq!(a.element_type_id(), TypeId::of::<Rc<u8>>());
}
#[test]
fn resize() {
let mut a = VecDropAll::with_type::<Rc<u8>>();
a.resize(3, Rc::new(1u8))
.expect("Failed to resize VecDrop up by 3 elements");
assert_eq!(a.len(), 3);
for i in 0..3 {
assert_eq!(a.get_ref_as::<Rc<u8>>(i).unwrap(), &Rc::new(1));
}
a.resize(2, Rc::new(1u8))
.expect("Failed to resize VecDrop down to 2 elements");
assert_eq!(a.len(), 2);
for i in 0..2 {
assert_eq!(a.get_ref_as::<Rc<u8>>(i).unwrap(), &Rc::new(1));
}
}
#[test]
fn data_integrity_u8_test() {
let vec: Vec<Rc<u8>> = vec![1u8, 3, 4, 1, 2].into_iter().map(Rc::new).collect();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<u8>> = buf.clone_into_vec().unwrap();
assert_eq!(vec, nu_vec);
let vec: Vec<Rc<u8>> = vec![1u8, 3, 4, 1, 2, 52, 1, 3, 41, 23, 2]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<u8>> = buf.clone_into_vec().unwrap();
assert_eq!(vec, nu_vec);
}
#[test]
fn data_integrity_i16_test() {
let vec: Vec<Rc<i16>> = vec![1i16, -3, 1002, -231, 32]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<i16>> = buf.clone_into_vec().unwrap();
assert_eq!(vec, nu_vec);
let vec: Vec<Rc<i16>> = vec![1i16, -3, 1002, -231, 32, 42, -123, 4]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<i16>> = buf.clone_into_vec().unwrap();
assert_eq!(vec, nu_vec);
}
#[test]
fn data_integrity_i32_test() {
let vec: Vec<Rc<i32>> = vec![1i32, -3, 1002, -231, 32]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<i32>> = buf.into_vec().unwrap();
assert_eq!(vec, nu_vec);
let vec: Vec<Rc<i32>> = vec![1i32, -3, 1002, -231, 32, 42, -123]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<i32>> = buf.into_vec().unwrap();
assert_eq!(vec, nu_vec);
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
struct Foo {
a: u8,
b: i64,
}
#[test]
fn from_empty_vec_test() {
let vec: Vec<Rc<u32>> = Vec::new();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<u32>> = buf.into_vec().unwrap();
assert_eq!(vec, nu_vec);
let vec: Vec<Rc<String>> = Vec::new();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<String>> = buf.into_vec().unwrap();
assert_eq!(vec, nu_vec);
let vec: Vec<Rc<Foo>> = Vec::new();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<Foo>> = buf.into_vec().unwrap();
assert_eq!(vec, nu_vec);
}
#[test]
fn from_struct_test() {
let f1 = Foo { a: 3, b: -32 };
let f2 = Foo {
a: 33,
b: -3342432412,
};
let vec: Vec<Rc<Foo>> = vec![Rc::new(f1.clone()), Rc::new(f2.clone())];
let buf = VecDropAll::from(vec.clone());
assert_eq!(Rc::new(f1), buf.get_ref_as::<Rc<Foo>>(0).unwrap().clone());
assert_eq!(Rc::new(f2), buf.get_ref_as::<Rc<Foo>>(1).unwrap().clone());
let nu_vec: Vec<Rc<Foo>> = buf.into_vec().unwrap();
assert_eq!(vec, nu_vec);
}
#[test]
fn from_strings_test() {
let vec: Vec<Rc<String>> = vec![
String::from("hi"),
String::from("hello"),
String::from("goodbye"),
String::from("bye"),
String::from("supercalifragilisticexpialidocious"),
String::from("42"),
]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec.clone());
assert_eq!(
&Rc::new("hi".to_string()),
buf.get_ref_as::<Rc<String>>(0).unwrap()
);
assert_eq!(
&Rc::new("hello".to_string()),
buf.get_ref_as::<Rc<String>>(1).unwrap()
);
assert_eq!(
&Rc::new("goodbye".to_string()),
buf.get_ref_as::<Rc<String>>(2).unwrap()
);
let nu_vec: Vec<Rc<String>> = buf.into_vec().unwrap();
assert_eq!(vec, nu_vec);
}
#[test]
fn iter_test() {
let vec_u8: Vec<Rc<u8>> = vec![1u8, 3, 4, 1, 2, 4, 128, 32]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDropAll::from(vec_u8.clone());
for (i, val) in buf.iter_as::<Rc<u8>>().unwrap().enumerate() {
assert_eq!(val, &vec_u8[i]);
}
}
#[test]
fn large_sizes_clone() {
for i in 100000..100010 {
let vec: Vec<Rc<u8>> = vec![32u8; i].into_iter().map(Rc::new).collect();
let buf = VecDropAll::from(vec.clone());
let nu_vec: Vec<Rc<u8>> = buf.into_vec().unwrap();
assert_eq!(vec, nu_vec);
}
}
#[test]
fn wrong_type_test() {
let vec: Vec<Rc<u8>> = vec![1, 23, 2, 42, 11].into_iter().map(Rc::new).collect();
let mut buf = VecDropAll::from(vec.clone());
assert_eq!(vec, buf.clone_into_vec::<Rc<u8>>().unwrap());
assert!(buf.clone_into_vec::<Rc<f64>>().is_none());
assert!(buf.as_slice_as::<Rc<f64>>().is_none());
assert!(buf.iter_as::<Rc<[u8; 3]>>().is_none());
assert!(buf.get_ref_as::<Rc<i32>>(1).is_none());
assert!(buf.get_mut_as::<Rc<i32>>(2).is_none());
}
#[test]
fn push_test() {
let mut vec_u8: Vec<Rc<u8>> = vec![1u8, 23, 2].into_iter().map(Rc::new).collect();
let mut buf = VecDropAll::from(vec_u8.clone());
for (i, val) in buf.iter_as::<Rc<u8>>().unwrap().enumerate() {
assert_eq!(val, &vec_u8[i]);
}
vec_u8.push(Rc::new(42u8));
buf.push_as(Rc::new(42u8)).unwrap();
for (i, val) in buf.iter_as::<Rc<u8>>().unwrap().enumerate() {
assert_eq!(val, &vec_u8[i]);
}
vec_u8.push(Rc::new(11u8));
buf.push_as(Rc::new(11u8)).unwrap();
for (i, val) in buf.iter_as::<Rc<u8>>().unwrap().enumerate() {
assert_eq!(val, &vec_u8[i]);
}
}
#[test]
fn append_test() {
let mut buf = VecDropAll::with_type::<Rc<u8>>();
let data: Vec<Rc<u8>> = vec![1, 23, 2, 42, 11].into_iter().map(Rc::new).collect();
let mut other_buf = VecDropAll::from_vec(data.clone());
buf.append(&mut other_buf);
assert!(other_buf.is_empty());
for (i, val) in buf.iter_as::<Rc<u8>>().unwrap().enumerate() {
assert_eq!(val, &data[i]);
}
}
#[test]
fn dynamic_vtables_assignment() {
use crate::{from_dyn, into_dyn};
let buf = VecDropAll::with_type::<u8>();
let mut buf_dyn = into_dyn![VecDrop<dyn HasAllTrait>](buf);
buf_dyn.push(BoxValue::<AllTraitVTable>::new(1u8));
buf_dyn.push(BoxValue::<AllTraitVTable>::new(100u8));
buf_dyn.push(BoxValue::<AllTraitVTable>::new(23u8));
let buf = from_dyn![VecDrop<dyn HasAllTrait as AllTraitVTable>](buf_dyn);
let vec: Vec<u8> = buf.into_vec().unwrap();
assert_eq!(vec, vec![1u8, 100, 23]);
}
#[test]
fn clone_test() {
let buf = VecDropAll::with_size::<Rc<u8>>(3, Rc::new(1u8));
assert_eq!(&buf, &buf.clone());
}
#[cfg(feature = "numeric")]
#[test]
fn convert_float_test() {
let vecf64 = vec![1f64, -3.0, 10.02, -23.1, 32e-1];
let buf: VecDrop = VecDrop::from(vecf64.clone());
let nu_vec: Vec<f32> = buf.cast_into_vec().unwrap();
let vecf32 = vec![1f32, -3.0, 10.02, -23.1, 32e-1];
assert_eq!(vecf32, nu_vec);
let buf: VecDrop = VecDrop::from(vecf32.clone());
let nu_vec: Vec<f64> = buf.cast_into_vec().unwrap();
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: VecDrop = VecDrop::from(vecf64.clone());
let nu_vec: Vec<f32> = buf.cast_into_vec().unwrap();
let vecf32 = vec![1f32, -3.1, 100.2, -2.31, 3.2, 4e2, -1e23];
assert_eq!(vecf32, nu_vec);
let buf: VecDrop = VecDrop::from(vecf32.clone());
let nu_vec: Vec<f64> = buf.cast_into_vec().unwrap();
for (&a, &b) in vecf64.iter().zip(nu_vec.iter()) {
assert!((a - b).abs() < 1e-6 * f64::max(a, b).abs());
}
}
}