1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use std::ops::Deref;
use std::panic::{UnwindSafe, RefUnwindSafe};
use std::cell::Cell;
use std::mem::MaybeUninit;

/// A memory cell which is initialized on the first access
pub struct LazyCell<T, F = fn() -> T> {
    cell: Cell<Option<T>>,
    init: Cell<Option<F>>,
}

unsafe impl<T, F: Send> Sync for LazyCell<T, F> where MaybeUninit<T>: Sync {}
impl<T, F: UnwindSafe> RefUnwindSafe for LazyCell<T, F> where Cell<T>: RefUnwindSafe {}
impl<T, F: UnwindSafe> UnwindSafe for LazyCell<T, F> where Cell<T>: UnwindSafe {}

impl<T, F> LazyCell<T, F> {
    /// Creates a new lazy value with the given initializing function.
    pub const fn new(f: F) -> LazyCell<T, F> {
        LazyCell { cell: Cell::new(None), init: Cell::new(Some(f)) }
    }
}

impl<T, F: FnOnce() -> T> LazyCell<T, F> {
    #[inline]
    #[track_caller]
    pub fn force(this: &LazyCell<T, F>) -> &T {
        let cell = unsafe { &mut *this.cell.as_ptr() };
        if cell.is_none() {
            match this.init.take() {
                Some(f) => *cell = Some(f()),
                None => panic!("Lazy instance has previously been poisoned"),
            }
        }
        cell.as_ref().unwrap()
    }
}

impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
    type Target = T;
    
    #[track_caller]
    fn deref(&self) -> &T {
        Self::force(self)
    }
}

impl<T: Default> Default for LazyCell<T> {
    /// Creates a new lazy value using `Default` as the initializing function.
    fn default() -> LazyCell<T> {
        LazyCell::new(T::default)
    }
}