lazy_observer/
lazy.rs

1use std::cell::{Ref, RefCell};
2use std::cmp::*;
3use std::fmt;
4use std::hash::*;
5use std::ops::*;
6use std::pin::Pin;
7use std::rc::Rc;
8
9use super::dirty_marker::DirtyMarker;
10use super::{exec_updater, notify_updater};
11
12pub struct Lazy<T> {
13    data: RefCell<Option<T>>,
14    updater: Rc<dyn Fn() -> T>,
15    dirty: Pin<Rc<DirtyMarker>>,
16}
17
18impl<T> Lazy<T> {
19    #[inline]
20    pub fn new<F: 'static + Fn() -> T>(updater: F) -> Self {
21        let updater = Rc::new(updater);
22        let dirty = Rc::pin(DirtyMarker::new(true));
23        Self {
24            data: RefCell::new(None),
25            updater,
26            dirty,
27        }
28    }
29    #[inline]
30    pub fn check_update(&self) {
31        if self.dirty.clear_dirty() {
32            match self.data.try_borrow_mut() {
33                Ok(mut x) => *x = Some(exec_updater(&self.dirty, &self.updater)),
34                Err(_) => {}
35            }
36        }
37    }
38    #[inline]
39    pub fn get_ref(&self) -> Ref<T> {
40        self.check_update();
41        notify_updater(&self.dirty);
42        Ref::map(self.data.borrow(), |x| x.as_ref().unwrap())
43    }
44}
45
46impl<T: Clone> Lazy<T> {
47    #[inline]
48    pub fn get(&self) -> T {
49        self.check_update();
50        notify_updater(&self.dirty);
51        self.data.borrow().as_ref().unwrap().clone()
52    }
53}
54
55impl<T> Drop for Lazy<T> {
56    fn drop(&mut self) {
57        self.dirty.destroy();
58    }
59}
60
61impl<T: PartialEq> PartialEq for Lazy<T> {
62    fn eq(&self, other: &Self) -> bool {
63        *self.get_ref() == *other.get_ref()
64    }
65}
66
67impl<T: Eq> Eq for Lazy<T> {}
68
69impl<T: PartialOrd> PartialOrd for Lazy<T> {
70    #[inline]
71    fn partial_cmp(&self, other: &Lazy<T>) -> Option<Ordering> {
72        PartialOrd::partial_cmp(&*self.get_ref(), &*other.get_ref())
73    }
74    #[inline]
75    fn lt(&self, other: &Lazy<T>) -> bool {
76        PartialOrd::lt(&*self.get_ref(), &*other.get_ref())
77    }
78    #[inline]
79    fn le(&self, other: &Lazy<T>) -> bool {
80        PartialOrd::le(&*self.get_ref(), &*other.get_ref())
81    }
82    #[inline]
83    fn ge(&self, other: &Lazy<T>) -> bool {
84        PartialOrd::ge(&*self.get_ref(), &*other.get_ref())
85    }
86    #[inline]
87    fn gt(&self, other: &Lazy<T>) -> bool {
88        PartialOrd::gt(&*self.get_ref(), &*other.get_ref())
89    }
90}
91
92impl<T: Ord> Ord for Lazy<T> {
93    #[inline]
94    fn cmp(&self, other: &Lazy<T>) -> Ordering {
95        Ord::cmp(&*self.get_ref(), &*other.get_ref())
96    }
97}
98
99impl<T: Hash> Hash for Lazy<T> {
100    fn hash<H: Hasher>(&self, state: &mut H) {
101        (*self.get_ref()).hash(state);
102    }
103}
104
105impl<T: Clone> Clone for Lazy<T> {
106    #[inline]
107    fn clone(&self) -> Lazy<T> {
108        let updater = self.updater.clone();
109        let dirty = Rc::pin(DirtyMarker::new(false));
110        Self {
111            data: RefCell::new(None),
112            updater,
113            dirty,
114        }
115    }
116}
117
118impl<T: fmt::Display> fmt::Display for Lazy<T> {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        fmt::Display::fmt(&*self.get_ref(), f)
121    }
122}
123
124impl<T: fmt::Debug> fmt::Debug for Lazy<T> {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        fmt::Debug::fmt(&*self.get_ref(), f)
127    }
128}