use crate::read::Readable; use crate::read::ReadableVecExt; use crate::rt::CopyValue; use crate::signal::Signal; use crate::write::Writable; use crate::{GlobalMemo, GlobalSignal, ReadOnlySignal, ReadableValueIterator, SignalData}; use generational_box::UnsyncStorage; use generational_box::{AnyStorage, Storage}; use std::{ fmt::{Debug, Display}, ops::{Add, Div, Mul, Sub}, }; macro_rules! read_impls { ($ty:ident $(: $extra_bounds:path)? $(, $bound_ty:ident : $bound:path, $vec_bound_ty:ident : $vec_bound:path)?) => { $( impl Default for $ty { #[track_caller] fn default() -> Self { Self::new_maybe_sync(Default::default()) } } )? impl std::clone::Clone for $ty { #[track_caller] fn clone(&self) -> Self { *self } } impl Copy for $ty {} impl Display for $ty { #[track_caller] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.with(|v| Display::fmt(v, f)) } } impl Debug for $ty { #[track_caller] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.with(|v| Debug::fmt(v, f)) } } impl PartialEq for $ty { #[track_caller] fn eq(&self, other: &T) -> bool { self.with(|v| *v == *other) } } impl $ty, $($vec_bound_ty)?> { /// Returns the length of the inner vector. #[track_caller] pub fn len(&self) -> usize { self.with(|v| v.len()) } /// Returns true if the inner vector is empty. #[track_caller] pub fn is_empty(&self) -> bool { self.with(|v| v.is_empty()) } } }; } macro_rules! write_impls { ($ty:ident, $bound:path, $vec_bound:path) => { impl + Copy + 'static, S: $bound> std::ops::Add for $ty { type Output = T; #[track_caller] fn add(self, rhs: T) -> Self::Output { self.with(|v| *v + rhs) } } impl + Copy + 'static, S: $bound> std::ops::AddAssign for $ty { #[track_caller] fn add_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v + rhs) } } impl + Copy + 'static, S: $bound> std::ops::SubAssign for $ty { #[track_caller] fn sub_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v - rhs) } } impl + Copy + 'static, S: $bound> std::ops::Sub for $ty { type Output = T; #[track_caller] fn sub(self, rhs: T) -> Self::Output { self.with(|v| *v - rhs) } } impl + Copy + 'static, S: $bound> std::ops::MulAssign for $ty { #[track_caller] fn mul_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v * rhs) } } impl + Copy + 'static, S: $bound> std::ops::Mul for $ty { type Output = T; #[track_caller] fn mul(self, rhs: T) -> Self::Output { self.with(|v| *v * rhs) } } impl + Copy + 'static, S: $bound> std::ops::DivAssign for $ty { #[track_caller] fn div_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v / rhs) } } impl + Copy + 'static, S: $bound> std::ops::Div for $ty { type Output = T; #[track_caller] fn div(self, rhs: T) -> Self::Output { self.with(|v| *v / rhs) } } }; } read_impls!(CopyValue, S: Storage, S: Storage>); write_impls!(CopyValue, Storage, Storage>); impl>> IntoIterator for CopyValue, S> { type IntoIter = ReadableValueIterator; type Item = S::Ref; fn into_iter(self) -> Self::IntoIter { self.iter() } } read_impls!(Signal, S: Storage>, S: Storage>>); write_impls!(Signal, Storage>, Storage>>); impl>>> IntoIterator for Signal, S> { type IntoIter = ReadableValueIterator; type Item = S::Ref; fn into_iter(self) -> Self::IntoIter { self.iter() } } read_impls!( ReadOnlySignal, S: Storage>, S: Storage>> ); impl>>> IntoIterator for ReadOnlySignal, S> { type IntoIter = ReadableValueIterator; type Item = S::Ref; fn into_iter(self) -> Self::IntoIter { self.iter() } } read_impls!(GlobalSignal); impl IntoIterator for GlobalSignal> { type IntoIter = ReadableValueIterator; type Item = ::Ref; fn into_iter(self) -> Self::IntoIter { self.iter() } } read_impls!(GlobalMemo: PartialEq); impl IntoIterator for GlobalMemo> { type IntoIter = ReadableValueIterator; type Item = ::Ref; fn into_iter(self) -> Self::IntoIter { self.iter() } }