lunk/
prim.rs

1use std::{
2    mem::swap,
3    rc::{
4        Rc,
5        Weak,
6    },
7    cell::{
8        RefCell,
9        Ref,
10    },
11    ops::Deref,
12};
13use crate::{
14    core::{
15        Id,
16        ValueTrait,
17        ProcessingContext,
18        Cleanup,
19        Link_,
20        Value,
21        IntoValue,
22    },
23    Link,
24};
25
26pub struct PrimMut_<T> {
27    value: T,
28    first_change: bool,
29    next: Vec<Weak<Link_>>,
30}
31
32impl<T: 'static> PrimMut_<T> {
33    pub fn get(&self) -> &T {
34        return &self.value;
35    }
36}
37
38pub(crate) struct Prim_<T> {
39    mut_: RefCell<PrimMut_<T>>,
40}
41
42impl<T> ValueTrait for Prim_<T> {
43    fn next_links(&self) -> Vec<crate::Link> {
44        let mut out = vec![];
45        let mut self2 = self.mut_.borrow_mut();
46        out.reserve(self2.next.len());
47        self2.next.retain_mut(|e| {
48            match e.upgrade() {
49                Some(e) => {
50                    out.push(Link(e.clone()));
51                    return true;
52                },
53                None => {
54                    return false;
55                },
56            }
57        });
58        return out;
59    }
60}
61
62impl<T> Cleanup for Prim_<T> {
63    fn clean(&self) {
64        self.mut_.borrow_mut().first_change = true;
65    }
66}
67
68/// This represents a non-collection value, like an int, bool, or struct.
69#[derive(Clone)]
70pub struct Prim<T>(pub(crate) Rc<Prim_<T>>);
71
72#[derive(Clone)]
73pub struct WeakPrim<T>(Weak<Prim_<T>>);
74
75impl<T: 'static> Prim<T> {
76    pub fn new(initial: T) -> Self {
77        return Prim(Rc::new(Prim_ { mut_: RefCell::new(PrimMut_ {
78            value: initial,
79            first_change: true,
80            next: vec![],
81        }) }));
82    }
83
84    /// Used internally by the `link!` macro to establish graph edges between an input
85    /// value and the link.
86    pub fn add_next(&self, link: &Link) {
87        self.0.mut_.borrow_mut().next.push(Rc::downgrade(&link.0));
88    }
89
90    /// Get a weak reference to the value.
91    pub fn weak(&self) -> WeakPrim<T> {
92        return WeakPrim(Rc::downgrade(&self.0));
93    }
94
95    /// Modify the value and mark downstream links as needing to be rerun.
96    pub fn set(&self, pc: &mut ProcessingContext, value: T) {
97        let first_change;
98        {
99            let mut self2 = self.0.mut_.borrow_mut();
100            first_change = self2.first_change;
101            self2.first_change = false;
102            self2.value = value;
103        }
104        if first_change {
105            pc.1.cleanup.push(self.0.clone());
106            if !pc.1.processing {
107                for l in self.0.next_links() {
108                    pc.1.step1_stacked_links.push((true, l));
109                }
110            }
111        }
112    }
113
114    /// Immutable access to the data via a `Deref` wrapper.
115    pub fn borrow<'a>(&'a self) -> ValueRef<'a, T> {
116        return ValueRef(self.0.mut_.borrow());
117    }
118}
119
120impl<T: 'static> IntoValue for Prim<T> {
121    fn into_value(&self) -> Value {
122        return Value(self.0.clone());
123    }
124}
125
126impl<T: 'static> WeakPrim<T> {
127    pub fn upgrade(&self) -> Option<Prim<T>> {
128        return Some(Prim(self.0.upgrade()?));
129    }
130}
131
132pub struct ValueRef<'a, T: 'static>(Ref<'a, PrimMut_<T>>);
133
134impl<'a, T: 'static> Deref for ValueRef<'a, T> {
135    type Target = T;
136
137    fn deref(&self) -> &Self::Target {
138        return &self.0.value;
139    }
140}
141
142pub struct HistPrimMut_<T: PartialEq + Clone> {
143    value: T,
144    previous_value: Option<T>,
145    next: Vec<Weak<Link_>>,
146}
147
148impl<T: PartialEq + Clone + 'static> HistPrimMut_<T> {
149    pub fn get(&self) -> &T {
150        return &self.value;
151    }
152}
153
154pub(crate) struct HistPrim_<T: PartialEq + Clone> {
155    pub(crate) id: Id,
156    mut_: RefCell<HistPrimMut_<T>>,
157}
158
159impl<T: PartialEq + Clone> ValueTrait for HistPrim_<T> {
160    fn next_links(&self) -> Vec<crate::Link> {
161        let mut out = vec![];
162        let mut self2 = self.mut_.borrow_mut();
163        out.reserve(self2.next.len());
164        self2.next.retain_mut(|e| {
165            match e.upgrade() {
166                Some(e) => {
167                    out.push(Link(e.clone()));
168                    return true;
169                },
170                None => {
171                    return false;
172                },
173            }
174        });
175        return out;
176    }
177}
178
179impl<T: PartialEq + Clone> Cleanup for HistPrim_<T> {
180    fn clean(&self) {
181        self.mut_.borrow_mut().previous_value = None;
182    }
183}
184
185/// Like Prim represents a non-collection value, like an int, bool, or struct. It
186/// keeps the old value around, and only triggers updates if the value is changed.
187/// The old value is available for links to query if they need to refer to the old
188/// value for some reason.  The value must implement `PartialEq` and `Clone`.
189#[derive(Clone)]
190pub struct HistPrim<T: PartialEq + Clone>(pub(crate) Rc<HistPrim_<T>>);
191
192#[derive(Clone)]
193pub struct WeakHistPrim<T: PartialEq + Clone>(Weak<HistPrim_<T>>);
194
195impl<T: PartialEq + Clone + 'static> HistPrim<T> {
196    pub fn new(pc: &mut ProcessingContext, initial: T) -> Self {
197        let id = pc.1.take_id();
198        return HistPrim(Rc::new(HistPrim_ {
199            id: id,
200            mut_: RefCell::new(HistPrimMut_ {
201                value: initial,
202                previous_value: None,
203                next: vec![],
204            }),
205        }));
206    }
207
208    /// Used internally by the `link!` macro to establish graph edges between an input
209    /// value and the link.
210    pub fn add_next(&self, link: &Link) {
211        self.0.mut_.borrow_mut().next.push(Rc::downgrade(&link.0));
212    }
213
214    /// Get a weak reference to the value.
215    pub fn weak(&self) -> WeakHistPrim<T> {
216        return WeakHistPrim(Rc::downgrade(&self.0));
217    }
218
219    /// Modify the value and mark downstream links as needing to be rerun.
220    pub fn set(&self, pc: &mut ProcessingContext, mut value: T) {
221        let first_change;
222        {
223            let mut self2 = self.0.mut_.borrow_mut();
224            if self2.value == value {
225                return;
226            }
227            swap(&mut self2.value, &mut value);
228            first_change = self2.previous_value.is_none();
229            self2.previous_value = Some(value);
230        }
231        if first_change {
232            pc.1.cleanup.push(self.0.clone());
233            if !pc.1.processing {
234                for l in self.0.next_links() {
235                    pc.1.step1_stacked_links.push((true, l));
236                }
237            }
238        }
239    }
240
241    /// Immutable access to the data via a `Deref` wrapper.
242    pub fn borrow<'a>(&'a self) -> HistValueRef<'a, T> {
243        return HistValueRef(self.0.mut_.borrow());
244    }
245
246    /// Get the internal value.  This copies/clones the value.
247    pub fn get(&self) -> T {
248        return self.0.mut_.borrow().value.clone();
249    }
250
251    /// Get the previous version of the value.  This copies/clones the value.
252    pub fn get_old(&self) -> T {
253        let m = self.0.mut_.borrow();
254        return m.previous_value.as_ref().unwrap_or_else(|| &m.value).clone();
255    }
256}
257
258impl<T: PartialEq + Clone + 'static> IntoValue for HistPrim<T> {
259    fn into_value(&self) -> Value {
260        return Value(self.0.clone());
261    }
262}
263
264impl<T: PartialEq + Clone + 'static> WeakHistPrim<T> {
265    pub fn upgrade(&self) -> Option<HistPrim<T>> {
266        return Some(HistPrim(self.0.upgrade()?));
267    }
268}
269
270pub struct HistValueRef<'a, T: PartialEq + Clone + 'static>(Ref<'a, HistPrimMut_<T>>);
271
272impl<'a, T: PartialEq + Clone + 'static> Deref for HistValueRef<'a, T> {
273    type Target = T;
274
275    fn deref(&self) -> &Self::Target {
276        return &self.0.value;
277    }
278}