#![allow(dead_code)]
use std::{
any::{Any, TypeId},
fmt,
mem::ManuallyDrop,
slice,
sync::Arc,
};
use crate::traits::*;
use crate::value::*;
use crate::VecCopy;
pub trait Elem: Any + DropBytes {}
impl<T> Elem for T where T: Any + DropBytes {}
pub struct VecDyn<V> {
data: ManuallyDrop<VecCopy>,
vtable: Arc<(DropFn, V)>,
}
impl<V> Drop for VecDyn<V> {
fn drop(&mut self) {
unsafe {
for elem_bytes in self.data.byte_chunks_mut() {
self.vtable.drop_fn().0(elem_bytes);
}
}
}
}
impl<V: HasClone> Clone for VecDyn<V> {
fn clone(&self) -> Self {
let data_clone = |bytes: &[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.vtable.1.clone_from_fn()(dst, src) });
new_data
};
VecDyn {
data: ManuallyDrop::new(self.data.clone_with(data_clone)),
vtable: Arc::clone(&self.vtable),
}
}
}
impl<V: HasPartialEq> PartialEq for VecDyn<V> {
fn eq(&self, other: &Self) -> bool {
self.iter()
.zip(other.iter())
.all(|(this, that)| this == that)
}
}
impl<V: HasEq> Eq for VecDyn<V> {}
impl<V: HasHash> std::hash::Hash for VecDyn<V> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.iter().for_each(|elem| elem.hash(state));
}
}
impl<V: HasDebug> fmt::Debug for VecDyn<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<V> VecDyn<V> {
pub fn vtable(&self) -> &V {
&self.vtable.1
}
#[inline]
pub fn with_type<T: Elem>() -> Self
where
V: VTable<T>,
{
VecDyn {
data: ManuallyDrop::new(unsafe { VecCopy::with_type_non_copy::<T>() }),
vtable: Arc::new((DropFn(T::drop_bytes), V::build_vtable())),
}
}
#[inline]
pub fn with_type_from(other: &VecDyn<V>) -> Self {
VecDyn {
data: ManuallyDrop::new(VecCopy::with_type_from(&other.data)),
vtable: Arc::clone(&other.vtable),
}
}
#[inline]
pub fn with_capacity<T: Elem>(n: usize) -> Self
where
V: VTable<T>,
{
VecDyn {
data: ManuallyDrop::new(unsafe { VecCopy::with_capacity_non_copy::<T>(n) }),
vtable: Arc::new((DropFn(T::drop_bytes), V::build_vtable())),
}
}
pub fn from_vec<T: Elem>(vec: Vec<T>) -> Self
where
V: VTable<T>,
{
VecDyn {
data: ManuallyDrop::new(unsafe { VecCopy::from_vec_non_copy(vec) }),
vtable: Arc::new((DropFn(T::drop_bytes), V::build_vtable())),
}
}
#[inline]
pub fn clear(&mut self) {
unsafe {
for bytes in self.data.byte_chunks_mut() {
self.vtable.drop_fn().0(bytes);
}
}
self.data.data.clear();
}
#[inline]
pub fn push<T: Elem>(&mut self, element: T) -> Option<&mut Self> {
if self.data.push(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::<T>()
}
#[inline]
pub fn iter_mut_as<T: Elem>(&mut self) -> Option<slice::IterMut<T>> {
self.data.iter_mut::<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<T: Elem>(&self) -> Option<&[T]> {
self.data.as_slice()
}
#[inline]
pub fn as_mut_slice<T: Elem>(&mut self) -> Option<&mut [T]> {
self.data.as_mut_slice()
}
#[inline]
pub fn get_ref_as<T: Elem>(&self, i: usize) -> Option<&T> {
self.data.get_ref::<T>(i)
}
#[inline]
pub fn get_mut_as<T: Elem>(&mut self, i: usize) -> Option<&mut T> {
self.data.get_mut::<T>(i)
}
#[inline]
pub fn append(&mut self, buf: &mut VecDyn<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_value(&mut self, value: BoxValue<V>) -> Option<&mut Self> {
if self.element_type_id() == value.value_type_id() {
let value = ManuallyDrop::new(value);
self.data.data.extend_from_slice(&value.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(), 0u8);
unsafe {
self.vtable.1.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.vtable)
}
}
#[inline]
pub fn iter<'a>(&'a self) -> impl Iterator<Item = ValueRef<'a, V>> + 'a {
let &Self {
ref data,
ref vtable,
} = self;
let VecCopy {
data,
element_size,
element_type_id,
} = &**data;
data.chunks_exact(*element_size)
.map(move |bytes| unsafe { ValueRef::from_raw_parts(bytes, *element_type_id, vtable) })
}
#[inline]
pub fn get_mut(&mut self, i: usize) -> ValueMut<V> {
debug_assert!(i < self.len());
let Self { data, vtable } = self;
let type_id = data.element_type_id();
unsafe { ValueMut::from_raw_parts(data.get_bytes_mut(i), type_id, vtable) }
}
#[inline]
pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = ValueMut<'a, V>> + 'a {
let &mut Self {
ref mut data,
ref vtable,
} = self;
let VecCopy {
data,
element_size,
element_type_id,
} = &mut **data;
data.chunks_exact_mut(*element_size)
.map(move |bytes| unsafe { ValueMut::from_raw_parts(bytes, *element_type_id, vtable) })
}
}
impl<V: HasClone> VecDyn<V> {
#[inline]
pub fn with_size<T: Elem + Clone>(n: usize, def: T) -> Self
where
V: VTable<T>,
{
VecDyn {
data: ManuallyDrop::new(unsafe { VecCopy::from_vec_non_copy(vec![def; n]) }),
vtable: Arc::new((DropFn(T::drop_bytes), V::build_vtable())),
}
}
#[inline]
pub fn from_slice<T: Elem + Clone>(slice: &[T]) -> Self
where
V: VTable<T>,
{
VecDyn {
data: ManuallyDrop::new(unsafe { VecCopy::from_slice_non_copy::<T>(slice) }),
vtable: Arc::new((DropFn(T::drop_bytes), V::build_vtable())),
}
}
#[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(value.clone());
}
} else {
unsafe {
for bytes in self.data.byte_chunks_mut().skip(new_len) {
self.vtable.drop_fn().0(bytes);
}
}
self.data.data.resize(new_len * size_t, 0);
}
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()?;
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<T: Elem, V: VTable<T>> From<Vec<T>> for VecDyn<V> {
#[inline]
fn from(vec: Vec<T>) -> VecDyn<V> {
VecDyn::from_vec(vec)
}
}
impl<'a, T, V> From<&'a [T]> for VecDyn<V>
where
T: Elem + Clone,
V: VTable<T> + HasClone,
{
#[inline]
fn from(slice: &'a [T]) -> VecDyn<V> {
VecDyn::from_slice(slice)
}
}
impl<T: Elem, V: VTable<T>> Into<Option<Vec<T>>> for VecDyn<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(suffix = "VTable", 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 VecDynAll = VecDyn<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_dyn(n: usize) -> VecDynAll {
let mut rng: StdRng = SeedableRng::from_seed([3; 32]);
let between = rand::distributions::Uniform::from(1i64..5);
let vec: Vec<_> = (0..n).map(move |_| [between.sample(&mut rng); 3]).collect();
vec.into()
}
#[inline]
fn vec_dyn_compute<V>(v: &mut VecDyn<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];
}
}
#[test]
fn downcast_value_mut() {
let mut v: VecDynAll = make_random_vec_dyn(9_000);
vec_dyn_compute(&mut v);
}
#[test]
fn clone_from_test() {
use std::collections::HashSet;
use std::rc::Rc;
let vec_rc: Vec<_> = vec![1, 23, 2, 42, 23, 1, 13534653]
.into_iter()
.map(Rc::new)
.collect();
let buf = VecDynAll::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(Value::new(Rc::clone(&vec_rc[4]))));
assert!(!hashset.insert(Value::new(Rc::clone(&vec_rc[5]))));
assert_eq!(hashset.len(), 4);
assert!(hashset.contains(&Value::new(Rc::new(1))));
assert!(hashset.contains(&Value::new(Rc::new(23))));
assert!(hashset.contains(&Value::new(Rc::new(2))));
assert!(hashset.contains(&Value::new(Rc::new(42))));
assert!(!hashset.contains(&Value::new(Rc::new(13534653))));
}
#[test]
fn iter() {
use std::rc::Rc;
let vec: Vec<_> = vec![1, 23, 2, 42, 11].into_iter().map(Rc::new).collect();
{
let buf = VecDynAll::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(val);
}
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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::with_type::<Rc<u8>>();
a.resize(3, Rc::new(1u8))
.expect("Failed to resize VecDyn 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 VecDyn 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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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 = VecDynAll::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::<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 = VecDynAll::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(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(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 = VecDynAll::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 = VecDynAll::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]);
}
}
}