reactive-signals 0.1.0-alpha.4

reactive-signals is a dx-first scope-based fine-grained reactive system.
Documentation
use std::any::Any;

use crate::{signals::SignalType, CellType};

pub struct AnyData(pub(crate) Box<CellType<dyn Any>>);

impl std::fmt::Debug for AnyData {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "RefData")
    }
}

impl AnyData {
    pub fn new<T: 'static>(val: T) -> Self {
        Self(Box::new(CellType::new(val)))
    }

    pub fn with<T, R>(&self, f: impl Fn(&T::Inner) -> R) -> R
    where
        T: SignalType + 'static,
    {
        let val_any = self.val_ref();
        let val = (*val_any).downcast_ref::<T>().unwrap();
        f(val.inner())
    }

    pub fn update<T, R>(&self, f: impl Fn(&mut T::Inner) -> R) -> (bool, R)
    where
        T: SignalType + 'static,
    {
        #[allow(unused_mut)]
        let mut val_any = self.val_mut();
        let val = (*val_any).downcast_mut::<T>().unwrap();
        let hash_before = val.opt_hash();
        let r = f(val.inner_mut());
        let hash_after = val.opt_hash();
        let eq = match (hash_before, hash_after) {
            (Some(h1), Some(h2)) => h1 == h2,
            _ => false,
        };
        (eq, r)
    }

    pub fn cloned<T>(&self) -> T::Inner
    where
        T: SignalType + 'static,
        T::Inner: Clone,
    {
        let val_any = self.val_ref();
        let val = (*val_any).downcast_ref::<T>().unwrap();
        val.inner().clone()
    }

    pub fn get<T>(&self) -> T::Inner
    where
        T: SignalType + 'static,
        T::Inner: Copy,
    {
        let val_any = self.val_ref();
        let val = (*val_any).downcast_ref::<T>().unwrap();
        *val.inner()
    }

    pub fn set<T: SignalType + 'static>(&self, val: T::Inner) -> bool {
        #[allow(unused_mut)]
        let mut val_any = self.val_mut();
        let val_t = (*val_any).downcast_mut::<T>().unwrap();
        let eq = val_t.is_eq(&val);
        *val_t.inner_mut() = val;
        eq
    }
}

#[cfg(not(feature = "unsafe-cell"))]
impl AnyData {
    #[inline]
    fn val_ref(&self) -> std::cell::Ref<dyn Any> {
        self.0.borrow()
    }
    #[inline]
    fn val_mut(&self) -> std::cell::RefMut<dyn Any> {
        self.0.borrow_mut()
    }
}

#[cfg(feature = "unsafe-cell")]
impl AnyData {
    #[inline]
    fn val_ref(&self) -> &dyn Any {
        unsafe { &*self.0.get() }
    }

    #[inline]
    fn val_mut(&self) -> &mut dyn Any {
        unsafe { &mut *self.0.get() }
    }
}