use core::{convert::Infallible, fmt::Debug, marker::PhantomData, result};
use crate::{Error, raw::RawVacant};
pub trait State: Debug + Send + Sync + 'static {
type Repr: Debug + Send + Sync + 'static;
fn into_repr(self) -> Self::Repr
where
Self: Sized;
fn from_repr(state: Self::Repr) -> Self
where
Self: Sized;
fn from_repr_ref(state: &Self::Repr) -> &Self
where
Self: Sized;
}
impl<T> State for T
where
T: Debug + Send + Sync + 'static,
{
type Repr = T;
fn into_repr(self) -> Self::Repr {
self
}
fn from_repr(this: Self::Repr) -> Self
where
Self: Sized,
{
this
}
fn from_repr_ref(this: &Self::Repr) -> &Self
where
Self: Sized,
{
this
}
}
#[derive(Debug)]
pub struct Stateless(#[allow(unused)] [()]);
impl State for Stateless {
type Repr = Infallible;
}
pub struct Vacant<S>
where
S: State,
{
inner: Option<RawVacant>,
_marker: PhantomData<S>,
}
impl<S> Vacant<S>
where
S: State,
{
pub(crate) fn new(vacant: Option<RawVacant>) -> Self {
Self {
inner: vacant,
_marker: PhantomData,
}
}
pub fn with_state(self, state: S) -> Error<S> {
let Some(vacant) = self.inner else {
return Error::from_state(state);
};
let err = vacant
.try_with_state(S::into_repr(state))
.expect("Vacant must be created with correct state storage type");
Error(err)
}
pub fn try_into_stateless(self) -> result::Result<Error, Self> {
let Some(vacant) = self.inner else {
return Err(Self::new(None));
};
match vacant.try_into_stateless() {
Ok(err) => Ok(Error(err)),
Err(err) => Err(Self::new(Some(err))),
}
}
}
impl<S> Debug for Vacant<S>
where
S: State,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let Some(vacant) = &self.inner else {
return write!(f, "Vacant");
};
Debug::fmt(vacant, f)
}
}