use core::{
error::Error,
fmt::{self, Display},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ConcurrentInitialization;
impl Display for ConcurrentInitialization {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "another init function is running concurrently")
}
}
impl Error for ConcurrentInitialization {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InitError<E> {
InitFunctionFailed(E),
ConcurrentInitialization,
}
impl<E> InitError<E> {
#[must_use]
pub fn init_function_error(self) -> Option<E> {
match self {
InitError::InitFunctionFailed(error) => Some(error),
InitError::ConcurrentInitialization => None,
}
}
}
impl<E: fmt::Display> fmt::Display for InitError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InitError::InitFunctionFailed(error) => write!(f, "the init function failed: {error}"),
InitError::ConcurrentInitialization => ConcurrentInitialization.fmt(f),
}
}
}
impl<E: Error + 'static> Error for InitError<E> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
InitError::InitFunctionFailed(error) => Some(error),
InitError::ConcurrentInitialization => None,
}
}
}
impl<E> From<ConcurrentInitialization> for InitError<E> {
fn from(_: ConcurrentInitialization) -> Self {
InitError::ConcurrentInitialization
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SetError<T> {
AlreadyInitialized(T),
ConcurrentInitialization(T),
}
impl<T> SetError<T> {
#[must_use]
pub fn into_rejected_value(self) -> T {
match self {
SetError::AlreadyInitialized(value) | SetError::ConcurrentInitialization(value) => {
value
}
}
}
}
impl<T> fmt::Debug for SetError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SetError::AlreadyInitialized(_) => f.write_str("SetError::AlreadyInitialized(..)"),
SetError::ConcurrentInitialization(_) => {
f.write_str("SetError::ConcurrentInitialization(..)")
}
}
}
}
impl<T> Display for SetError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SetError::AlreadyInitialized(_) => write!(f, "the cell is already initialized"),
SetError::ConcurrentInitialization(_) => ConcurrentInitialization.fmt(f),
}
}
}
impl<T> Error for SetError<T> {}
impl<T> From<InsertError<T>> for SetError<T> {
fn from(error: InsertError<T>) -> Self {
SetError::ConcurrentInitialization(error.into_rejected_value())
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct InsertError<T>(pub(crate) T);
impl<T> InsertError<T> {
#[must_use]
pub fn into_rejected_value(self) -> T {
self.0
}
}
impl<T> fmt::Debug for InsertError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("InsertError(..)")
}
}
impl<T> Display for InsertError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ConcurrentInitialization.fmt(f)
}
}
impl<T> Error for InsertError<T> {}