reactive-signals 0.1.0-alpha.4

reactive-signals is a dx-first scope-based fine-grained reactive system.
Documentation
use std::{marker::PhantomData, ops::Deref, rc::Rc};

use crate::{
    runtimes::{Runtime, ServerRuntime},
    signal,
    tests::StringStore,
};

#[test]
fn test_scopes_deep() {
    let root = ServerRuntime::new_root_scope();

    let mut sc = root.clone();
    let num_sig = signal!(sc, 5);

    (0..3).for_each(|_| sc = sc.new_child());

    let output = Rc::new(StringStore::new());
    let _str_sig = signal!(sc, clone: output, move || output
        .push(format!("val: {}", num_sig.get())));

    num_sig.set(4);

    assert_eq!(output.values(), "val: 5, val: 4");
}

#[test]
fn test_scopes_discard() {
    let root = ServerRuntime::new_root_scope();

    let sc0 = root.clone();
    let num_sig = signal!(sc0, 5);

    let sc1 = sc0.new_child();
    let sc2 = sc1.new_child();
    let sc3 = sc2.new_child();

    let output = Rc::new(StringStore::new());
    let _str_sig = signal!(sc3, clone: output, move || output
        .push(format!("val: {}", num_sig.get())));

    num_sig.set(4);

    assert_eq!(output.values(), "val: 5, val: 4");

    sc2.discard();

    num_sig.set(4);

    assert_eq!(output.values(), "val: 5, val: 4");
}

#[derive(Copy, Clone)]
pub struct ScopeId<RT: Runtime> {
    pub(crate) _sx: usize,
    pub(crate) _rt: RT,
}

impl<RT: Runtime> Scope<RT> for ScopeId<RT> {
    fn get_id(&self) -> usize {
        self._sx
    }
}
pub trait Scope<RT: Runtime> {
    fn get_id(&self) -> usize;
}

pub struct ScopeWrap1<I, RT>
where
    I: Scope<RT>,
    RT: Runtime,
{
    inner: I,
    pos: usize,
    rt: PhantomData<RT>,
}

impl<I, RT> ScopeWrap1<I, RT>
where
    I: Scope<RT>,
    RT: Runtime,
{
    fn get_pos(&self) -> usize {
        self.pos
    }
}

impl<I: Scope<RT>, RT: Runtime> Scope<RT> for ScopeWrap1<I, RT> {
    fn get_id(&self) -> usize {
        self.inner.get_id()
    }
}

impl<I: Scope<RT>, RT: Runtime> Deref for ScopeWrap1<I, RT> {
    type Target = I;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

pub struct ScopeWrap2<I, RT>
where
    I: Scope<RT>,
    RT: Runtime,
{
    inner: I,
    some_data: usize,
    rt: PhantomData<RT>,
}

impl<I: Scope<RT>, RT: Runtime> Scope<RT> for ScopeWrap2<I, RT> {
    fn get_id(&self) -> usize {
        self.inner.get_id()
    }
}

impl<I, RT> ScopeWrap2<I, RT>
where
    I: Scope<RT>,
    RT: Runtime,
{
    #[allow(dead_code)]
    fn get_some_data(&self) -> usize {
        self.some_data
    }
}
impl<I: Scope<RT>, RT: Runtime> Deref for ScopeWrap2<I, RT> {
    type Target = I;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

fn get_scope_id<RT: Runtime>() -> ScopeId<RT> {
    unimplemented!()
}

fn some_func<RT: Runtime, SC: Scope<RT>>(_sc: SC) {}

#[allow(dead_code)]
fn chained_deref() {
    let scope = get_scope_id::<ServerRuntime>();

    let wrap1 = ScopeWrap1 {
        inner: scope,
        pos: 2,
        rt: PhantomData,
    };

    wrap1.get_id();

    let wrap2 = ScopeWrap2 {
        inner: wrap1,
        some_data: 4,
        rt: PhantomData,
    };

    wrap2.get_id();
    wrap2.get_pos();
    wrap2.get_some_data();
    some_func(wrap2);
}