]>
Commit | Line | Data |
---|---|---|
923072b8 FG |
1 | use crate::cell::{Cell, OnceCell}; |
2 | use crate::fmt; | |
3 | use crate::ops::Deref; | |
4 | ||
5 | /// A value which is initialized on the first access. | |
6 | /// | |
487cf647 FG |
7 | /// For a thread-safe version of this struct, see [`std::sync::LazyLock`]. |
8 | /// | |
9 | /// [`std::sync::LazyLock`]: ../../std/sync/struct.LazyLock.html | |
10 | /// | |
923072b8 FG |
11 | /// # Examples |
12 | /// | |
13 | /// ``` | |
14 | /// #![feature(once_cell)] | |
15 | /// | |
16 | /// use std::cell::LazyCell; | |
17 | /// | |
18 | /// let lazy: LazyCell<i32> = LazyCell::new(|| { | |
19 | /// println!("initializing"); | |
20 | /// 92 | |
21 | /// }); | |
22 | /// println!("ready"); | |
23 | /// println!("{}", *lazy); | |
24 | /// println!("{}", *lazy); | |
25 | /// | |
26 | /// // Prints: | |
27 | /// // ready | |
28 | /// // initializing | |
29 | /// // 92 | |
30 | /// // 92 | |
31 | /// ``` | |
32 | #[unstable(feature = "once_cell", issue = "74465")] | |
33 | pub struct LazyCell<T, F = fn() -> T> { | |
34 | cell: OnceCell<T>, | |
35 | init: Cell<Option<F>>, | |
36 | } | |
37 | ||
f25598a0 | 38 | impl<T, F: FnOnce() -> T> LazyCell<T, F> { |
923072b8 FG |
39 | /// Creates a new lazy value with the given initializing function. |
40 | /// | |
41 | /// # Examples | |
42 | /// | |
43 | /// ``` | |
44 | /// #![feature(once_cell)] | |
45 | /// | |
46 | /// use std::cell::LazyCell; | |
47 | /// | |
48 | /// let hello = "Hello, World!".to_string(); | |
49 | /// | |
50 | /// let lazy = LazyCell::new(|| hello.to_uppercase()); | |
51 | /// | |
52 | /// assert_eq!(&*lazy, "HELLO, WORLD!"); | |
53 | /// ``` | |
f25598a0 | 54 | #[inline] |
923072b8 FG |
55 | #[unstable(feature = "once_cell", issue = "74465")] |
56 | pub const fn new(init: F) -> LazyCell<T, F> { | |
57 | LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) } | |
58 | } | |
923072b8 | 59 | |
923072b8 FG |
60 | /// Forces the evaluation of this lazy value and returns a reference to |
61 | /// the result. | |
62 | /// | |
63 | /// This is equivalent to the `Deref` impl, but is explicit. | |
64 | /// | |
65 | /// # Examples | |
66 | /// | |
67 | /// ``` | |
68 | /// #![feature(once_cell)] | |
69 | /// | |
70 | /// use std::cell::LazyCell; | |
71 | /// | |
72 | /// let lazy = LazyCell::new(|| 92); | |
73 | /// | |
74 | /// assert_eq!(LazyCell::force(&lazy), &92); | |
75 | /// assert_eq!(&*lazy, &92); | |
76 | /// ``` | |
f25598a0 | 77 | #[inline] |
923072b8 FG |
78 | #[unstable(feature = "once_cell", issue = "74465")] |
79 | pub fn force(this: &LazyCell<T, F>) -> &T { | |
80 | this.cell.get_or_init(|| match this.init.take() { | |
81 | Some(f) => f(), | |
82 | None => panic!("`Lazy` instance has previously been poisoned"), | |
83 | }) | |
84 | } | |
85 | } | |
86 | ||
87 | #[unstable(feature = "once_cell", issue = "74465")] | |
88 | impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { | |
89 | type Target = T; | |
f25598a0 | 90 | #[inline] |
923072b8 FG |
91 | fn deref(&self) -> &T { |
92 | LazyCell::force(self) | |
93 | } | |
94 | } | |
95 | ||
96 | #[unstable(feature = "once_cell", issue = "74465")] | |
97 | impl<T: Default> Default for LazyCell<T> { | |
98 | /// Creates a new lazy value using `Default` as the initializing function. | |
f25598a0 | 99 | #[inline] |
923072b8 FG |
100 | fn default() -> LazyCell<T> { |
101 | LazyCell::new(T::default) | |
102 | } | |
103 | } | |
104 | ||
105 | #[unstable(feature = "once_cell", issue = "74465")] | |
106 | impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> { | |
107 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
108 | f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() | |
109 | } | |
110 | } |