use core::fmt::Display;
use effectful::{
bound::{Dynamic, IsSync},
effective::{Canonical, Effective},
environment::Environment,
DynBind, SendSync,
};
use crate::{
any::{
type_name::{self, Raised},
AnyTrait, BorrowedMutStatic, BorrowedStatic, OwnedStatic, TempBorrowedMutStatic,
TempBorrowedStatic,
},
hkt::Marker,
protocol::{
visitor::{EffectiveVisitExt as _, RequestHint, Value, VisitResult},
walker::hint::hint_protocol,
AsVisitor, DynVisitor, DynWalker,
},
trait_by_id, Flow,
};
#[derive(SendSync)]
#[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
#[derive(SendSync)]
pub struct ValueBuilder<T, Clone, E> {
value: Option<T>,
_marker: Marker<(E, Clone)>,
}
impl<T, Clone, E: Environment> crate::build::BuilderTypes<E> for ValueBuilder<T, Clone, E>
where
T: DynBind<E>,
{
type Error = ValueError<T>;
type Output = T;
type Value = T;
type Seed = ();
fn unwrap_output(output: Self::Output) -> Self::Value {
output
}
}
impl<'src, T: 'static, Clone, E: Environment> crate::Builder<'src, E> for ValueBuilder<T, Clone, E>
where
T: DynBind<E>,
Self: AnyTrait<'src>,
{
fn build<'a>(self) -> Canonical<'a, Result<Self::Output, Self::Error>, E>
where
Self: 'a,
{
E::value(self.value.ok_or(ValueError(Default::default()))).cast()
}
fn from_seed<'a>(_seed: Self::Seed) -> Canonical<'a, Self, E>
where
Self: 'a,
{
E::value(Self {
value: None,
_marker: Default::default(),
})
.cast()
}
}
impl<'src, T: 'static, Clone, E: Environment> AsVisitor<'src, E> for ValueBuilder<T, Clone, E>
where
Self: AnyTrait<'src> + DynBind<E>,
{
fn as_visitor(&mut self) -> DynVisitor<'_, 'src, E> {
DynVisitor::new(self)
}
}
impl<'src, T: 'static, E: Environment> AnyTrait<'src> for ValueBuilder<T, NotCloneable, E>
where
Self: RequestHint<'src, E> + Value<'src, OwnedStatic<T>, E>,
{
fn upcast_by_id_mut(
&mut self,
id: crate::any::WithLtTypeId<'src>,
) -> Option<crate::any::MutAnyUnsized<'_, 'src>> {
trait_by_id!(&mut self, id, {
type Impls = (dyn RequestHint<'src, E>, dyn Value<'src, OwnedStatic<T>, E>);
});
None
}
}
impl<'src, T: 'static + Clone, E: Environment> AnyTrait<'src> for ValueBuilder<T, Cloneable, E>
where
T: DynBind<E> + IsSync<E::NeedSend>,
Self: Value<'src, OwnedStatic<T>, E>
+ Value<'src, Raised<'src, 'src, BorrowedStatic<'src, i32>>, E>,
{
fn upcast_by_id_mut(
&mut self,
id: crate::any::WithLtTypeId<'src>,
) -> Option<crate::any::MutAnyUnsized<'_, 'src>> {
trait_by_id!(&mut self, id, {
type Impls = (
dyn RequestHint<'src, E>,
dyn Value<'src, OwnedStatic<T>, E>,
dyn Value<'_, Raised<'_, '_, BorrowedStatic<'_, T>>, E>,
dyn Value<'_, Raised<'_, '_, TempBorrowedStatic<'_, T>>, E>,
);
});
None
}
}
impl<'src, T: 'static, E: Environment> RequestHint<'src, E> for ValueBuilder<T, NotCloneable, E>
where
T: DynBind<E>,
T: IsSync<E::NeedSend>,
{
fn request_hint<'r>(
&'r mut self,
walker: DynWalker<'r, 'src, E>,
) -> Canonical<'r, VisitResult, E> {
E::value((self, walker))
.update_map((), |_, (this, walker)| {
hint_protocol::<dyn Value<'_, OwnedStatic<T>, E>, _, _>(walker.cast(), *this, ())
.cast()
})
.map((), |_, (_, x)| x)
.cast()
}
}
impl<'src, T: 'static, E: Environment> RequestHint<'src, E> for ValueBuilder<T, Cloneable, E>
where
T: Clone + DynBind<E> + IsSync<E::NeedSend>,
Self: AnyTrait<'src>,
{
fn request_hint<'r>(
&'r mut self,
walker: DynWalker<'r, 'src, E>,
) -> Canonical<'r, VisitResult, E> {
E::value((self, walker))
.update_map((), |_, (this, walker)| {
hint_protocol::<dyn Value<'_, OwnedStatic<T>, E>, _, _>(walker.cast(), *this, ())
.cast()
})
.cast::<()>()
.if_not_finished((), |_, (this, walker)| {
hint_protocol::<
dyn Value<'_, type_name::Raised<'_, '_, BorrowedStatic<'_, T>>, E>,
_,
_,
>(walker.cast(), *this, ())
.cast()
})
.cast::<()>()
.if_not_finished((), |_, (this, walker)| {
hint_protocol::<
dyn Value<'_, type_name::Raised<'_, '_, TempBorrowedStatic<'_, T>>, E>,
_,
_,
>(walker.cast(), *this, ())
.cast()
})
.cast::<()>()
.if_not_finished((), |_, (this, walker)| {
hint_protocol::<
dyn Value<'_, type_name::Raised<'_, '_, BorrowedMutStatic<'_, T>>, E>,
_,
_,
>(walker.cast(), *this, ())
.cast()
})
.cast::<()>()
.if_not_finished((), |_, (this, walker)| {
hint_protocol::<
dyn Value<'_, type_name::Raised<'_, '_, TempBorrowedMutStatic<'_, T>>, E>,
_,
_,
>(walker.cast(), *this, ())
.cast()
})
.map((), |_, (_, x)| x)
.cast()
}
}
impl<'src, T: 'static, Clone, E: Environment> Value<'src, OwnedStatic<T>, E>
for ValueBuilder<T, Clone, E>
where
T: DynBind<E>,
{
fn visit<'r>(
&'r mut self,
value: type_name::Lowered<'r, 'src, OwnedStatic<T>>,
) -> Canonical<'r, VisitResult<type_name::Lowered<'r, 'src, OwnedStatic<T>>>, E>
where
type_name::Lowered<'r, 'src, OwnedStatic<T>>: Sized + DynBind<E>,
{
self.value = Some(value.0);
E::value(Flow::Done.into()).cast()
}
}
impl<'src, T: 'static, E: Environment>
Value<'src, type_name::Raised<'src, 'src, BorrowedStatic<'src, T>>, E>
for ValueBuilder<T, Cloneable, E>
where
T: DynBind<E> + Clone,
{
fn visit<'r>(
&'r mut self,
value: type_name::Lowered<'r, 'src, type_name::Raised<'r, 'src, BorrowedStatic<'src, T>>>,
) -> Canonical<
'r,
VisitResult<
type_name::Lowered<'r, 'src, type_name::Raised<'r, 'src, BorrowedStatic<'src, T>>>,
>,
E,
>
where
type_name::Lowered<'r, 'src, type_name::Raised<'r, 'src, BorrowedStatic<'src, T>>>:
Sized + DynBind<E>,
{
self.value = Some(value.0.clone());
E::value(Flow::Done.into()).cast()
}
}
impl<'ctx, T: 'static, E: Environment>
Value<'ctx, type_name::Raised<'ctx, 'ctx, TempBorrowedStatic<'ctx, T>>, E>
for ValueBuilder<T, Cloneable, E>
where
T: Clone + DynBind<E>,
{
fn visit<'a>(
&'a mut self,
TempBorrowedStatic(value): TempBorrowedStatic<'a, T>,
) -> Canonical<'a, VisitResult<TempBorrowedStatic<'a, T>>, E>
where
'ctx: 'a,
TempBorrowedStatic<'a, T>: DynBind<E>,
{
self.value = Some(value.clone());
E::value(Flow::Done.into()).cast()
}
}
// impl<'ctx, T: 'static, E: Environment> Value<'ctx, BorrowedMutStatic<'ctx, T>, E>
// for ValueBuilder<T, Cloneable, E>
// where
// T: Clone,
// Dynamic<T>: DynBind<E>,
// Dynamic<BorrowedMutStatic<'ctx, T>>: DynBind<E>,
// {
// fn visit<'a>(
// &'a mut self,
// BorrowedMutStatic(value): BorrowedMutStatic<'ctx, T>,
// ) -> Canonical<'a, VisitResult<Dynamic<BorrowedMutStatic<'ctx, T>>>, E>
// where
// 'ctx: 'a,
// {
// self.value = Some(Dynamic(value.clone()));
//
// E::value(Flow::Done.into()).cast()
// }
// }
//
// impl<'ctx, T: 'static, E: Environment>
// Value<'ctx, type_name::Raised<'static, 'ctx, BorrowedMutStatic<'static, T>>, E>
// for ValueBuilder<T, Cloneable, E>
// where
// T: Clone,
// Dynamic<T>: DynBind<E>,
// for<'a> Dynamic<TempBorrowedMutStatic<'a, T>>: DynBind<E>,
// {
// fn visit<'a>(
// &'a mut self,
// TempBorrowedMutStatic(value): TempBorrowedMutStatic<'a, T>,
// ) -> Canonical<'a, VisitResult<Dynamic<TempBorrowedMutStatic<'a, T>>>, E>
// where
// 'ctx: 'a,
// {
// self.value = Some(Dynamic(value.clone()));
//
// E::value(Flow::Done.into()).cast()
// }
// }