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 53 54 55
//! A lazily fill Cell, but with frozen contents. //! //! With a `RefCell`, the inner contents cannot be borrowed for the lifetime of //! the entire object, but only of the borrows returned. A `LazyCell` is a //! variation on `RefCell` which allows borrows tied to the lifetime of the //! outer object. //! //! The limitation of a `LazyCell` is that after initialized, it can never be //! modified. use std::cell::UnsafeCell; pub struct LazyCell<T> { inner: UnsafeCell<Option<T>>, } impl<T> LazyCell<T> { /// Creates a new empty lazy cell. pub fn new(init: Option<T>) -> LazyCell<T> { LazyCell { inner: UnsafeCell::new(init) } } /// Put a value into this cell. /// /// This function will fail if the cell has already been filled. pub fn fill(&self, t: T) -> Result<(), T> { unsafe { let slot = self.inner.get(); if (*slot).is_none() { *slot = Some(t); Ok(()) } else { Err(t) } } } /// Borrows the contents of this lazy cell for the duration of the cell /// itself. /// /// This function will return `Some` if the cell has been previously /// initialized, and `None` if it has not yet been initialized. pub fn borrow(&self) -> Option<&T> { unsafe { (*self.inner.get()).as_ref() } } /// Consumes this `LazyCell`, returning the underlying value. pub fn into_inner(self) -> Option<T> { unsafe { self.inner.into_inner() } } }