| 1 | use core::cell::UnsafeCell; | 
| 2 |  | 
|---|
| 3 | pub struct LazyCell<T> { | 
|---|
| 4 | contents: UnsafeCell<Option<T>>, | 
|---|
| 5 | } | 
|---|
| 6 | impl<T> LazyCell<T> { | 
|---|
| 7 | pub fn new() -> LazyCell<T> { | 
|---|
| 8 | LazyCell { | 
|---|
| 9 | contents: UnsafeCell::new(None), | 
|---|
| 10 | } | 
|---|
| 11 | } | 
|---|
| 12 |  | 
|---|
| 13 | pub fn borrow(&self) -> Option<&T> { | 
|---|
| 14 | unsafe { &*self.contents.get() }.as_ref() | 
|---|
| 15 | } | 
|---|
| 16 |  | 
|---|
| 17 | pub fn borrow_with(&self, closure: impl FnOnce() -> T) -> &T { | 
|---|
| 18 | // First check if we're already initialized... | 
|---|
| 19 | let ptr = self.contents.get(); | 
|---|
| 20 | if let Some(val) = unsafe { &*ptr } { | 
|---|
| 21 | return val; | 
|---|
| 22 | } | 
|---|
| 23 | // Note that while we're executing `closure` our `borrow_with` may | 
|---|
| 24 | // be called recursively. This means we need to check again after | 
|---|
| 25 | // the closure has executed. For that we use the `get_or_insert` | 
|---|
| 26 | // method which will only perform mutation if we aren't already | 
|---|
| 27 | // `Some`. | 
|---|
| 28 | let val = closure(); | 
|---|
| 29 | unsafe { (*ptr).get_or_insert(val) } | 
|---|
| 30 | } | 
|---|
| 31 | } | 
|---|
| 32 |  | 
|---|