1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "alloc")]
extern crate alloc;
pub mod build;
pub mod impls;
pub mod protocol;
pub mod protocols;
pub mod transform;
pub mod walk;
use protocol::{AnyHint, AnyVisit, Hint, ProtocolId, Visit};
/// Signal to a walker or visitor that it should exit early or continue.
///
/// [`Walker`] and [`Visitor`] can't signal an error condition with a
/// [`Result`] so instead they can use this.
#[must_use]
#[derive(Copy, Clone, Debug)]
pub enum ControlFlow {
/// Continue the walk as normal.
Continue,
Done,
Error,
}
impl ControlFlow {
pub fn to_done(self) -> Self {
match self {
ControlFlow::Continue => ControlFlow::Done,
ControlFlow::Done => ControlFlow::Done,
ControlFlow::Error => ControlFlow::Error,
}
}
pub fn to_continue(self) -> Self {
match self {
ControlFlow::Continue => ControlFlow::Continue,
ControlFlow::Done => ControlFlow::Continue,
ControlFlow::Error => ControlFlow::Error,
}
}
}
/// Walker over a value.
///
/// The walker can give out borrows with a lifetime of `'ctx` to the visitor.
pub trait Walker<'ctx> {
/// Walk the value.
///
/// The walker will call [`Visit::visit`] methods for one or more
/// [`Protocol`][protocol::Protocol] on the given `visitor`.
fn walk(&mut self, visitor: &mut dyn Visitor<'ctx>) -> ControlFlow;
}
/// Hint lookup for a walker.
///
/// Some walkers may need a hint for what the value it's walking actually is.
/// To support this, a [`Walker`] will call the visitor's [`Visitor::request_hint`]
/// method and the visitor can call a [`Hint::hint`] method for a
/// [`Protocol`][protocol::Protocol] that the walker supports.
pub trait WalkerHints<'ctx> {
/// Query the walker for a given protocol.
///
/// If the walker doesn't support the protocol then a `None` is returned.
/// Note, a walker may return a `None` for a particular value but support
/// the protocol for other values.
///
/// Use [`lookup_hint`][protocol::lookup_hint], or manually call
/// [`AnyHint::downcast`] on the returned value to access the [`Hint`].
fn protocol(&mut self, id: ProtocolId) -> Option<AnyHint<'_, 'ctx>>;
}
/// Visitor over a value to be built.
pub trait Visitor<'ctx> {
/// Request the visitor provide a hint for what protocol to use.
///
/// Some walkers may need a hint for what the value it's walking actually is.
/// To support this, a [`Walker`] will call this method
/// and the visitor can call a [`Hint::hint`] method for a
/// [`Protocol`][protocol::Protocol] that the walker supports.
///
/// Returning a `None` means the visitor gave no hint. The `need_hint` will
/// be `true` if the walker needs a hint to not encounter an error.
fn request_hint(
&mut self,
hints: &mut dyn WalkerHints<'ctx>,
need_hint: bool,
) -> ControlFlow;
/// Query the visitor for a given protocol.
///
/// If the visitor doesn't support the protocol then a `None` is returned.
/// Note, a visitor may return a `None` if it doesn't support the protocol
/// for it's current internal state but could otherwise.
///
/// Use [`lookup_visit`][protocol::lookup_visit], or manually call
/// [`AnyVisit::downcast`] on the returned value to access the [`Visit`].
fn protocol(&mut self, id: ProtocolId) -> Option<AnyVisit<'_, 'ctx>>;
}
|