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()
}