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}