mod searcher;
mod visitor;
mod walkable;
pub use core::ops::ControlFlow;
pub use self::{
searcher::Searcher,
visitor::{OpVisitor, OperationVisitor, SymbolVisitor, Visitor},
walkable::{RawWalk, ReverseBlock, Walk, WalkMut, WalkOrder, WalkStage},
};
use crate::Report;
#[derive(Clone)]
#[must_use]
pub enum WalkResult<B = Report, C = ()> {
Continue(C),
Skip,
Break(B),
}
impl<B, C> WalkResult<B, C> {
pub fn should_continue(&self) -> bool {
matches!(self, Self::Continue(_))
}
pub fn was_interrupted(&self) -> bool {
matches!(self, Self::Break(_))
}
pub fn was_skipped(&self) -> bool {
matches!(self, Self::Skip)
}
}
impl<B> WalkResult<B, ()> {
#[inline]
pub fn into_result(self) -> Result<(), B> {
match self {
Self::Break(err) => Err(err),
Self::Skip | Self::Continue(_) => Ok(()),
}
}
}
impl<B> From<()> for WalkResult<B, ()> {
fn from(_value: ()) -> Self {
Self::Continue(())
}
}
impl<B> From<Result<(), B>> for WalkResult<B, ()> {
fn from(value: Result<(), B>) -> Self {
match value {
Ok(_) => WalkResult::Continue(()),
Err(err) => WalkResult::Break(err),
}
}
}
impl<B> From<WalkResult<B, ()>> for Result<(), B> {
#[inline(always)]
fn from(value: WalkResult<B, ()>) -> Self {
value.into_result()
}
}
impl<B, C> core::ops::FromResidual for WalkResult<B, C> {
fn from_residual(residual: <Self as core::ops::Try>::Residual) -> Self {
match residual {
WalkResult::Break(b) => WalkResult::Break(b),
_ => unreachable!(),
}
}
}
impl<B, C> core::ops::Residual<C> for WalkResult<B, core::convert::Infallible> {
type TryType = WalkResult<B, C>;
}
impl<B, C> core::ops::Try for WalkResult<B, C> {
type Output = C;
type Residual = WalkResult<B, core::convert::Infallible>;
#[inline]
fn from_output(output: Self::Output) -> Self {
WalkResult::Continue(output)
}
#[inline]
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self {
WalkResult::Continue(c) => ControlFlow::Continue(c),
WalkResult::Skip => ControlFlow::Break(WalkResult::Skip),
WalkResult::Break(b) => ControlFlow::Break(WalkResult::Break(b)),
}
}
}