use crate::cell::UnsafeCell; use crate::fmt; use crate::mem; /// A cell which can be written to only once. /// /// Unlike [`RefCell`], a `OnceCell` only provides shared `&T` references to its value. /// Unlike [`Cell`], a `OnceCell` doesn't require copying or replacing the value to access it. /// /// For a thread-safe version of this struct, see [`std::sync::OnceLock`]. /// /// [`RefCell`]: crate::cell::RefCell /// [`Cell`]: crate::cell::Cell /// [`std::sync::OnceLock`]: ../../std/sync/struct.OnceLock.html /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// let value: &String = cell.get_or_init(|| { /// "Hello, World!".to_string() /// }); /// assert_eq!(value, "Hello, World!"); /// assert!(cell.get().is_some()); /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub struct OnceCell { // Invariant: written to at most once. inner: UnsafeCell>, } impl OnceCell { /// Creates a new empty cell. #[inline] #[must_use] #[unstable(feature = "once_cell", issue = "74465")] pub const fn new() -> OnceCell { OnceCell { inner: UnsafeCell::new(None) } } /// Gets the reference to the underlying value. /// /// Returns `None` if the cell is empty. #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get(&self) -> Option<&T> { // SAFETY: Safe due to `inner`'s invariant unsafe { &*self.inner.get() }.as_ref() } /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_mut(&mut self) -> Option<&mut T> { self.inner.get_mut().as_mut() } /// Sets the contents of the cell to `value`. /// /// # Errors /// /// This method returns `Ok(())` if the cell was empty and `Err(value)` if /// it was full. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// assert_eq!(cell.set(92), Ok(())); /// assert_eq!(cell.set(62), Err(62)); /// /// assert!(cell.get().is_some()); /// ``` #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn set(&self, value: T) -> Result<(), T> { // SAFETY: Safe because we cannot have overlapping mutable borrows let slot = unsafe { &*self.inner.get() }; if slot.is_some() { return Err(value); } // SAFETY: This is the only place where we set the slot, no races // due to reentrancy/concurrency are possible, and we've // checked that slot is currently `None`, so this write // maintains the `inner`'s invariant. let slot = unsafe { &mut *self.inner.get() }; *slot = Some(value); Ok(()) } /// Gets the contents of the cell, initializing it with `f` /// if the cell was empty. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and the cell /// remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. Doing /// so results in a panic. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); /// let value = cell.get_or_init(|| 92); /// assert_eq!(value, &92); /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, { match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and the cell /// remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. Doing /// so results in a panic. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); /// assert!(cell.get().is_none()); /// let value = cell.get_or_try_init(|| -> Result { /// Ok(92) /// }); /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { if let Some(val) = self.get() { return Ok(val); } /// Avoid inlining the initialization closure into the common path that fetches /// the already initialized value #[cold] fn outlined_call(f: F) -> Result where F: FnOnce() -> Result, { f() } let val = outlined_call(f)?; // Note that *some* forms of reentrant initialization might lead to // UB (see `reentrant_init` test). I believe that just removing this // `assert`, while keeping `set/get` would be sound, but it seems // better to panic, rather than to silently use an old value. assert!(self.set(val).is_ok(), "reentrant init"); Ok(self.get().unwrap()) } /// Consumes the cell, returning the wrapped value. /// /// Returns `None` if the cell was empty. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::OnceCell; /// /// let cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.into_inner(), None); /// /// let cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies // that it is not currently borrowed. So it is safe to move out `Option`. self.inner.into_inner() } /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. /// /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. /// /// Safety is guaranteed by requiring a mutable reference. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::cell::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.take(), None); /// /// let mut cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn take(&mut self) -> Option { mem::take(self).into_inner() } } #[unstable(feature = "once_cell", issue = "74465")] impl Default for OnceCell { #[inline] fn default() -> Self { Self::new() } } #[unstable(feature = "once_cell", issue = "74465")] impl fmt::Debug for OnceCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { Some(v) => f.debug_tuple("OnceCell").field(v).finish(), None => f.write_str("OnceCell(Uninit)"), } } } #[unstable(feature = "once_cell", issue = "74465")] impl Clone for OnceCell { #[inline] fn clone(&self) -> OnceCell { let res = OnceCell::new(); if let Some(value) = self.get() { match res.set(value.clone()) { Ok(()) => (), Err(_) => unreachable!(), } } res } } #[unstable(feature = "once_cell", issue = "74465")] impl PartialEq for OnceCell { #[inline] fn eq(&self, other: &Self) -> bool { self.get() == other.get() } } #[unstable(feature = "once_cell", issue = "74465")] impl Eq for OnceCell {} #[unstable(feature = "once_cell", issue = "74465")] impl const From for OnceCell { /// Creates a new `OnceCell` which already contains the given `value`. #[inline] fn from(value: T) -> Self { OnceCell { inner: UnsafeCell::new(Some(value)) } } } // Just like for `Cell` this isn't needed, but results in nicer error messages. #[unstable(feature = "once_cell", issue = "74465")] impl !Sync for OnceCell {}