fates/
fates.rs

1#![allow(dead_code)]
2
3use std::sync::atomic::{AtomicBool, Ordering};
4use std::sync::Arc;
5
6use parking_lot::RwLock;
7
8type FateFn<T> = dyn Fn() -> T + Send + Sync + 'static;
9
10pub trait FateTrait: Send + Sync {
11    fn is_dirty(&self) -> bool;
12    fn set_dirty(&self);
13    fn add_dependent(&self, dependent: Box<dyn FateTrait>);
14    fn remove_dependent(&self, dependent: Box<dyn FateTrait>);
15    fn get_id(&self) -> usize;
16}
17
18enum Binding<T> {
19    Value(T),
20    Expression(Box<FateFn<T>>),
21}
22
23impl<T: Default> Default for Binding<T> {
24    fn default() -> Self {
25        Self::Value(T::default())
26    }
27}
28
29#[derive(Default)]
30struct FateDependencies {
31    dependencies: Vec<Box<dyn FateTrait>>,
32    dependents: Vec<Box<dyn FateTrait>>,
33}
34
35#[derive(Default, Clone)]
36pub struct Fate<T: Clone> {
37    cached_value: Arc<RwLock<T>>,
38    dirty: Arc<AtomicBool>,
39    dependencies: Arc<RwLock<FateDependencies>>,
40    data: Arc<RwLock<Binding<T>>>,
41}
42
43impl<T: 'static + Clone + Send + Sync> FateTrait for Fate<T> {
44    fn is_dirty(&self) -> bool {
45        self.dirty.load(Ordering::Acquire)
46    }
47
48    fn set_dirty(&self) {
49        self.dirty.store(true, Ordering::Release);
50        let data = self.dependencies.read();
51        for dependent in &data.dependents {
52            dependent.set_dirty();
53        }
54    }
55
56    fn add_dependent(&self, dependent: Box<dyn FateTrait>) {
57        let mut data = self.dependencies.write();
58        data.dependents.push(dependent);
59    }
60
61    fn remove_dependent(&self, dependent: Box<dyn FateTrait>) {
62        let mut data = self.dependencies.write();
63        let index = data
64            .dependents
65            .iter()
66            .position(|dep| dep.get_id() == dependent.get_id());
67        if let Some(index) = index {
68            data.dependents.remove(index);
69        }
70    }
71
72    fn get_id(&self) -> usize {
73        Arc::as_ptr(&self.dependencies) as usize
74    }
75}
76
77impl<T: 'static + Clone + Send + Sync> Fate<T> {
78    pub fn get(&self) -> T {
79        if self.is_dirty() {
80            let data = self.data.write();
81            let result = match &*data {
82                Binding::Value(value) => value.clone(),
83                Binding::Expression(expression) => expression(),
84            };
85            let mut cached_value = self.cached_value.write();
86            *cached_value = result.clone();
87            self.dirty.store(false, Ordering::Release);
88            result
89        } else {
90            self.cached_value.read().clone()
91        }
92    }
93
94    pub fn by_ref(&self, ref_fn: impl FnOnce(&T)) {
95        let data = self.data.read();
96        if let Binding::Value(value) = &*data {
97            ref_fn(value);
98        }
99    }
100
101    pub fn by_ref_mut(&self, mut_ref_fn: impl FnOnce(&mut T)) {
102        let mut dirtied = false;
103        {
104            let mut data = self.data.write();
105            if let Binding::Value(value) = &mut *data {
106                mut_ref_fn(value);
107
108                dirtied = true;
109            }
110        }
111        if dirtied {
112            self.set_dirty();
113        }
114    }
115
116    pub fn bind_value(&self, value: T) {
117        {
118            let mut data = self.data.write();
119            *data = Binding::Value(value);
120        }
121        self.set_dirty();
122    }
123
124    pub fn bind_expression(
125        &self,
126        expression: Box<FateFn<T>>,
127        dependencies: Vec<Box<dyn FateTrait>>,
128    ) {
129        self.set_dependencies(dependencies);
130        {
131            let mut data = self.data.write();
132            *data = Binding::Expression(expression);
133        }
134        self.set_dirty();
135    }
136
137    pub fn from_value(value: T) -> Fate<T> {
138        Fate {
139            cached_value: Arc::new(RwLock::new(value.clone())),
140            dirty: Arc::new(AtomicBool::new(false)),
141            data: Arc::new(RwLock::new(Binding::Value(value))),
142            dependencies: Arc::new(RwLock::new(FateDependencies {
143                dependencies: vec![],
144                dependents: vec![],
145            })),
146        }
147    }
148
149    pub fn from_expression(
150        expression: Box<FateFn<T>>,
151        dependencies: Vec<Box<dyn FateTrait>>,
152    ) -> Fate<T> {
153        let result = Fate {
154            cached_value: Arc::new(RwLock::new(expression())),
155            dirty: Arc::new(AtomicBool::new(false)),
156            data: Arc::new(RwLock::new(Binding::Expression(expression))),
157            dependencies: Arc::new(RwLock::new(FateDependencies {
158                dependencies: vec![],
159                dependents: vec![],
160            })),
161        };
162        result.set_dependencies(dependencies);
163        result
164    }
165
166    /// Creates a Fate with the same value that depends on this Fate.
167    /// This can be useful for easily checking when the value has been updated.
168    ///
169    /// # Examples
170    ///
171    /// ```
172    /// fate! {
173    ///     let a = 5;
174    ///     let b = a + 3;
175    /// }
176    /// let child = b.create_dependent_clone();
177    /// assert_eq!(child.get(), 8);
178    /// fate! {
179    ///     a = 10;
180    /// }
181    /// assert_eq!(b.get(), 13);
182    /// assert_eq!(b.is_dirty(), false);
183    /// assert_eq!(child.is_dirty(), true);
184    /// assert_eq!(child.get(), 13);
185    /// assert_eq!(child.is_dirty(), false);
186    /// ```
187    pub fn create_dependent_clone(&self) -> Self {
188        let self_clone = self.clone();
189        let dependent_clone = Fate::from_expression(
190            Box::new(move || {
191                let value = self_clone.get();
192                value
193            }),
194            vec![Box::new(self.clone())],
195        );
196        dependent_clone
197    }
198
199    fn clear_dependencies(&self) {
200        self.remove_all_dependencies();
201        let mut data = self.dependencies.write();
202        data.dependencies.clear();
203    }
204
205    fn remove_all_dependencies(&self) {
206        let data = self.dependencies.read();
207        for dependency in &data.dependencies {
208            dependency.remove_dependent(Box::new(self.clone()));
209        }
210    }
211
212    fn set_dependencies(&self, dependencies: Vec<Box<dyn FateTrait>>) {
213        self.remove_all_dependencies();
214        let mut data = self.dependencies.write();
215        data.dependencies = dependencies;
216        for dependency in &data.dependencies {
217            dependency.add_dependent(Box::new(self.clone()));
218        }
219    }
220}
221
222#[cfg(test)]
223mod tests {
224    use std::thread;
225
226    use fates_macro::fate;
227
228    use super::Fate;
229    use crate::FateTrait;
230
231    #[test]
232    fn simple() {
233        let a = Fate::from_value(3);
234        let b = Fate::from_value(5);
235        let a_clone = a.clone();
236        let b_clone = b.clone();
237        let c = Fate::from_expression(
238            Box::new(move || a_clone.get() + b_clone.get()),
239            vec![Box::new(a.clone()), Box::new(b.clone())],
240        );
241        assert_eq!(c.get(), 8);
242        b.bind_value(100);
243        assert_eq!(c.get(), 103);
244    }
245
246    #[test]
247    fn less_simple() {
248        let a = Fate::from_value(10);
249        let b = Fate::from_value(23);
250        let a_clone = a.clone();
251        let b_clone = b.clone();
252        let c = Fate::from_expression(
253            Box::new(move || a_clone.get() + b_clone.get() * b_clone.get()),
254            vec![Box::new(a.clone()), Box::new(b.clone())],
255        );
256        assert_eq!(c.get(), 10 + 23 * 23);
257        b.bind_value(113);
258        assert_eq!(c.get(), 10 + 113 * 113);
259
260        let c_clone = c.clone();
261        let a_clone = a.clone();
262        let d = Fate::from_expression(
263            Box::new(move || c_clone.get() * a_clone.get()),
264            vec![Box::new(c.clone()), Box::new(a.clone())],
265        );
266
267        assert_eq!(d.get(), (10 + 113 * 113) * 10);
268
269        let a_clone = a.clone();
270        let b_clone = b.clone();
271        let e = Fate::from_value(2);
272        let e_clone = e.clone();
273        c.bind_expression(
274            Box::new(move || a_clone.get() * b_clone.get() / e_clone.get()),
275            vec![
276                Box::new(a.clone()),
277                Box::new(b.clone()),
278                Box::new(e.clone()),
279            ],
280        );
281        assert_eq!(c.get(), 10 * 113 / 2);
282    }
283
284    #[test]
285    fn chain() {
286        fate! {
287            [a, b]
288            let a = "a".to_string();
289            let b = "b".to_string() + &a;
290            let c = "c".to_string() + &b;
291        }
292
293        assert_eq!(c.get(), "cba");
294        a.bind_value("c".to_string());
295        assert_eq!(c.get(), "cbc");
296    }
297
298    fn circular_reference() {
299        let a = Fate::from_value(3);
300        let b = Fate::from_value(5);
301        let a_clone = a.clone();
302        let b_clone = b.clone();
303        let c = Fate::from_expression(
304            Box::new(move || a_clone.get() + b_clone.get()),
305            vec![Box::new(a.clone()), Box::new(b.clone())],
306        );
307        let a_clone = a.clone();
308        let c_clone = c.clone();
309        b.bind_expression(
310            Box::new(move || a_clone.get() + c_clone.get()),
311            vec![Box::new(a.clone()), Box::new(c.clone())],
312        );
313    }
314
315    #[test]
316    fn macro_simple_test() {
317        let a = 5;
318        let b = a * 5;
319        let c = a * b;
320        fate! {
321            [a2, b2]
322            let a2 = 5;
323            let b2 = a2 * 5;
324            let c2 = a2 * b2;
325        }
326        assert_eq!(a, a2.get());
327        assert_eq!(b, b2.get());
328        assert_eq!(c, c2.get());
329
330        let a = 7;
331        let b = a * 5;
332        let c = a * b;
333
334        fate! {a2 = 7;}
335        assert_eq!(a, a2.get());
336        assert_eq!(b, b2.get());
337        assert_eq!(c, c2.get());
338    }
339
340    #[test]
341    fn thread_safe_test() {
342        fate! {
343            [a]
344            let a = 0;
345            let b = a * 10;
346        }
347
348        let mut thread_handles = Vec::new();
349        for _i in 1..100 {
350            let a2: Fate<_> = a.clone();
351            let b2: Fate<_> = b.clone();
352            let handle = thread::spawn(move || {
353                for i in 1..100 {
354                    let value = 30;
355                    fate! {a2 = i + value;}
356                    let _r = b2.get();
357                    // note: this will not be the correct value because it is still
358                    // being assigned to randomly, but no exceptions!
359                }
360            });
361            thread_handles.push(handle);
362        }
363
364        for handle in thread_handles {
365            handle.join().unwrap();
366        }
367    }
368
369    #[test]
370    fn value_capture_test() {
371        let a = 5;
372        let b = 10;
373        fate! {
374            [c, d]
375            let c = 15; // Comment
376            let d = a + b;
377            let e = c * d;
378        }
379
380        assert_eq!(c.get(), d.get());
381        assert_eq!(e.get(), c.get() * d.get());
382
383        fate! {c = a + b;}
384        assert_eq!(c.get(), a + b);
385        assert_eq!(e.get(), c.get() * d.get());
386    }
387
388    #[test]
389    fn explicit_fate_test() {
390        struct TestStruct {
391            fate: Fate<i32>,
392        }
393        fate! {
394            let a = 10;
395        }
396        let test_struct = TestStruct { fate: a.clone() };
397        assert_eq!(a.get(), 10);
398        fate! {a = 15;}
399        assert_eq!(test_struct.fate.get(), 15);
400    }
401
402    #[test]
403    fn mix_types_test() {
404        fate! {
405            [a, b]
406            let a = "String".to_string();
407            let b = 10;
408            let c = a + " " + &b.to_string();
409        }
410
411        assert_eq!(&c.get(), "String 10");
412
413        fate! {
414            a = "String2".to_string();
415            b = 100;
416        }
417
418        assert_eq!(&c.get(), "String2 100");
419    }
420
421    #[test]
422    fn ref_test() {
423        fate! {
424            let a = vec![1, 2, 3];
425        }
426        assert_eq!(a.get(), vec![1, 2, 3]);
427
428        a.by_ref_mut(|a| a.push(4));
429        assert_eq!(a.get(), vec![1, 2, 3, 4]);
430
431        let mut val = 2;
432        a.by_ref(|a| val = a[2]);
433        assert_eq!(val, 3);
434    }
435
436    #[test]
437    fn string_example_test() {
438        fate! {
439            [name]
440            let name = "Alex".to_string();
441            let hello = "Hello, ".to_string() + &name;
442            let goodbye = "Goodbye, ".to_string() + &name;
443        }
444        assert_eq!(&hello.get(), "Hello, Alex");
445        assert_eq!(&goodbye.get(), "Goodbye, Alex");
446
447        fate! {name = "Sam".to_string();}
448        assert_eq!(&hello.get(), "Hello, Sam");
449        assert_eq!(&goodbye.get(), "Goodbye, Sam");
450    }
451
452    #[test]
453    fn dependent_child_clone() {
454        fate! {
455            [a]
456            let a = 5;
457            let b = a + 3;
458        }
459        let child = b.create_dependent_clone();
460        assert_eq!(child.get(), 8);
461        fate! {
462            a = 10;
463        }
464        assert_eq!(b.get(), 13);
465        assert_eq!(b.is_dirty(), false);
466        assert_eq!(child.is_dirty(), true);
467        assert_eq!(child.get(), 13);
468        assert_eq!(child.is_dirty(), false);
469    }
470
471    #[test]
472    fn is_value_test() {
473        fate! {
474            [a]
475            let a = 5;
476            let b = a * 5;
477        }
478
479        {
480            let mut is_value = false;
481            a.by_ref_mut(|_a| {
482                is_value = true;
483            });
484            assert_eq!(is_value, true);
485        }
486        {
487            let mut is_value = false;
488            b.by_ref_mut(|_b| {
489                is_value = true;
490            });
491            assert_eq!(is_value, false);
492        }
493    }
494}