#![no_std]
#![warn(unsafe_op_in_unsafe_fn)]
mod imp;
use core::{
cell::Cell,
fmt, mem,
ops::{Deref, DerefMut},
panic::RefUnwindSafe,
};
use imp::OnceCell as Imp;
use lock_api::RawMutex;
pub struct OnceCell<R, T>(Imp<R, T>);
impl<R: RawMutex, T> Default for OnceCell<R, T> {
fn default() -> Self {
Self::new()
}
}
impl<R: RawMutex, T: fmt::Debug> fmt::Debug for OnceCell<R, T> {
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)"),
}
}
}
impl<R: RawMutex, T: Clone> Clone for OnceCell<R, T> {
fn clone(&self) -> Self {
match self.get() {
Some(value) => Self::with_value(value.clone()),
None => Self::new(),
}
}
fn clone_from(&mut self, source: &Self) {
match (self.get_mut(), source.get()) {
(Some(this), Some(source)) => this.clone_from(source),
_ => *self = source.clone(),
}
}
}
impl<R: RawMutex, T> From<T> for OnceCell<R, T> {
fn from(value: T) -> Self {
Self::with_value(value)
}
}
impl<R: RawMutex, T: PartialEq> PartialEq for OnceCell<R, T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<R: RawMutex, T: Eq> Eq for OnceCell<R, T> {}
impl<R: RawMutex, T> OnceCell<R, T> {
pub const fn new() -> Self {
Self(Imp::new())
}
pub const fn with_value(value: T) -> Self {
Self(Imp::with_value(value))
}
pub fn get(&self) -> Option<&T> {
if self.0.is_initialized() {
Some(unsafe { self.get_unchecked() })
} else {
None
}
}
#[inline]
pub fn get_mut(&mut self) -> Option<&mut T> {
self.0.get_mut()
}
#[inline]
pub unsafe fn get_unchecked(&self) -> &T {
unsafe { self.0.get_unchecked() }
}
pub fn set(&self, value: T) -> Result<(), T> {
match self.try_insert(value) {
Ok(_) => Ok(()),
Err((_, value)) => Err(value),
}
}
pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
let mut value = Some(value);
let res = self.get_or_init(|| unsafe { value.take().unwrap_unchecked() });
match value {
None => Ok(res),
Some(value) => Err((res, value)),
}
}
pub fn get_or_init<F>(&self, f: F) -> &T
where
F: FnOnce() -> T,
{
enum Void {}
match self.get_or_try_init(|| Ok::<T, Void>(f())) {
Ok(val) => val,
Err(void) => match void {},
}
}
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
where
F: FnOnce() -> Result<T, E>,
{
if let Some(value) = self.get() {
return Ok(value);
}
self.0.initialize(f)?;
debug_assert!(self.0.is_initialized());
Ok(unsafe { self.get_unchecked() })
}
pub fn take(&mut self) -> Option<T> {
mem::take(self).into_inner()
}
#[inline]
pub fn into_inner(self) -> Option<T> {
self.0.into_inner()
}
}
pub struct Lazy<R, T, F = fn() -> T> {
cell: OnceCell<R, T>,
init: Cell<Option<F>>,
}
impl<R: RawMutex, T: fmt::Debug, F> fmt::Debug for Lazy<R, T, F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Lazy")
.field("cell", &self.cell)
.field("init", &"..")
.finish()
}
}
unsafe impl<R, T, F: Send> Sync for Lazy<R, T, F> where OnceCell<R, T>: Sync {}
impl<R, T, F: RefUnwindSafe> RefUnwindSafe for Lazy<R, T, F> where OnceCell<R, T>: RefUnwindSafe {}
impl<R: RawMutex, T, F> Lazy<R, T, F> {
pub const fn new(f: F) -> Self {
Self {
cell: OnceCell::new(),
init: Cell::new(Some(f)),
}
}
pub fn into_value(this: Lazy<R, T, F>) -> Result<T, F> {
let cell = this.cell;
let init = this.init;
cell.into_inner().ok_or_else(|| {
init.take()
.unwrap_or_else(|| panic!("Lazy instance has previously been poisoned"))
})
}
}
impl<R: RawMutex, T, F: FnOnce() -> T> Lazy<R, T, F> {
pub fn force(this: &Self) -> &T {
this.cell.get_or_init(|| match this.init.take() {
Some(f) => f(),
None => panic!("Lazy instance has previously been poisoned"),
})
}
pub fn force_mut(this: &mut Self) -> &mut T {
Self::force(this);
Self::get_mut(this).unwrap_or_else(|| unreachable!())
}
pub fn get(this: &Self) -> Option<&T> {
this.cell.get()
}
pub fn get_mut(this: &mut Self) -> Option<&mut T> {
this.cell.get_mut()
}
}
impl<R: RawMutex, T, F: FnOnce() -> T> Deref for Lazy<R, T, F> {
type Target = T;
fn deref(&self) -> &T {
Self::force(self)
}
}
impl<R: RawMutex, T, F: FnOnce() -> T> DerefMut for Lazy<R, T, F> {
fn deref_mut(&mut self) -> &mut T {
Self::force(self);
self.cell.get_mut().unwrap_or_else(|| unreachable!())
}
}
impl<R: RawMutex, T: Default> Default for Lazy<R, T> {
fn default() -> Self {
Self::new(T::default)
}
}
fn _dummy() {}