Diffstat (limited to 'src/protocol/walker/hint.rs')
-rw-r--r--src/protocol/walker/hint.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs
new file mode 100644
index 0000000..fdcc46a
--- /dev/null
+++ b/src/protocol/walker/hint.rs
@@ -0,0 +1,95 @@
+//! 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::{
+ nameable,
+ protocol::{ControlFlow, Visitor},
+};
+
+/// Meta information for the hint.
+///
+/// This gives the visitor more information to work from when selecting a hint.
+pub trait HintMeta<'ctx> {
+ /// Information known by the walker.
+ ///
+ /// This should be information easy to get without changing the state of the walker
+ /// in an irreversable way.
+ type Known<'a>
+ where
+ 'ctx: 'a;
+
+ /// Extra information the visitor can give to the walker about what it is expecting.
+ type Hint;
+}
+
+/// Object implementing the [`Hint`] protocol.
+pub trait Hint<'ctx, Protocol: HintMeta<'ctx>> {
+ /// Hint to the walker to use the `P` protocol.
+ ///
+ /// This should only be called once per [`RequestHint`].
+ fn hint(&mut self, visitor: Visitor<'_, 'ctx>, hint: Protocol::Hint) -> ControlFlow;
+
+ /// Ask the walker for information about it's support of the protocol.
+ fn known(&mut self, hint: &Protocol::Hint) -> ControlFlow<(), Protocol::Known<'_>>;
+}
+
+nameable! {
+ pub ['a, 'ctx, Protocol]
+ dyn Hint<'ctx, Protocol> + 'a where {'ctx: 'a, Protocol: ?Sized}
+ dyn Hint<'ctx, Protocol::Nameable> + 'a where {'ctx: 'a, Protocol: ?Sized}
+}
+
+#[cfg(test)]
+mod test {
+ use crate::any::{LtTypeId, TypeNameable};
+
+ use super::*;
+
+ #[test]
+ fn demo() {
+ struct X;
+ struct Y;
+
+ nameable! {
+ ['a, 'ctx]
+ Y where {}
+ }
+
+ impl<'ctx, X> Hint<'ctx, Y> for X {
+ fn hint(
+ &mut self,
+ visitor: Visitor<'_, 'ctx>,
+ hint: <Y as HintMeta<'_>>::Hint,
+ ) -> ControlFlow<()> {
+ todo!()
+ }
+
+ fn known(
+ &mut self,
+ hint: &<Y as HintMeta<'_>>::Hint,
+ ) -> ControlFlow<(), <Y as HintMeta<'_>>::Known<'_>> {
+ todo!()
+ }
+ }
+
+ impl<'ctx> HintMeta<'ctx> for Y {
+ type Known<'a> = () where 'ctx: 'a;
+
+ type Hint = ();
+ }
+
+ let x = X;
+ let y: &dyn Hint<'_, Y> = &x;
+
+ fn id<'a, 'ctx, T: ?Sized + TypeNameable<'a, 'ctx>>(x: &T) {
+ dbg!(LtTypeId::of::<T>());
+ }
+
+ id(y);
+
+ // todo!();
+ }
+}