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(Marker); impl ::core::fmt::Debug for ValueError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "missing value of type `{}`", core::any::type_name::()) } } impl Display for ValueError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "missing value of type `{}`", core::any::type_name::()) } } 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 { value: Option, _marker: Marker<(E, Clone)>, } impl crate::build::BuilderTypes for ValueBuilder where T: DynBind, { type Error = ValueError; 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 where T: DynBind, Self: AnyTrait<'src>, { fn build<'a>(self) -> Canonical<'a, Result, 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 where Self: AnyTrait<'src> + DynBind, { fn as_visitor(&mut self) -> DynVisitor<'_, 'src, E> { DynVisitor::new(self) } } impl<'src, T: 'static, E: Environment> AnyTrait<'src> for ValueBuilder where Self: RequestHint<'src, E> + Value<'src, OwnedStatic, E>, { fn upcast_by_id_mut( &mut self, id: crate::any::WithLtTypeId<'src>, ) -> Option> { trait_by_id!(&mut self, id, { type Impls = (dyn RequestHint<'src, E>, dyn Value<'src, OwnedStatic, E>); }); None } } impl<'src, T: 'static + Clone, E: Environment> AnyTrait<'src> for ValueBuilder where T: DynBind + IsSync, Self: Value<'src, OwnedStatic, E> + Value<'src, Raised<'src, 'src, BorrowedStatic<'src, i32>>, E>, { fn upcast_by_id_mut( &mut self, id: crate::any::WithLtTypeId<'src>, ) -> Option> { trait_by_id!(&mut self, id, { type Impls = ( dyn RequestHint<'src, E>, dyn Value<'src, OwnedStatic, 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 where T: DynBind, T: IsSync, { 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::, E>, _, _>(walker.cast(), *this, ()) .cast() }) .map((), |_, (_, x)| x) .cast() } } impl<'src, T: 'static, E: Environment> RequestHint<'src, E> for ValueBuilder where T: Clone + DynBind + IsSync, 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::, 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, E> for ValueBuilder where T: DynBind, { fn visit<'r>( &'r mut self, value: type_name::Lowered<'r, 'src, OwnedStatic>, ) -> Canonical<'r, VisitResult>>, E> where type_name::Lowered<'r, 'src, OwnedStatic>: Sized + DynBind, { 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 where T: DynBind + 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, { 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 where T: Clone + DynBind, { fn visit<'a>( &'a mut self, TempBorrowedStatic(value): TempBorrowedStatic<'a, T>, ) -> Canonical<'a, VisitResult>, E> where 'ctx: 'a, TempBorrowedStatic<'a, T>: DynBind, { 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 // where // T: Clone, // Dynamic: DynBind, // Dynamic>: DynBind, // { // fn visit<'a>( // &'a mut self, // BorrowedMutStatic(value): BorrowedMutStatic<'ctx, T>, // ) -> Canonical<'a, VisitResult>>, 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 // where // T: Clone, // Dynamic: DynBind, // for<'a> Dynamic>: DynBind, // { // fn visit<'a>( // &'a mut self, // TempBorrowedMutStatic(value): TempBorrowedMutStatic<'a, T>, // ) -> Canonical<'a, VisitResult>>, E> // where // 'ctx: 'a, // { // self.value = Some(Dynamic(value.clone())); // // E::value(Flow::Done.into()).cast() // } // }