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}