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
use crate::{error::WalkerError, Walker};

/// A type that can be walked once.
///
/// A walkable type has one canonical walker type, but other walkers
/// can operate on the same walkable type. This trait gives the canonical
/// walker for an owned instance of the value. The `'value` lifetime
/// is the lifetime of the value itself.
///
/// [`WalkableOnce`], [`WalkableMut`], and [`Walkable`] form a family of traits
/// similar to the [`FnOnce`], [`FnMut`], [`Fn`] family of traits.
pub trait WalkOnce<'value, 'ctx: 'value, VisitorErr> {
    /// Error the walker can return during the walk.
    type ErrorOnce: WalkerError<'value, 'ctx>;

    /// Walker over an instance of the type.
    type WalkerOnce: Walker<'value, 'ctx, VisitorErr, Error = Self::ErrorOnce>;

    /// Create a walker over a value of the type.
    ///
    /// Walking over the value is able to transfer ownership to the visitor.
    fn into_walker(self) -> Self::WalkerOnce;
}

/// A type that can be walked using a mutable borrow.
///
/// This trait gives the canonical walker for a mutably borrowed
/// instance of the value. The `'value` lifetime is the lifetime of
/// the value itself. The `'walking` lifetime can be used by
/// [`Self::ErrorMut`] to reference the value using the passed mutable borrow.
///
/// [`WalkableOnce`], [`WalkableMut`], and [`Walkable`] form a family of traits
/// similar to the [`FnOnce`], [`FnMut`], [`Fn`] family of traits.
pub trait WalkMut<'value, 'ctx: 'value, VisitorErr> {
    /// Error the walker can return during the walk.
    type ErrorMut: WalkerError<'value, 'ctx>;

    /// Walker over an instance of the type.
    type WalkerMut: Walker<'value, 'ctx, VisitorErr, Error = Self::ErrorMut>;

    fn walker_mut(&'value mut self) -> Self::WalkerMut;
}

pub trait Walk<'value, 'ctx: 'value, VisitorErr>: WalkMut<'value, 'ctx, VisitorErr> {
    type Error: WalkerError<'value, 'ctx>;
    type Walker: Walker<'value, 'ctx, VisitorErr, Error = Self::Error>;

    fn walker(&'value self) -> Self::Walker;
}

pub fn walker_once<'value, 'ctx: 'value, VisitorErr, W: WalkOnce<'value, 'ctx, VisitorErr>>(
    value: W,
) -> W::WalkerOnce {
    value.into_walker()
}

pub fn walker_mut<'value, 'ctx: 'value, VisitorErr, W: WalkMut<'value, 'ctx, VisitorErr>>(
    value: &'value mut W,
) -> W::WalkerMut {
    value.walker_mut()
}

pub fn walker<'value, 'ctx: 'value, VisitorErr, W: Walk<'value, 'ctx, VisitorErr>>(
    value: &'value W,
) -> W::Walker {
    value.walker()
}