use crate::rt::CopyValue; use crate::signal::{ReadOnlySignal, Signal, Write}; use crate::SignalData; use generational_box::Mappable; use generational_box::{MappableMut, Storage}; use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard}; use std::{ fmt::{Debug, Display}, ops::{Add, Div, Mul, Sub}, }; macro_rules! read_impls { ($ty:ident) => { impl> Default for $ty { fn default() -> Self { Self::new(Default::default()) } } impl> std::clone::Clone for $ty { fn clone(&self) -> Self { *self } } impl + Copy> Copy for $ty {} impl> Display for $ty { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.with(|v| Display::fmt(v, f)) } } impl> Debug for $ty { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.with(|v| Debug::fmt(v, f)) } } impl> $ty, S> { /// Read a value from the inner vector. pub fn get(&self, index: usize) -> Option> { MappedRwLockReadGuard::try_map(self.read(), |v| v.get(index)).ok() } } impl> $ty, S> { /// Unwraps the inner value and clones it. pub fn unwrap(&self) -> T where T: Clone, { self.with(|v| v.clone()).unwrap() } /// Attemps to read the inner value of the Option. pub fn as_ref(&self) -> Option> { MappedRwLockReadGuard::try_map(self.read(), |v| v.as_ref()).ok() } } }; } macro_rules! write_impls { ($ty:ident) => { impl + Copy + 'static, S: Storage> std::ops::Add for $ty { type Output = T; fn add(self, rhs: T) -> Self::Output { self.with(|v| *v + rhs) } } impl + Copy + 'static, S: Storage> std::ops::AddAssign for $ty { fn add_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v + rhs) } } impl + Copy + 'static, S: Storage> std::ops::SubAssign for $ty { fn sub_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v - rhs) } } impl + Copy + 'static, S: Storage> std::ops::Sub for $ty { type Output = T; fn sub(self, rhs: T) -> Self::Output { self.with(|v| *v - rhs) } } impl + Copy + 'static, S: Storage> std::ops::MulAssign for $ty { fn mul_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v * rhs) } } impl + Copy + 'static, S: Storage> std::ops::Mul for $ty { type Output = T; fn mul(self, rhs: T) -> Self::Output { self.with(|v| *v * rhs) } } impl + Copy + 'static, S: Storage> std::ops::DivAssign for $ty { fn div_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v / rhs) } } impl + Copy + 'static, S: Storage> std::ops::Div for $ty { type Output = T; fn div(self, rhs: T) -> Self::Output { self.with(|v| *v / rhs) } } impl> $ty, S> { /// Pushes a new value to the end of the vector. pub fn push(&self, value: T) { self.with_mut(|v| v.push(value)) } /// Pops the last value from the vector. pub fn pop(&self) -> Option { self.with_mut(|v| v.pop()) } /// Inserts a new value at the given index. pub fn insert(&self, index: usize, value: T) { self.with_mut(|v| v.insert(index, value)) } /// Removes the value at the given index. pub fn remove(&self, index: usize) -> T { self.with_mut(|v| v.remove(index)) } /// Clears the vector, removing all values. pub fn clear(&self) { self.with_mut(|v| v.clear()) } /// Extends the vector with the given iterator. pub fn extend(&self, iter: impl IntoIterator) { self.with_mut(|v| v.extend(iter)) } /// Truncates the vector to the given length. pub fn truncate(&self, len: usize) { self.with_mut(|v| v.truncate(len)) } /// Swaps two values in the vector. pub fn swap_remove(&self, index: usize) -> T { self.with_mut(|v| v.swap_remove(index)) } /// Retains only the values that match the given predicate. pub fn retain(&self, f: impl FnMut(&T) -> bool) { self.with_mut(|v| v.retain(f)) } /// Splits the vector into two at the given index. pub fn split_off(&self, at: usize) -> Vec { self.with_mut(|v| v.split_off(at)) } } impl> $ty, S> { /// Takes the value out of the Option. pub fn take(&self) -> Option { self.with_mut(|v| v.take()) } /// Replace the value in the Option. pub fn replace(&self, value: T) -> Option { self.with_mut(|v| v.replace(value)) } /// Gets the value out of the Option, or inserts the given value if the Option is empty. pub fn get_or_insert(&self, default: T) -> S::Ref { self.get_or_insert_with(|| default) } /// Gets the value out of the Option, or inserts the value returned by the given function if the Option is empty. pub fn get_or_insert_with( &self, default: impl FnOnce() -> T, ) -> >::Mapped { let borrow = self.read(); if borrow.is_none() { drop(borrow); self.with_mut(|v| *v = Some(default())); S::Ref::map(self.read(), |v| v.as_ref().unwrap()) } else { S::Ref::map(borrow, |v| v.as_ref().unwrap()) } } } }; } read_impls!(CopyValue); write_impls!(CopyValue); read_impls!(Signal); write_impls!(Signal); read_impls!(ReadOnlySignal); /// An iterator over the values of a `CopyValue>`. pub struct CopyValueIterator> { index: usize, value: CopyValue, S>, } impl> Iterator for CopyValueIterator { type Item = T; fn next(&mut self) -> Option { let index = self.index; self.index += 1; self.value.get(index).map(|v| v.clone()) } } impl> IntoIterator for CopyValue, S> { type IntoIter = CopyValueIterator; type Item = T; fn into_iter(self) -> Self::IntoIter { CopyValueIterator { index: 0, value: self, } } } impl>> CopyValue, S> { /// Write to an element in the inner vector. pub fn get_mut(&self, index: usize) -> Option<>>::Mapped> { S::Mut::try_map(self.write(), |v: &mut Vec| v.get_mut(index)) } } impl>> CopyValue, S> { /// Deref the inner value mutably. pub fn as_mut( &self, ) -> Option<<>>::Mut as MappableMut>>::Mapped> { S::Mut::try_map(self.write(), |v: &mut Option| v.as_mut()) } } /// An iterator over items in a `Signal>`. pub struct SignalIterator> { index: usize, value: Signal, S>, } impl> Iterator for SignalIterator { type Item = T; fn next(&mut self) -> Option { let index = self.index; self.index += 1; self.value.get(index).map(|v| v.clone()) } } impl> IntoIterator for Signal, S> { type IntoIter = SignalIterator; type Item = T; fn into_iter(self) -> Self::IntoIter { SignalIterator { index: 0, value: self, } } } impl>>> Signal, S> where <>>>::Mut as MappableMut< SignalData>, >>::Mapped>: MappableMut>, { /// Returns a reference to an element or `None` if out of bounds. pub fn get_mut( &self, index: usize, ) -> Option< Write< T, <<>>>::Mut as MappableMut>>>::Mapped< Vec, > as MappableMut>>::Mapped, S, Vec, >, > { Write::filter_map(self.write(), |v| v.get_mut(index)) } } impl>>> Signal, S> { /// Returns a reference to an element or `None` if out of bounds. pub fn as_mut(&self) -> Option>>>::Mut as MappableMut>>>::Mapped> as MappableMut>>::Mapped, S, Option>>{ Write::filter_map(self.write(), |v| v.as_mut()) } }