diff --git a/dynatos-reactive/src/lib.rs b/dynatos-reactive/src/lib.rs index ba976bd..47c06d0 100644 --- a/dynatos-reactive/src/lib.rs +++ b/dynatos-reactive/src/lib.rs @@ -14,7 +14,18 @@ pub mod with_default; pub use self::{ derived::Derived, effect::{Effect, WeakEffect}, - signal::Signal, + signal::{ + Signal, + SignalGet, + SignalGetClone, + SignalGetCloned, + SignalGetCopy, + SignalReplace, + SignalSet, + SignalSetWith, + SignalUpdate, + SignalWith, + }, trigger::Trigger, with_default::{SignalWithDefault, WithDefault}, }; @@ -22,130 +33,6 @@ pub use self::{ // Imports use std::marker::Unsize; -/// Types which may be copied by [`SignalGet`] -pub trait SignalGetCopy: Sized { - fn copy(self) -> T; -} - -impl SignalGetCopy for &'_ T { - fn copy(self) -> T { - *self - } -} -impl SignalGetCopy> for Option<&'_ T> { - fn copy(self) -> Option { - self.copied() - } -} - -/// Signal get -pub trait SignalGet { - /// Gets the signal value, by copying it. - fn get(&self) -> T; -} - -impl SignalGet for S -where - S: SignalWith, - for<'a> S::Value<'a>: SignalGetCopy, -{ - fn get(&self) -> T { - self.with(|value| value.copy()) - } -} - -/// Types which may be cloned by [`SignalGetCloned`] -pub trait SignalGetClone: Sized { - fn clone(self) -> T; -} - -impl SignalGetClone for &'_ T { - fn clone(self) -> T { - self.clone() - } -} -impl SignalGetClone> for Option<&'_ T> { - fn clone(self) -> Option { - self.cloned() - } -} - -/// Signal cloned -pub trait SignalGetCloned { - /// Gets the signal value, by cloning it. - fn get_cloned(&self) -> T; -} - -impl SignalGetCloned for S -where - S: SignalWith, - for<'a> S::Value<'a>: SignalGetClone, -{ - fn get_cloned(&self) -> T { - self.with(|value| value.clone()) - } -} - -/// Signal with -pub trait SignalWith { - /// Value type - type Value<'a>: ?Sized; - - /// Uses the signal value - fn with(&self, f: F) -> O - where - F: for<'a> FnOnce(Self::Value<'a>) -> O; -} - -/// Types which may be set by [`SignalSet`] -pub trait SignalSetWith: Sized { - fn set(self, new_value: T); -} - -impl SignalSetWith for &'_ mut T { - fn set(self, new_value: T) { - *self = new_value; - } -} -impl SignalSetWith for &'_ mut Option { - fn set(self, new_value: T) { - *self = Some(new_value); - } -} - -/// Signal set -pub trait SignalSet { - /// Sets the signal value - fn set(&self, new_value: Value); -} - -impl SignalSet for S -where - S: SignalUpdate, - for<'a> S::Value<'a>: SignalSetWith, -{ - fn set(&self, new_value: T) { - self.update(|value| SignalSetWith::set(value, new_value)); - } -} - -/// Signal replace -pub trait SignalReplace { - /// Replaces the signal value, returning the previous value - fn replace(&self, new_value: Value) -> Value; -} - -/// Signal update -pub trait SignalUpdate { - /// Value type - type Value<'a>: ?Sized; - - /// Updates the signal value - fn update(&self, f: F) -> O - where - F: for<'a> FnOnce(Self::Value<'a>) -> O; -} - /// Types that may be converted into a subscriber pub trait IntoSubscriber { /// Converts this type into a weak effect. diff --git a/dynatos-reactive/src/signal.rs b/dynatos-reactive/src/signal.rs index e105be3..84f2ea0 100644 --- a/dynatos-reactive/src/signal.rs +++ b/dynatos-reactive/src/signal.rs @@ -3,9 +3,25 @@ //! A read-write value that automatically updates //! any subscribers when changed. +// Modules +pub mod ops; + +// Exports +pub use ops::{ + SignalGet, + SignalGetClone, + SignalGetCloned, + SignalGetCopy, + SignalReplace, + SignalSet, + SignalSetWith, + SignalUpdate, + SignalWith, +}; + // Imports use { - crate::{effect, SignalReplace, SignalUpdate, SignalWith, Trigger}, + crate::{effect, Trigger}, std::{cell::RefCell, fmt, marker::Unsize, mem, ops::CoerceUnsized, rc::Rc}, }; @@ -121,7 +137,7 @@ mod test { let signals = std::array::from_fn::<_, 100, _>(|_| Signal::new(0_i32)); bencher.iter(|| { for signal in &signals { - let signal = test::black_box(signal.clone()); + let signal = test::black_box(Signal::clone(signal)); mem::forget(signal); } }); diff --git a/dynatos-reactive/src/signal/ops.rs b/dynatos-reactive/src/signal/ops.rs new file mode 100644 index 0000000..4939ed5 --- /dev/null +++ b/dynatos-reactive/src/signal/ops.rs @@ -0,0 +1,125 @@ +//! Signal operators + +/// Types which may be copied by [`SignalGet`] +pub trait SignalGetCopy: Sized { + fn copy(self) -> T; +} + +impl SignalGetCopy for &'_ T { + fn copy(self) -> T { + *self + } +} +impl SignalGetCopy> for Option<&'_ T> { + fn copy(self) -> Option { + self.copied() + } +} + +/// Signal get +pub trait SignalGet { + /// Gets the signal value, by copying it. + fn get(&self) -> T; +} + +impl SignalGet for S +where + S: SignalWith, + for<'a> S::Value<'a>: SignalGetCopy, +{ + fn get(&self) -> T { + self.with(|value| value.copy()) + } +} + +/// Types which may be cloned by [`SignalGetCloned`] +pub trait SignalGetClone: Sized { + fn clone(self) -> T; +} + +impl SignalGetClone for &'_ T { + fn clone(self) -> T { + self.clone() + } +} +impl SignalGetClone> for Option<&'_ T> { + fn clone(self) -> Option { + self.cloned() + } +} + +/// Signal cloned +pub trait SignalGetCloned { + /// Gets the signal value, by cloning it. + fn get_cloned(&self) -> T; +} + +impl SignalGetCloned for S +where + S: SignalWith, + for<'a> S::Value<'a>: SignalGetClone, +{ + fn get_cloned(&self) -> T { + self.with(|value| value.clone()) + } +} + +/// Signal with +pub trait SignalWith { + /// Value type + type Value<'a>: ?Sized; + + /// Uses the signal value + fn with(&self, f: F) -> O + where + F: for<'a> FnOnce(Self::Value<'a>) -> O; +} + +/// Types which may be set by [`SignalSet`] +pub trait SignalSetWith: Sized { + fn set(self, new_value: T); +} + +impl SignalSetWith for &'_ mut T { + fn set(self, new_value: T) { + *self = new_value; + } +} +impl SignalSetWith for &'_ mut Option { + fn set(self, new_value: T) { + *self = Some(new_value); + } +} + +/// Signal set +pub trait SignalSet { + /// Sets the signal value + fn set(&self, new_value: Value); +} + +impl SignalSet for S +where + S: SignalUpdate, + for<'a> S::Value<'a>: SignalSetWith, +{ + fn set(&self, new_value: T) { + self.update(|value| SignalSetWith::set(value, new_value)); + } +} + +/// Signal replace +pub trait SignalReplace { + /// Replaces the signal value, returning the previous value + fn replace(&self, new_value: Value) -> Value; +} + +/// Signal update +pub trait SignalUpdate { + /// Value type + type Value<'a>: ?Sized; + + /// Updates the signal value + fn update(&self, f: F) -> O + where + F: for<'a> FnOnce(Self::Value<'a>) -> O; +}