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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
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<i32> = 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, F = fn() -> T> {
cell: OnceCell<T>,
init: Cell<Option<F>>,
}
impl<T, F> LazyCell<T, F> {
/// 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!");
/// ```
#[unstable(feature = "once_cell", issue = "74465")]
pub const fn new(init: F) -> LazyCell<T, F> {
LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) }
}
}
impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// 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);
/// ```
#[unstable(feature = "once_cell", issue = "74465")]
pub fn force(this: &LazyCell<T, F>) -> &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, F: FnOnce() -> T> Deref for LazyCell<T, F> {
type Target = T;
fn deref(&self) -> &T {
LazyCell::force(self)
}
}
#[unstable(feature = "once_cell", issue = "74465")]
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)
}
}
#[unstable(feature = "once_cell", issue = "74465")]
impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
}
}