use crate::cell::{Cell, OnceCell}; use crate::fmt; use crate::ops::Deref; /// A value which is initialized on the first access. /// /// For a thread-safe version of this struct, see [`std::sync::LazyLock`]. /// /// [`std::sync::LazyLock`]: ../../std/sync/struct.LazyLock.html /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::LazyCell; /// /// let lazy: LazyCell = LazyCell::new(|| { /// println!("initializing"); /// 92 /// }); /// println!("ready"); /// println!("{}", *lazy); /// println!("{}", *lazy); /// /// // Prints: /// // ready /// // initializing /// // 92 /// // 92 /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub struct LazyCell T> { cell: OnceCell, init: Cell>, } impl T> LazyCell { /// Creates a new lazy value with the given initializing function. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::LazyCell; /// /// let hello = "Hello, World!".to_string(); /// /// let lazy = LazyCell::new(|| hello.to_uppercase()); /// /// assert_eq!(&*lazy, "HELLO, WORLD!"); /// ``` #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub const fn new(init: F) -> LazyCell { LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) } } /// Forces the evaluation of this lazy value and returns a reference to /// the result. /// /// This is equivalent to the `Deref` impl, but is explicit. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::LazyCell; /// /// let lazy = LazyCell::new(|| 92); /// /// assert_eq!(LazyCell::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn force(this: &LazyCell) -> &T { this.cell.get_or_init(|| match this.init.take() { Some(f) => f(), None => panic!("`Lazy` instance has previously been poisoned"), }) } } #[unstable(feature = "once_cell", issue = "74465")] impl T> Deref for LazyCell { type Target = T; #[inline] fn deref(&self) -> &T { LazyCell::force(self) } } #[unstable(feature = "once_cell", issue = "74465")] impl Default for LazyCell { /// Creates a new lazy value using `Default` as the initializing function. #[inline] fn default() -> LazyCell { LazyCell::new(T::default) } } #[unstable(feature = "once_cell", issue = "74465")] impl fmt::Debug for LazyCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() } }