Diffstat (limited to 'src/protocol/walker/hint.rs')
| -rw-r--r-- | src/protocol/walker/hint.rs | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index 683436a..049d881 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -4,11 +4,13 @@ //! this module gives a protocol by which a visitor can give a hint //! to the walker about what it is expecting. +use core::ops::{Deref, DerefMut}; + use crate::{ - any::TypeName, - effect::{Effect, EffectiveExt as _, ErasedEffective, ReadyExt as _}, + any::{AnyTrait, TypeName}, + effect::{Effect, EffectiveExt as _, ErasedEffective, ReadyExt as _, Ss}, hkt::Marker, - protocol::{visitor::VisitResult, DynWalker}, + protocol::{visitor::VisitResult, DynVisitor, DynWalker}, Flow, }; @@ -72,9 +74,9 @@ pub trait Hint<'ctx, Protocol: ?Sized + HintMeta> { /// This should only be called once per [`RequestHint`]. fn hint<'this: 'e, 'visitor: 'e, 'hint: 'e, 'e>( &'this mut self, - visitor: &'visitor mut TypeName::T<'visitor, 'ctx, Protocol>, + visitor: DynVisitorWith<'visitor, 'ctx, Protocol>, hint: MetaHint<'hint, 'ctx, Protocol>, - ) -> ErasedEffective<'e, Flow, Protocol::Effect> + ) -> ErasedEffective<'e, VisitResult, Protocol::Effect> where 'ctx: 'this + 'visitor + 'hint + 'e; @@ -85,6 +87,47 @@ pub trait Hint<'ctx, Protocol: ?Sized + HintMeta> { ) -> ErasedEffective<'a, Result<MetaKnown<'a, 'ctx, Protocol>, ()>, Protocol::Effect>; } +pub struct DynVisitorWith<'temp, 'ctx, Protocol: ?Sized> { + visitor: DynVisitor<'temp, 'ctx>, + _marker: Marker<Protocol>, +} + +pub trait HasProtocol<Protocol: ?Sized> {} + +impl<'temp, 'ctx: 'temp, Protocol: ?Sized + HintMeta> DynVisitorWith<'temp, 'ctx, Protocol> { + pub fn new<T>(visitor: &'temp mut T) -> Self + where + T: AnyTrait<'ctx> + HasProtocol<Protocol> + Ss, + { + Self { + visitor: DynVisitor(visitor), + _marker: Default::default(), + } + } + + pub fn as_known(&mut self) -> &mut TypeName::T<'_, 'ctx, Protocol> { + self.visitor.upcast_mut::<Protocol>().unwrap() + } + + pub fn into_inner(self) -> DynVisitor<'temp, 'ctx> { + self.visitor + } +} + +impl<'temp, 'ctx, Protocol: ?Sized> Deref for DynVisitorWith<'temp, 'ctx, Protocol> { + type Target = DynVisitor<'temp, 'ctx>; + + fn deref(&self) -> &Self::Target { + &self.visitor + } +} + +impl<'temp, 'ctx, Protocol: ?Sized> DerefMut for DynVisitorWith<'temp, 'ctx, Protocol> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.visitor + } +} + pub struct HintProto<Protocol: ?Sized>(Marker<Protocol>); impl<'a, 'ctx, Protocol: ?Sized> TypeName::MemberTypeForLt<'a, 'ctx, &'a &'ctx ()> @@ -110,13 +153,19 @@ pub fn hint_protocol< 'hint: 'e, 'e, Protocol: ?Sized + HintMeta, + T, >( walker: DynWalker<'walker, 'ctx>, - visitor: &'visitor mut TypeName::T<'visitor, 'ctx, Protocol>, + visitor: &'visitor mut T, hint: MetaHint<'hint, 'ctx, Protocol>, -) -> ErasedEffective<'e, VisitResult<()>, Protocol::Effect> { +) -> ErasedEffective<'e, VisitResult<()>, Protocol::Effect> +where + T: AnyTrait<'ctx> + HasProtocol<Protocol> + Ss, +{ if let Some(object) = walker.0.upcast_mut::<HintProto<Protocol>>() { - object.hint(visitor, hint).map(Into::into) + object + .hint(DynVisitorWith::new(visitor), hint) + .map(Into::into) } else { VisitResult::Skipped(()).ready() } |