lazy_observer/
lazy_field.rs

1use std::cell::{Ref, RefCell};
2use std::ops::*;
3use std::pin::Pin;
4use std::rc::Rc;
5
6use super::dirty_marker::DirtyMarker;
7use super::{exec_field_updater, notify_updater};
8
9pub struct LazyField<S, T> {
10    data: RefCell<Option<T>>,
11    updater: Rc<dyn for<'r> Fn(&'r S) -> T>,
12    dirty: Pin<Rc<DirtyMarker>>,
13}
14
15impl<S, T> LazyField<S, T> {
16    #[inline]
17    pub fn new<F: 'static + for<'r> Fn(&'r S) -> T>(updater: F) -> Self {
18        let updater = Rc::new(updater);
19        let dirty = Rc::pin(DirtyMarker::new(true));
20        Self {
21            data: RefCell::new(None),
22            updater,
23            dirty,
24        }
25    }
26    #[inline]
27    pub fn check_update(&self, s: &S) {
28        if self.dirty.clear_dirty() {
29            match self.data.try_borrow_mut() {
30                Ok(mut x) => *x = Some(exec_field_updater(&self.dirty, s, &self.updater)),
31                Err(_) => {}
32            }
33        }
34    }
35    #[inline]
36    pub fn get_ref(&self, s: &S) -> Ref<T> {
37        self.check_update(s);
38        notify_updater(&self.dirty);
39        Ref::map(self.data.borrow(), |x| x.as_ref().unwrap())
40    }
41}
42
43impl<S, T: Clone> LazyField<S, T> {
44    #[inline]
45    pub fn get(&self, s: &S) -> T {
46        self.check_update(s);
47        notify_updater(&self.dirty);
48        self.data.borrow().as_ref().unwrap().clone()
49    }
50}
51
52impl<S, T> Drop for LazyField<S, T> {
53    fn drop(&mut self) {
54        self.dirty.destroy();
55    }
56}
57
58impl<S, T: Clone> Clone for LazyField<S, T> {
59    #[inline]
60    fn clone(&self) -> LazyField<S, T> {
61        let updater = self.updater.clone();
62        let dirty = Rc::pin(DirtyMarker::new(false));
63        Self {
64            data: RefCell::new(None),
65            updater,
66            dirty,
67        }
68    }
69}