//! Provides `Once`, `OnceState`, `OnceLock`12pub use implementation::{Once, OnceLock, OnceState};34#[cfg(feature = "std")]5use std::sync as implementation;67#[cfg(not(feature = "std"))]8mod implementation {9use core::{10fmt,11panic::{RefUnwindSafe, UnwindSafe},12};1314/// Fallback implementation of `OnceLock` from the standard library.15pub struct OnceLock<T> {16inner: spin::Once<T>,17}1819impl<T> OnceLock<T> {20/// Creates a new empty cell.21///22/// See the standard library for further details.23#[must_use]24pub const fn new() -> Self {25Self {26inner: spin::Once::new(),27}28}2930/// Gets the reference to the underlying value.31///32/// See the standard library for further details.33pub fn get(&self) -> Option<&T> {34self.inner.get()35}3637/// Gets the mutable reference to the underlying value.38///39/// See the standard library for further details.40pub fn get_mut(&mut self) -> Option<&mut T> {41self.inner.get_mut()42}4344/// Sets the contents of this cell to `value`.45///46/// See the standard library for further details.47pub fn set(&self, value: T) -> Result<(), T> {48let mut value = Some(value);4950self.inner.call_once(|| value.take().unwrap());5152match value {53Some(value) => Err(value),54None => Ok(()),55}56}5758/// Gets the contents of the cell, initializing it with `f` if the cell59/// was empty.60///61/// See the standard library for further details.62pub fn get_or_init<F>(&self, f: F) -> &T63where64F: FnOnce() -> T,65{66self.inner.call_once(f)67}6869/// Consumes the `OnceLock`, returning the wrapped value. Returns70/// `None` if the cell was empty.71///72/// See the standard library for further details.73pub fn into_inner(mut self) -> Option<T> {74self.take()75}7677/// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.78///79/// See the standard library for further details.80pub fn take(&mut self) -> Option<T> {81if self.inner.is_completed() {82let mut inner = spin::Once::new();8384core::mem::swap(&mut self.inner, &mut inner);8586inner.try_into_inner()87} else {88None89}90}91}9293impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}94impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}9596impl<T> Default for OnceLock<T> {97fn default() -> OnceLock<T> {98OnceLock::new()99}100}101102impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {103fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {104let mut d = f.debug_tuple("OnceLock");105match self.get() {106Some(v) => d.field(v),107None => d.field(&format_args!("<uninit>")),108};109d.finish()110}111}112113impl<T: Clone> Clone for OnceLock<T> {114fn clone(&self) -> OnceLock<T> {115let cell = Self::new();116if let Some(value) = self.get() {117cell.set(value.clone()).ok().unwrap();118}119cell120}121}122123impl<T> From<T> for OnceLock<T> {124fn from(value: T) -> Self {125let cell = Self::new();126cell.set(value).map(move |_| cell).ok().unwrap()127}128}129130impl<T: PartialEq> PartialEq for OnceLock<T> {131fn eq(&self, other: &OnceLock<T>) -> bool {132self.get() == other.get()133}134}135136impl<T: Eq> Eq for OnceLock<T> {}137138/// Fallback implementation of `Once` from the standard library.139pub struct Once {140inner: OnceLock<()>,141}142143impl Once {144/// Creates a new `Once` value.145///146/// See the standard library for further details.147#[expect(clippy::new_without_default, reason = "matching std::sync::Once")]148pub const fn new() -> Self {149Self {150inner: OnceLock::new(),151}152}153154/// Performs an initialization routine once and only once. The given closure155/// will be executed if this is the first time `call_once` has been called,156/// and otherwise the routine will *not* be invoked.157///158/// See the standard library for further details.159pub fn call_once<F: FnOnce()>(&self, f: F) {160self.inner.get_or_init(f);161}162163/// Performs the same function as [`call_once()`] except ignores poisoning.164///165/// See the standard library for further details.166pub fn call_once_force<F: FnOnce(&OnceState)>(&self, f: F) {167const STATE: OnceState = OnceState { _private: () };168169self.call_once(move || f(&STATE));170}171172/// Returns `true` if some [`call_once()`] call has completed173/// successfully. Specifically, `is_completed` will return false in174/// the following situations:175/// * [`call_once()`] was not called at all,176/// * [`call_once()`] was called, but has not yet completed,177/// * the [`Once`] instance is poisoned178///179/// See the standard library for further details.180pub fn is_completed(&self) -> bool {181self.inner.get().is_some()182}183}184185impl RefUnwindSafe for Once {}186impl UnwindSafe for Once {}187188impl fmt::Debug for Once {189fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {190f.debug_struct("Once").finish_non_exhaustive()191}192}193194/// Fallback implementation of `OnceState` from the standard library.195pub struct OnceState {196_private: (),197}198199impl OnceState {200/// Returns `true` if the associated [`Once`] was poisoned prior to the201/// invocation of the closure passed to [`Once::call_once_force()`].202///203/// See the standard library for further details.204pub fn is_poisoned(&self) -> bool {205false206}207}208209impl fmt::Debug for OnceState {210fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {211f.debug_struct("OnceState")212.field("poisoned", &self.is_poisoned())213.finish()214}215}216}217218219