rart_rs/common/
lazy.rs

1use core::cell::UnsafeCell;
2use core::ops::Deref;
3use crate::common::UnsafeOption;
4use crate::common::result::Expect;
5
6pub type LazyInitFn<T> = fn() -> T;
7
8pub struct Lazy<T: Sized> {
9    data: UnsafeOption<T>,
10    init: Option<LazyInitFn<T>>,
11}
12
13// TODO Explain why this is safe
14unsafe impl<T: Sized> Sync for Lazy<T> {}
15
16unsafe impl<T: Sized> Send for Lazy<T> {}
17
18impl<T: Sized> Lazy<T> {
19    pub const fn new() -> Self {
20        Self {
21            data: UnsafeCell::new(None),
22            init: None,
23        }
24    }
25
26    pub const fn new_with_init(init_fn: LazyInitFn<T>) -> Self {
27        Self {
28            data: UnsafeCell::new(None),
29            init: Some(init_fn),
30        }
31    }
32
33    pub fn init(&self, data: T) {
34        // TODO Explain why this is safe
35        unsafe {
36            let data_ptr = &mut *self.data.get();
37            if data_ptr.is_none() {
38                *data_ptr = Some(data);
39            }
40        }
41    }
42
43    pub fn data(&self) -> &T {
44        // TODO Explain why this is safe
45        unsafe {
46            let data_ptr = &*self.data.get();
47            data_ptr.as_ref().rart_expect("Cannot get the data from empty lazy")
48        }
49    }
50}
51
52
53impl<T> Deref for Lazy<T> {
54    type Target = T;
55
56    fn deref(&self) -> &Self::Target {
57        unsafe {
58            let data_ptr = &mut *self.data.get();
59            if data_ptr.is_none() {
60                if let Some(init_fn) = self.init {
61                    *data_ptr = Some(init_fn());
62                    data_ptr.as_ref().rart_expect("Cannot get the data from empty lazy")
63                } else {
64                    panic!("Init Fn in None");
65                }
66            } else {
67                data_ptr.as_ref().rart_expect("Cannot get the data from empty lazy")
68            }
69        }
70    }
71}