use std::{
cmp::Ordering,
marker::PhantomData,
mem::take,
ops::{Deref, DerefMut, Index, IndexMut},
};
use rand::{RngCore, thread_rng};
use crate::{
DBData, declare_trait_object,
dynamic::DataTraitTyped,
utils::{
dyn_advance, dyn_retreat, stable_sort, stable_sort_by, {self},
},
};
use super::{Data, DataTrait, DowncastTrait, Erase, LeanVec, RawIter};
pub trait Vector<T: DataTrait + ?Sized>: Data {
fn len(&self) -> usize;
fn capacity(&self) -> usize;
fn spare_capacity(&self) -> usize {
self.capacity() - self.len()
}
fn has_spare_capacity(&self) -> bool {
self.spare_capacity() > 0
}
fn is_empty(&self) -> bool {
self.len() == 0
}
fn clear(&mut self);
fn shrink_to_fit(&mut self);
fn push_val(&mut self, val: &mut T);
fn push_ref(&mut self, val: &T);
fn push_with(&mut self, f: &mut dyn FnMut(&mut T));
fn index(&self, index: usize) -> &T;
fn first(&self) -> Option<&T> {
if self.is_empty() {
None
} else {
Some(self.index(0))
}
}
fn first_mut(&mut self) -> Option<&mut T> {
if self.is_empty() {
None
} else {
Some(self.index_mut(0))
}
}
fn last(&self) -> Option<&T> {
if self.is_empty() {
None
} else {
Some(self.index(self.len() - 1))
}
}
fn last_mut(&mut self) -> Option<&mut T> {
if self.is_empty() {
None
} else {
Some(self.index_mut(self.len() - 1))
}
}
unsafe fn index_unchecked(&self, index: usize) -> &T;
fn index_mut(&mut self, index: usize) -> &mut T;
unsafe fn index_mut_unchecked(&mut self, index: usize) -> &mut T;
fn swap(&mut self, a: usize, b: usize);
fn reserve(&mut self, additional: usize);
fn reserve_exact(&mut self, additional: usize);
fn extend_from_range(&mut self, other: &DynVec<T>, from: usize, to: usize);
fn extend(&mut self, other: &DynVec<T>);
fn append(&mut self, other: &mut DynVec<T>);
fn append_range(&mut self, other: &mut DynVec<T>, from: usize, to: usize);
fn advance_while(&self, from: usize, to: usize, predicate: &dyn Fn(&T) -> bool) -> usize;
fn advance_until(&self, from: usize, to: usize, predicate: &dyn Fn(&T) -> bool) -> usize;
fn advance_to(&self, from: usize, to: usize, val: &T) -> usize;
fn retreat_while(&self, from: usize, to: usize, predicate: &dyn Fn(&T) -> bool) -> usize;
fn retreat_until(&self, from: usize, to: usize, predicate: &dyn Fn(&T) -> bool) -> usize;
fn retreat_to(&self, from: usize, to: usize, val: &T) -> usize;
unsafe fn set_len(&mut self, len: usize);
fn truncate(&mut self, len: usize);
fn sort(&mut self) {
self.sort_slice(0, self.len());
}
fn sort_slice(&mut self, from: usize, to: usize);
fn sort_unstable(&mut self) {
self.sort_slice_unstable(0, self.len())
}
fn sort_slice_unstable(&mut self, from: usize, to: usize);
fn sort_slice_by(&mut self, from: usize, to: usize, cmp: &dyn Fn(&T, &T) -> Ordering);
fn sort_unstable_by(&mut self, cmp: &dyn Fn(&T, &T) -> Ordering) {
self.sort_slice_unstable_by(0, self.len(), cmp)
}
fn sort_slice_unstable_by(&mut self, from: usize, to: usize, cmp: &dyn Fn(&T, &T) -> Ordering);
fn is_sorted_by(&self, compare: &dyn Fn(&T, &T) -> Ordering) -> bool;
fn dedup(&mut self);
fn dyn_iter<'a>(&'a self) -> Box<dyn DoubleEndedIterator<Item = &'a T> + 'a>;
fn dyn_iter_mut<'a>(&'a mut self) -> Box<dyn DoubleEndedIterator<Item = &'a mut T> + 'a>;
fn sample_slice(
&self,
from: usize,
to: usize,
rng: &mut dyn RngCore,
sample_size: usize,
callback: &mut dyn FnMut(&T),
);
fn as_vec(&self) -> &DynVec<T>;
fn as_vec_mut(&mut self) -> &mut DynVec<T>;
}
pub trait VecTrait<T: DataTrait + ?Sized>: Vector<T> + DataTrait {}
impl<V, T: DataTrait + ?Sized> VecTrait<T> for V where V: Vector<T> + DataTrait {}
declare_trait_object!(DynVec<T> = dyn Vector<T>
where
T: DataTrait + ?Sized
);
const APPROXIMATE_BYTE_SIZE_SAMPLE_SIZE: usize = 100;
impl<T: DataTrait + ?Sized> DynVec<T> {
pub fn approximate_byte_size(&self) -> usize {
if self.len() <= APPROXIMATE_BYTE_SIZE_SAMPLE_SIZE {
return self.size_of().total_bytes();
}
let mut acc = 0;
self.sample_slice(
0,
self.len(),
&mut thread_rng(),
APPROXIMATE_BYTE_SIZE_SAMPLE_SIZE,
&mut |x| acc += x.size_of().total_bytes(),
);
let average = (acc as f64) / (APPROXIMATE_BYTE_SIZE_SAMPLE_SIZE as f64);
(average * self.len() as f64).round() as usize
}
}
impl<T: DataTraitTyped + ?Sized> Deref for DynVec<T> {
type Target = LeanVec<T::Type>;
fn deref(&self) -> &Self::Target {
unsafe { self.downcast::<Self::Target>() }
}
}
impl<T: DataTraitTyped + ?Sized> DerefMut for DynVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.downcast_mut::<Self::Target>() }
}
}
impl<T: DataTrait + ?Sized> Index<usize> for DynVec<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
Vector::index(self, index)
}
}
impl<T: DataTrait + ?Sized> IndexMut<usize> for DynVec<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
Vector::index_mut(self, index)
}
}
impl<T, Trait> Vector<Trait> for LeanVec<T>
where
Trait: DataTrait + ?Sized,
T: DBData + Erase<Trait>,
{
fn len(&self) -> usize {
LeanVec::len(self)
}
fn capacity(&self) -> usize {
LeanVec::capacity(self)
}
fn clear(&mut self) {
LeanVec::clear(self)
}
fn shrink_to_fit(&mut self) {
self.vec.shrink_to_fit()
}
fn push_val(&mut self, val: &mut Trait) {
let val = take(unsafe { val.downcast_mut::<T>() });
LeanVec::push(self, val);
}
fn push_ref(&mut self, val: &Trait) {
let val = unsafe { val.downcast::<T>() }.clone();
LeanVec::push(self, val);
}
fn push_with(&mut self, f: &mut dyn FnMut(&mut Trait)) {
let mut val: T = Default::default();
f(val.erase_mut());
LeanVec::push(self, val);
}
fn index(&self, index: usize) -> &Trait {
LeanVec::get(self, index).erase()
}
fn index_mut(&mut self, index: usize) -> &mut Trait {
LeanVec::get_mut(self, index).erase_mut()
}
unsafe fn index_unchecked(&self, index: usize) -> &Trait {
unsafe { LeanVec::get_unchecked(self, index).erase() }
}
unsafe fn index_mut_unchecked(&mut self, index: usize) -> &mut Trait {
unsafe { LeanVec::get_mut_unchecked(self, index).erase_mut() }
}
fn swap(&mut self, a: usize, b: usize) {
self.as_mut_slice().swap(a, b)
}
fn reserve(&mut self, reservation: usize) {
LeanVec::reserve(self, reservation)
}
fn reserve_exact(&mut self, reservation: usize) {
LeanVec::reserve_exact(self, reservation)
}
fn extend_from_range(&mut self, other: &DynVec<Trait>, from: usize, to: usize) {
let other = unsafe { other.downcast::<Self>() };
LeanVec::extend_from_slice(self, &other[from..to])
}
fn extend(&mut self, other: &DynVec<Trait>) {
let other = unsafe { other.downcast::<Self>() };
LeanVec::extend_from_slice(self, &other[..])
}
fn append(&mut self, other: &mut DynVec<Trait>) {
let other = unsafe { other.downcast_mut::<Self>() };
LeanVec::append(self, other);
}
fn append_range(&mut self, other: &mut DynVec<Trait>, from: usize, to: usize) {
let other = unsafe { other.downcast_mut::<Self>() };
LeanVec::append_from_slice(self, &mut other[from..to])
}
fn advance_while(&self, from: usize, to: usize, predicate: &dyn Fn(&Trait) -> bool) -> usize {
dyn_advance(&self[from..to], &|val| {
predicate(unsafe { &*(val as *const T) }.erase())
})
}
fn advance_until(&self, from: usize, to: usize, predicate: &dyn Fn(&Trait) -> bool) -> usize {
dyn_advance(&self[from..to], &|val| {
!predicate(unsafe { &*(val as *const T) }.erase())
})
}
fn advance_to(&self, from: usize, to: usize, val: &Trait) -> usize {
let val = unsafe { val.downcast::<T>() };
dyn_advance(&self[from..to], &|x| unsafe { &*(x as *const T) } < val)
}
fn retreat_while(&self, from: usize, to: usize, predicate: &dyn Fn(&Trait) -> bool) -> usize {
dyn_retreat(&self[from..=to], &|val| {
predicate(unsafe { &*(val as *const T) }.erase())
})
}
fn retreat_until(&self, from: usize, to: usize, predicate: &dyn Fn(&Trait) -> bool) -> usize {
dyn_retreat(&self[from..=to], &|val| {
!predicate(unsafe { &*(val as *const T) }.erase())
})
}
fn retreat_to(&self, from: usize, to: usize, val: &Trait) -> usize {
let val = unsafe { val.downcast::<T>() };
dyn_retreat(&self[from..=to], &|x| unsafe { &*(x as *const T) } > val)
}
unsafe fn set_len(&mut self, len: usize) {
unsafe { LeanVec::set_len(self, len) }
}
fn truncate(&mut self, len: usize) {
LeanVec::truncate(self, len)
}
fn sort_slice(&mut self, from: usize, to: usize) {
stable_sort(&mut self[from..to]);
}
fn sort_slice_by(&mut self, from: usize, to: usize, cmp: &dyn Fn(&Trait, &Trait) -> Ordering) {
stable_sort_by(&mut self[from..to], |x, y| cmp(x.erase(), y.erase()))
}
fn sort_slice_unstable(&mut self, from: usize, to: usize) {
stable_sort(&mut self[from..to]);
}
fn sort_slice_unstable_by(
&mut self,
from: usize,
to: usize,
cmp: &dyn Fn(&Trait, &Trait) -> Ordering,
) {
stable_sort_by(&mut self[from..to], |x, y| cmp(x.erase(), y.erase()))
}
fn dedup(&mut self) {
LeanVec::dedup(self);
}
fn dyn_iter<'a>(&'a self) -> Box<dyn DoubleEndedIterator<Item = &'a Trait> + 'a> {
Box::new(VecIter::new(self))
}
fn dyn_iter_mut<'a>(&'a mut self) -> Box<dyn DoubleEndedIterator<Item = &'a mut Trait> + 'a> {
Box::new(VecIterMut::new(self))
}
fn sample_slice(
&self,
from: usize,
to: usize,
rng: &mut dyn RngCore,
sample_size: usize,
callback: &mut dyn FnMut(&Trait),
) {
utils::sample_slice(&self[from..to], rng, sample_size, &mut |x: &T| {
callback(x.erase())
});
}
fn as_vec(&self) -> &DynVec<Trait> {
self
}
fn as_vec_mut(&mut self) -> &mut DynVec<Trait> {
self
}
fn is_sorted_by(&self, compare: &dyn Fn(&Trait, &Trait) -> Ordering) -> bool {
LeanVec::is_sorted_by(self, |x, y| compare(x.erase(), y.erase()))
}
}
struct VecIter<'a, T, Trait: ?Sized> {
iter: RawIter<'a>,
phantom: PhantomData<(&'a T, &'a Trait)>,
}
impl<'a, T, Trait: ?Sized> VecIter<'a, T, Trait> {
fn new(vec: &'a LeanVec<T>) -> Self {
Self {
iter: vec.raw_iter(),
phantom: PhantomData,
}
}
}
impl<'a, T, Trait: DataTrait + ?Sized> Iterator for VecIter<'a, T, Trait>
where
T: Erase<Trait>,
{
type Item = &'a Trait;
fn next(&mut self) -> Option<&'a Trait> {
self.iter
.next()
.map(|x| unsafe { &*(x as *const T) }.erase())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn count(self) -> usize
where
Self: Sized,
{
self.iter.count()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter
.nth(n)
.map(|x| unsafe { &*(x as *const T) }.erase())
}
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
self.iter
.last()
.map(|x| unsafe { &*(x as *const T) }.erase())
}
}
impl<'a, T, Trait: DataTrait + ?Sized> DoubleEndedIterator for VecIter<'a, T, Trait>
where
T: Erase<Trait>,
{
fn next_back(&mut self) -> Option<&'a Trait> {
self.iter
.next_back()
.map(|x| unsafe { &*(x as *const T) }.erase())
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.iter
.nth_back(n)
.map(|x| unsafe { &*(x as *const T) }.erase())
}
}
struct VecIterMut<'a, T, Trait: ?Sized> {
iter: RawIter<'a>,
phantom: PhantomData<(&'a mut T, &'a Trait)>,
}
impl<'a, T, Trait: ?Sized> VecIterMut<'a, T, Trait> {
fn new(vec: &'a mut LeanVec<T>) -> Self {
Self {
iter: vec.raw_iter(),
phantom: PhantomData,
}
}
}
impl<'a, T, Trait: DataTrait + ?Sized> Iterator for VecIterMut<'a, T, Trait>
where
T: Erase<Trait>,
{
type Item = &'a mut Trait;
fn next(&mut self) -> Option<&'a mut Trait> {
self.iter
.next()
.map(|x| unsafe { &mut *(x as *mut T) }.erase_mut())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn count(self) -> usize
where
Self: Sized,
{
self.iter.count()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter
.nth(n)
.map(|x| unsafe { &mut *(x as *mut T) }.erase_mut())
}
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
self.iter
.last()
.map(|x| unsafe { &mut *(x as *mut T) }.erase_mut())
}
}
impl<'a, T, Trait: DataTrait + ?Sized> DoubleEndedIterator for VecIterMut<'a, T, Trait>
where
T: Erase<Trait>,
{
fn next_back(&mut self) -> Option<&'a mut Trait> {
self.iter
.next_back()
.map(|x| unsafe { &mut *(x as *mut T) }.erase_mut())
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.iter
.nth_back(n)
.map(|x| unsafe { &mut *(x as *mut T) }.erase_mut())
}
}
#[cfg(test)]
mod test {
use crate::{
dynamic::{DowncastTrait, DynData, DynVec, LeanVec, WithFactory},
lean_vec,
};
#[test]
fn dyn_vec_test() {
let factory = <DynVec<DynData> as WithFactory<LeanVec<String>>>::FACTORY;
let mut vec = factory.default_box();
vec.push_val(&mut "foo".to_string());
vec.push_ref(&"bar".to_string());
let contents = vec
.dyn_iter()
.map(|x| x.downcast_checked::<String>().clone())
.collect::<Vec<String>>();
assert_eq!(
LeanVec::from(contents),
lean_vec!["foo".to_string(), "bar".to_string()]
);
}
}