1 | #[cfg (feature = "std" )] |
2 | pub(crate) use once_cell::sync::Lazy; |
3 | |
4 | #[cfg (not(feature = "std" ))] |
5 | pub(crate) use self::spin::Lazy; |
6 | |
7 | #[cfg (not(feature = "std" ))] |
8 | mod spin { |
9 | //! This is the `once_cell::sync::Lazy` type, but modified to use our |
10 | //! `spin::Once` type rather than `OnceCell`. This is used to replace |
11 | //! `once_cell::sync::Lazy` on `no-std` builds. |
12 | use crate::spin::Once; |
13 | use core::{cell::Cell, fmt, ops::Deref}; |
14 | |
15 | /// Re-implementation of `once_cell::sync::Lazy` on top of `spin::Once` |
16 | /// rather than `OnceCell`. |
17 | /// |
18 | /// This is used when the standard library is disabled. |
19 | pub(crate) struct Lazy<T, F = fn() -> T> { |
20 | cell: Once<T>, |
21 | init: Cell<Option<F>>, |
22 | } |
23 | |
24 | impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> { |
25 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
26 | f.debug_struct("Lazy" ) |
27 | .field("cell" , &self.cell) |
28 | .field("init" , &".." ) |
29 | .finish() |
30 | } |
31 | } |
32 | |
33 | // We never create a `&F` from a `&Lazy<T, F>` so it is fine to not impl |
34 | // `Sync` for `F`. We do create a `&mut Option<F>` in `force`, but this is |
35 | // properly synchronized, so it only happens once so it also does not |
36 | // contribute to this impl. |
37 | unsafe impl<T, F: Send> Sync for Lazy<T, F> where Once<T>: Sync {} |
38 | // auto-derived `Send` impl is OK. |
39 | |
40 | impl<T, F> Lazy<T, F> { |
41 | /// Creates a new lazy value with the given initializing function. |
42 | pub(crate) const fn new(init: F) -> Lazy<T, F> { |
43 | Lazy { |
44 | cell: Once::new(), |
45 | init: Cell::new(Some(init)), |
46 | } |
47 | } |
48 | } |
49 | |
50 | impl<T, F: FnOnce() -> T> Lazy<T, F> { |
51 | /// Forces the evaluation of this lazy value and returns a reference to |
52 | /// the result. |
53 | /// |
54 | /// This is equivalent to the `Deref` impl, but is explicit. |
55 | pub(crate) fn force(this: &Lazy<T, F>) -> &T { |
56 | this.cell.call_once(|| match this.init.take() { |
57 | Some(f) => f(), |
58 | None => panic!("Lazy instance has previously been poisoned" ), |
59 | }) |
60 | } |
61 | } |
62 | |
63 | impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { |
64 | type Target = T; |
65 | fn deref(&self) -> &T { |
66 | Lazy::force(self) |
67 | } |
68 | } |
69 | |
70 | impl<T: Default> Default for Lazy<T> { |
71 | /// Creates a new lazy value using `Default` as the initializing function. |
72 | fn default() -> Lazy<T> { |
73 | Lazy::new(T::default) |
74 | } |
75 | } |
76 | } |
77 | |