stardom_reactive/
io.rs

1use std::mem;
2
3use crate::{memo::Memo, runtime::Runtime, ItemKey};
4
5pub trait HasRuntime {
6    fn runtime(&self) -> &'static Runtime;
7}
8
9pub trait Runnable {
10    fn run(&self);
11
12    fn item_key(&self) -> ItemKey;
13
14    fn depend<T: 'static>(&self, tracker: &impl Track<T>)
15    where
16        Self: Sized,
17    {
18        tracker.track(self);
19    }
20}
21
22pub trait Track<T: 'static> {
23    fn track<R: Runnable>(&self, runnable: &R);
24
25    fn track_active(&self)
26    where
27        Self: HasRuntime,
28    {
29        let rt = self.runtime();
30        if !rt.tracking.get() {
31            return;
32        }
33
34        if let Some(active) = rt.active.borrow().last() {
35            self.track(&ItemKeyWrapper(rt, *active));
36        }
37    }
38
39    fn with<U, F>(&self, f: F) -> U
40    where
41        F: FnOnce(&T) -> U;
42
43    fn get(&self) -> T
44    where
45        T: Copy,
46    {
47        self.with(|v| *v)
48    }
49
50    fn map<U, F>(&self, f: F) -> Memo<U>
51    where
52        Self: HasRuntime + Clone + 'static,
53        U: 'static,
54        F: Fn(&T) -> U + 'static,
55    {
56        let s = self.clone();
57        self.runtime().memo(move || s.with(|v| f(v)))
58    }
59}
60
61pub trait Trigger<T: 'static> {
62    fn trigger(&self);
63
64    fn update<U, F>(&self, f: F) -> U
65    where
66        F: FnOnce(&mut T) -> U;
67
68    fn replace(&self, value: T) -> T {
69        self.update(|v| mem::replace(v, value))
70    }
71
72    fn set(&self, value: T) {
73        self.replace(value);
74    }
75}
76
77struct ItemKeyWrapper(&'static Runtime, ItemKey);
78
79impl Runnable for ItemKeyWrapper {
80    fn run(&self) {
81        self.1.run(self.0);
82    }
83
84    fn item_key(&self) -> ItemKey {
85        self.1
86    }
87}