Diffstat (limited to 'src/build/builders/core/value.rs')
| -rw-r--r-- | src/build/builders/core/value.rs | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/build/builders/core/value.rs b/src/build/builders/core/value.rs new file mode 100644 index 0000000..d82ea1e --- /dev/null +++ b/src/build/builders/core/value.rs @@ -0,0 +1,231 @@ +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. +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<'a>( + &'a mut self, + walker: DynWalker<'a, 'ctx>, + ) -> ErasedEffective<'a, VisitResult<DynWalker<'a, 'ctx>>, E> { + E::as_ctx((self, walker), |(this, walker)| { + hint_protocol::<ValueProto<OwnedStatic<T>, E>>(walker.cast(), *this, ()).cast() + }) + .map(|((_, walker), result)| result.map_skipped(|_| walker)) + } +} + +impl<'ctx, T: Ss + 'static, E: Effect> RequestHint<'ctx, E> for ValueBuilder<T, Cloneable, E> +where + T: Clone, +{ + fn request_hint<'a>( + &'a mut self, + walker: DynWalker<'a, 'ctx>, + ) -> ErasedEffective<'a, VisitResult<DynWalker<'a, 'ctx>>, E> { + 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() + }) + .map(|((_, walker), result)| result.map_skipped(|_| walker)) + } +} + +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()) + } +} |