lazy_observer/
lazy_field.rs1use 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}