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
13unsafe 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 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 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}