use core::fmt::Display;
use crate::{
any::{
AnyTrait, BorrowedMutStatic, BorrowedMutStaticHrt, BorrowedStatic, BorrowedStaticHrt,
OwnedStatic, TempBorrowedMutStatic, TempBorrowedMutStaticHrt, TempBorrowedStatic,
TempBorrowedStaticHrt,
},
any_trait,
effect::{Effect, EffectExt as _, Effective as _, EffectiveExt as _, ErasedEffective, Ss},
hkt::Marker,
protocol::{
visitor::{
EffectiveVisitExt as _, RequestHint, RequestHintProto, Value, ValueProto, VisitResult,
},
walker::hint::hint_protocol,
DynVisitor, DynWalker,
},
Flow,
};
#[non_exhaustive]
pub struct ValueError<T>(Marker<T>);
impl<T> ::core::fmt::Debug for ValueError<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "missing value of type `{}`", core::any::type_name::<T>())
}
}
impl<T> Display for ValueError<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "missing value of type `{}`", core::any::type_name::<T>())
}
}
pub enum Cloneable {}
pub enum NotCloneable {}
/// Builder for `'static` values.
///
/// This builder only uses the [`Value`] protocol.
///
#[doc = crate::doc_macro::mermaid!("value.mmd", 100)]
///
/// After
pub struct ValueBuilder<T, Clone, E> {
value: Option<T>,
_marker: Marker<(E, Clone)>,
}
impl<T: Ss, Clone, E> crate::BuilderTypes for ValueBuilder<T, Clone, E> {
type Error = ValueError<T>;
type Value = T;
type Seed = ();
}
impl<'ctx, T: Ss + 'static, Clone, E: Effect> crate::Builder<'ctx, E> for ValueBuilder<T, Clone, E>
where
Self: AnyTrait<'ctx>,
{
fn build<'a>(self) -> ErasedEffective<'a, Result<Self::Value, Self::Error>, E>
where
Self: 'a,
{
E::ready(self.value.ok_or(ValueError(Default::default())))
}
fn from_seed<'a>(_seed: Self::Seed) -> ErasedEffective<'a, Self, E>
where
Self: 'a,
{
E::ready(Self {
value: None,
_marker: Default::default(),
})
}
fn as_visitor(&mut self) -> DynVisitor<'_, 'ctx> {
DynVisitor(self)
}
}
any_trait! {
impl['ctx, T, E] ValueBuilder<T, NotCloneable, E> = [
RequestHintProto<E>,
ValueProto<OwnedStatic<T>, E>,
] where
E: Effect,
T: Ss + 'static
}
any_trait! {
impl['ctx, T, E] ValueBuilder<T, Cloneable, E> = [
RequestHintProto<E>,
ValueProto<OwnedStatic<T>, E>,
ValueProto<BorrowedStaticHrt<T>, E>,
ValueProto<TempBorrowedStaticHrt<T>, E>,
ValueProto<BorrowedMutStaticHrt<T>, E>,
ValueProto<TempBorrowedMutStaticHrt<T>, E>,
] where
E: Effect,
T: Ss + 'static + Clone,
}
impl<'ctx, T: Ss + 'static, E: Effect> RequestHint<'ctx, E> for ValueBuilder<T, NotCloneable, E> {
fn request_hint<'this: 'e, 'walker: 'e, 'e>(
&'this mut self,
walker: DynWalker<'walker, 'ctx>,
) -> ErasedEffective<'e, VisitResult, E>
where
'ctx: 'this + 'walker,
{
E::as_ctx((self, walker), |(this, walker)| {
hint_protocol::<ValueProto<OwnedStatic<T>, E>, _>(walker.cast(), *this, ()).cast()
})
.remove_ctx()
}
}
impl<'ctx, T: Ss + 'static, E: Effect> RequestHint<'ctx, E> for ValueBuilder<T, Cloneable, E>
where
T: Clone,
{
fn request_hint<'this: 'e, 'walker: 'e, 'e>(
&'this mut self,
walker: DynWalker<'walker, 'ctx>,
) -> ErasedEffective<'e, VisitResult, E>
where
'ctx: 'this + 'walker,
{
E::as_ctx((self, walker), |(this, walker)| {
hint_protocol::<ValueProto<OwnedStatic<T>, E>, _>(walker.cast(), *this, ()).cast()
})
.if_not_finished(|(this, walker)| {
hint_protocol::<ValueProto<BorrowedStaticHrt<T>, E>, _>(walker.cast(), *this, ()).cast()
})
.if_not_finished(|(this, walker)| {
hint_protocol::<ValueProto<TempBorrowedStaticHrt<T>, E>, _>(walker.cast(), *this, ())
.cast()
})
.if_not_finished(|(this, walker)| {
hint_protocol::<ValueProto<BorrowedMutStaticHrt<T>, E>, _>(walker.cast(), *this, ())
.cast()
})
.if_not_finished(|(this, walker)| {
hint_protocol::<ValueProto<TempBorrowedMutStaticHrt<T>, E>, _>(walker.cast(), *this, ())
.cast()
})
.remove_ctx()
}
}
impl<'ctx, T: Ss + 'static, Clone, E: Effect> Value<'ctx, OwnedStatic<T>, E>
for ValueBuilder<T, Clone, E>
{
fn visit<'a>(
&'a mut self,
OwnedStatic(value): OwnedStatic<T>,
) -> ErasedEffective<'a, VisitResult<OwnedStatic<T>>, E>
where
'ctx: 'a,
{
self.value = Some(value);
E::ready(Flow::Done.into())
}
}
impl<'ctx, T: Ss + 'static, E: Effect> Value<'ctx, BorrowedStaticHrt<T>, E>
for ValueBuilder<T, Cloneable, E>
where
T: Clone,
{
fn visit<'a>(
&'a mut self,
BorrowedStatic(value): BorrowedStatic<'ctx, T>,
) -> ErasedEffective<'a, VisitResult<BorrowedStatic<'ctx, T>>, E>
where
'ctx: 'a,
{
self.value = Some(value.clone());
E::ready(Flow::Done.into())
}
}
impl<'ctx, T: Ss + 'static, E: Effect> Value<'ctx, TempBorrowedStaticHrt<T>, E>
for ValueBuilder<T, Cloneable, E>
where
T: Clone,
{
fn visit<'a>(
&'a mut self,
TempBorrowedStatic(value): TempBorrowedStatic<'a, T>,
) -> ErasedEffective<'a, VisitResult<TempBorrowedStatic<'a, T>>, E>
where
'ctx: 'a,
{
self.value = Some(value.clone());
E::ready(Flow::Done.into())
}
}
impl<'ctx, T: Ss + 'static, E: Effect> Value<'ctx, BorrowedMutStaticHrt<T>, E>
for ValueBuilder<T, Cloneable, E>
where
T: Clone,
{
fn visit<'a>(
&'a mut self,
BorrowedMutStatic(value): BorrowedMutStatic<'ctx, T>,
) -> ErasedEffective<'a, VisitResult<BorrowedMutStatic<'ctx, T>>, E>
where
'ctx: 'a,
{
self.value = Some(value.clone());
E::ready(Flow::Done.into())
}
}
impl<'ctx, T: Ss + 'static, E: Effect> Value<'ctx, TempBorrowedMutStaticHrt<T>, E>
for ValueBuilder<T, Cloneable, E>
where
T: Clone,
{
fn visit<'a>(
&'a mut self,
TempBorrowedMutStatic(value): TempBorrowedMutStatic<'a, T>,
) -> ErasedEffective<'a, VisitResult<TempBorrowedMutStatic<'a, T>>, E>
where
'ctx: 'a,
{
self.value = Some(value.clone());
E::ready(Flow::Done.into())
}
}