use std::{
cell::Cell,
iter::FusedIterator,
ops::{Bound, Deref, DerefMut, Index, IndexMut},
};
use crate::hooks::Gen;
#[derive(Copy, Clone)]
#[non_exhaustive]
pub struct Tracked<T> {
#[doc(hidden)]
pub __avalanche_internal_value: T,
#[doc(hidden)]
pub __avalanche_internal_updated: bool,
}
impl<T> Tracked<T> {
pub fn new(value: T, updated: bool) -> Self {
Self {
__avalanche_internal_value: value,
__avalanche_internal_updated: updated,
}
}
}
#[macro_export]
macro_rules! tracked {
($e:expr) => {
$e.__avalanche_internal_value
};
}
#[macro_export]
macro_rules! updated {
($e:expr) => {
$e.__avalanche_internal_updated
};
}
pub struct Vec<T> {
pub(crate) data: std::vec::Vec<T>,
pub(crate) gens: std::vec::Vec<Gen>,
pub(crate) curr_gen: Cell<Gen>,
}
pub struct VecMutRef<'a, T> {
vec: &'a mut Vec<T>,
}
impl<'a, T> Deref for VecMutRef<'a, T> {
type Target = ::std::vec::Vec<T>;
fn deref(&self) -> &Self::Target {
&self.vec.data
}
}
impl<'a, T> DerefMut for VecMutRef<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.vec.data
}
}
impl<'a, T> Drop for VecMutRef<'a, T> {
fn drop(&mut self) {
let data_len = self.vec.data.len();
let curr_gen = self.vec.curr_gen.get();
if data_len > self.vec.gens.len() {
self.vec.gens.fill(curr_gen);
self.vec.gens.resize(data_len, curr_gen);
} else {
self.vec.gens.resize(data_len, curr_gen);
self.vec.gens.fill(curr_gen);
}
}
}
impl<T> Vec<T> {
pub(crate) fn new(data: std::vec::Vec<T>, gen: Gen) -> Self {
Self {
gens: vec![gen.next(); data.len()],
data,
curr_gen: Cell::new(gen),
}
}
pub fn as_raw_vec(&mut self) -> VecMutRef<T> {
VecMutRef { vec: self }
}
pub fn iter<'a>(
&'a self,
) -> impl Iterator<Item = Tracked<&T>> + DoubleEndedIterator + FusedIterator + ExactSizeIterator + 'a
{
self.data
.iter()
.zip(self.gens.iter())
.map(move |(val, gen)| Tracked {
__avalanche_internal_value: val,
__avalanche_internal_updated: gen.updated(self.curr_gen.get()),
})
}
pub fn windows<'a>(
&'a self,
size: usize,
) -> impl Iterator<Item = Tracked<&[T]>> + DoubleEndedIterator + FusedIterator + ExactSizeIterator + 'a
{
self.data
.windows(size)
.zip(self.gens.windows(size))
.map(move |(val, gen)| Tracked {
__avalanche_internal_value: val,
__avalanche_internal_updated: gen
.iter()
.any(|&val| val.updated(self.curr_gen.get())),
})
}
pub fn chunks<'a>(
&'a self,
chunk_size: usize,
) -> impl Iterator<Item = Tracked<&[T]>> + DoubleEndedIterator + FusedIterator + ExactSizeIterator + 'a
{
self.data
.chunks(chunk_size)
.zip(self.gens.chunks(chunk_size))
.map(move |(val, gen)| Tracked {
__avalanche_internal_value: val,
__avalanche_internal_updated: gen
.iter()
.any(|&val| val.updated(self.curr_gen.get())),
})
}
pub fn chunks_exact<'a>(
&'a self,
chunk_size: usize,
) -> impl Iterator<Item = Tracked<&[T]>> + DoubleEndedIterator + FusedIterator + ExactSizeIterator + 'a
{
self.data
.chunks_exact(chunk_size)
.zip(self.gens.chunks_exact(chunk_size))
.map(move |(val, gen)| Tracked {
__avalanche_internal_value: val,
__avalanche_internal_updated: gen
.iter()
.any(|&val| val.updated(self.curr_gen.get())),
})
}
pub fn rchunks<'a>(
&'a self,
chunk_size: usize,
) -> impl Iterator<Item = Tracked<&[T]>> + DoubleEndedIterator + FusedIterator + ExactSizeIterator + 'a
{
self.data
.rchunks(chunk_size)
.zip(self.gens.rchunks(chunk_size))
.map(move |(val, gen)| Tracked {
__avalanche_internal_value: val,
__avalanche_internal_updated: gen
.iter()
.any(|&val| val.updated(self.curr_gen.get())),
})
}
pub fn rchunks_exact<'a>(
&'a self,
chunk_size: usize,
) -> impl Iterator<Item = Tracked<&[T]>> + DoubleEndedIterator + FusedIterator + ExactSizeIterator + 'a
{
self.data
.rchunks_exact(chunk_size)
.zip(self.gens.rchunks_exact(chunk_size))
.map(move |(val, gen)| Tracked {
__avalanche_internal_value: val,
__avalanche_internal_updated: gen
.iter()
.any(|&val| val.updated(self.curr_gen.get())),
})
}
pub fn push(&mut self, value: T) {
self.data.push(value);
self.gens.push(self.curr_gen.get().next());
}
pub fn pop(&mut self) -> Option<T> {
let _ = self.gens.pop();
self.data.pop()
}
pub fn insert(&mut self, index: usize, element: T) {
self.data.insert(index, element);
self.gens.insert(index, self.curr_gen.get().next());
}
pub fn remove(&mut self, index: usize) -> T {
self.gens.remove(index);
self.data.remove(index)
}
pub fn swap_remove(&mut self, index: usize) -> T {
self.gens.swap_remove(index);
self.data.swap_remove(index)
}
pub fn clear(&mut self) {
self.data.clear();
self.gens.clear();
}
pub fn retain<F: FnMut(&T) -> bool>(&mut self, mut f: F) {
let mut gens_idx = 0;
let gens_mut = &mut self.gens;
self.data.retain(|val| {
let retain = f(val);
if !retain {
gens_mut[gens_idx] = Gen { gen: 0 };
}
gens_idx += 1;
retain
});
self.gens.retain(|&gen| gen != Gen { gen: 0 });
}
pub fn reserve(&mut self, additional: usize) {
self.data.reserve(additional);
self.gens.reserve(additional);
}
pub fn reserve_exact(&mut self, additional: usize) {
self.data.reserve_exact(additional);
self.gens.reserve_exact(additional);
}
pub fn shrink_to_fit(&mut self) {
self.data.shrink_to_fit();
self.gens.shrink_to_fit();
}
}
impl<T> IntoIterator for Vec<T> {
type Item = Tracked<T>;
type IntoIter = std::vec::IntoIter<Tracked<T>>;
#[allow(clippy::needless_collect)]
fn into_iter(self) -> Self::IntoIter {
let curr_gen = self.curr_gen.get();
let data: std::vec::Vec<_> = self
.data
.into_iter()
.zip(self.gens.into_iter())
.map(move |(val, gen)| Tracked {
__avalanche_internal_value: val,
__avalanche_internal_updated: gen.updated(curr_gen),
})
.collect();
data.into_iter()
}
}
impl<T> Deref for Vec<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&*self.data
}
}
impl<T, Idx: TrackedVecIndex<T>> Index<Idx> for Vec<T> {
type Output = Idx::Output;
fn index(&self, index: Idx) -> &Self::Output {
index.get(self)
}
}
impl<T, Idx: TrackedVecIndex<T>> IndexMut<Idx> for Vec<T> {
fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
self.gens[index.span()].fill(self.curr_gen.get().next());
index.get_mut(self)
}
}
mod private {
pub trait Sealed {}
impl Sealed for usize {}
}
pub trait TrackedVecIndex<T>: private::Sealed + Copy {
type Output: ?Sized;
fn get(self, vec: &Vec<T>) -> &Self::Output;
fn get_mut(self, vec: &mut Vec<T>) -> &mut Self::Output;
fn span(self) -> (Bound<usize>, Bound<usize>);
}
impl<T> TrackedVecIndex<T> for usize {
type Output = T;
fn get(self, vec: &Vec<T>) -> &Self::Output {
&vec.data[self]
}
fn get_mut(self, vec: &mut Vec<T>) -> &mut Self::Output {
&mut vec.data[self]
}
fn span(self) -> (Bound<usize>, Bound<usize>) {
(Bound::Included(self), Bound::Included(self))
}
}