//! Protocol for giving a hint to a walker.
//!
//! Sometimes a walker has multiple protocols it could use,
//! this module gives a protocol by which a visitor can give a hint
//! to the walker about what it is expecting.
use crate::{
any::TypeName,
effect::{Effect, ErasedEffective},
higher_ranked_trait, higher_ranked_type,
hkt::Marker,
protocol::DynVisitor,
Flow,
};
higher_ranked_trait! {
pub type class Meta for<'a, 'ctx> {
type Bound = &'a &'ctx ();
type T: { Send + Sync + Sized } where { 'ctx: 'a };
type HigherRanked: { };
}
}
higher_ranked_type! {
impl Meta {
impl['a, 'ctx] type T['a, 'ctx] for () = ();
impl['a, 'ctx] type HigherRanked['a, 'ctx] for () = ();
}
}
/// Meta information for the hint.
///
/// This gives the visitor more information to work from when selecting a hint.
pub trait HintMeta: Send + Sync + 'static {
/// Information known by the walker.
///
/// This should be information easy to get without changing the state of the walker
/// in an irreversible way.
type Known: Meta::MemberType;
/// Extra information the visitor can give to the walker about what it is expecting.
type Hint: Meta::MemberType;
type Effect: Effect;
}
pub type MetaKnown<'a, 'ctx, Protocol> = Meta::T<'a, 'ctx, <Protocol as HintMeta>::Known>;
pub type MetaHint<'a, 'ctx, Protocol> = Meta::T<'a, 'ctx, <Protocol as HintMeta>::Hint>;
/// Object implementing the [`Hint`] protocol.
pub trait Hint<'ctx, Protocol: ?Sized + HintMeta> {
/// Hint to the walker to use the `P` protocol.
///
/// This should only be called once per [`RequestHint`].
fn hint<'a>(
&'a mut self,
visitor: DynVisitor<'a, 'ctx>,
hint: MetaHint<'a, 'ctx, Protocol>,
) -> ErasedEffective<'a, Flow, Protocol::Effect>;
/// Ask the walker for information about it's support of the protocol.
fn known<'a>(
&'a mut self,
hint: &'a MetaHint<'a, 'ctx, Protocol>,
) -> ErasedEffective<'a, Result<MetaKnown<'a, 'ctx, Protocol>, ()>, Protocol::Effect>;
}
pub struct HintProto<Protocol: ?Sized>(Marker<Protocol>);
higher_ranked_type! {
impl TypeName {
impl['a, 'ctx, Protocol] type T['a, 'ctx] for HintProto<Protocol> =
dyn Hint<'ctx, Protocol> + Send + Sync + 'a
where {
Protocol: 'static,
};
impl['a, 'ctx, Protocol] type HigherRanked['a, 'ctx] for dyn Hint<'ctx, Protocol> + Send + Sync + 'a =
HintProto<Protocol>
where {
Protocol: 'static,
};
}
}