use crate::*;
impl<T> SignalInner<T>
where
T: Clone,
{
pub fn new(value: T) -> Self {
let inner: SignalInner<T> = SignalInner {
value,
listeners: Vec::new(),
alive: true,
};
inner
}
}
impl<T> Signal<T>
where
T: Clone + PartialEq,
{
pub fn new(value: T) -> Self {
let boxed: Box<SignalInner<T>> = Box::new(SignalInner::new(value));
Signal {
inner: Box::leak(boxed) as *mut SignalInner<T>,
}
}
pub(crate) fn from_inner(inner: *mut SignalInner<T>) -> Self {
Signal { inner }
}
pub(crate) fn get_inner(&self) -> *mut SignalInner<T> {
self.inner
}
#[allow(clippy::mut_from_ref)]
fn get_inner_mut(&self) -> &mut SignalInner<T> {
unsafe { &mut *self.get_inner() }
}
pub fn get(&self) -> T {
self.get_inner_mut().get_value().clone()
}
pub fn try_get(&self) -> Option<T> {
Some(self.get_inner_mut().get_value().clone())
}
pub fn subscribe<F>(&self, callback: F)
where
F: FnMut() + 'static,
{
self.get_inner_mut()
.get_mut_listeners()
.push(Box::new(callback));
}
pub fn replace_subscribe<F>(&self, callback: F)
where
F: FnMut() + 'static,
{
let listeners: &mut Vec<Box<dyn FnMut()>> = self.get_inner_mut().get_mut_listeners();
listeners.clear();
listeners.push(Box::new(callback));
}
pub fn clear_listeners(&self) {
let inner: &mut SignalInner<T> = self.get_inner_mut();
inner.set_alive(false);
inner.get_mut_listeners().clear();
}
pub fn set(&self, value: T) {
let inner: &mut SignalInner<T> = self.get_inner_mut();
if !inner.get_alive() {
return;
}
if inner.get_value() == &value {
return;
}
inner.set_value(value);
for listener in inner.get_mut_listeners().iter_mut() {
listener();
}
schedule_signal_update();
}
pub fn set_silent(&self, value: T) {
let inner: &mut SignalInner<T> = self.get_inner_mut();
if !inner.get_alive() {
return;
}
if inner.get_value() == &value {
return;
}
inner.set_value(value);
for listener in inner.get_mut_listeners().iter_mut() {
listener();
}
}
pub fn try_set(&self, value: T) -> bool {
let inner: &mut SignalInner<T> = self.get_inner_mut();
if !inner.get_alive() {
return false;
}
if inner.get_value() == &value {
return false;
}
inner.set_value(value);
for listener in inner.get_mut_listeners().iter_mut() {
listener();
}
schedule_signal_update();
true
}
}
impl<T> Deref for Signal<T>
where
T: Clone + PartialEq,
{
type Target = T;
fn deref(&self) -> &Self::Target {
panic!("Signal does not support direct dereference; use .get() instead");
}
}
impl<T> DerefMut for Signal<T>
where
T: Clone + PartialEq,
{
fn deref_mut(&mut self) -> &mut Self::Target {
panic!("Signal does not support direct dereference; use .set() instead");
}
}
impl<T> Clone for Signal<T>
where
T: Clone + PartialEq,
{
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Signal<T> where T: Clone + PartialEq {}
unsafe impl<T> Sync for SignalCell<T> where T: Clone + PartialEq {}
impl<T> SignalCell<T>
where
T: Clone + PartialEq,
{
pub const fn new() -> Self {
SignalCell {
inner: UnsafeCell::new(None),
}
}
pub(crate) fn get_inner(&self) -> *mut Option<Signal<T>> {
self.inner.get()
}
pub fn set(&self, signal: Signal<T>) {
unsafe {
let ptr: &mut Option<Signal<T>> = &mut *self.get_inner();
if ptr.is_some() {
panic!("SignalCell::set called on an already-initialized cell");
}
*ptr = Some(signal);
}
}
pub fn get(&self) -> Signal<T> {
unsafe {
let ptr: &Option<Signal<T>> = &*self.get_inner();
match ptr {
Some(signal) => *signal,
None => panic!("SignalCell::get called on an uninitialized cell"),
}
}
}
}
impl<T> Default for SignalCell<T>
where
T: Clone + PartialEq,
{
fn default() -> Self {
Self::new()
}
}