use std::convert::Infallible;
use std::ops::ControlFlow;
use std::ops::FromResidual;
pub use Flow::Continue;
pub use Flow::Exit;
pub enum Flow<C, E> {
Continue(C),
Exit(E),
}
impl<C, E> Flow<C, E> {
pub fn map<F, C2>(self, f: F) -> Flow<C2, E>
where
F: FnOnce(C) -> C2,
{
match self {
Flow::Continue(v) => Flow::Continue(f(v)),
Flow::Exit(e) => Flow::Exit(e),
}
}
pub fn map_exception<F, E2>(self, f: F) -> Flow<C, E2>
where
F: FnOnce(E) -> E2,
{
match self {
Flow::Continue(v) => Flow::Continue(v),
Flow::Exit(e) => Flow::Exit(f(e)),
}
}
}
impl<C, E> std::ops::Try for Flow<C, E> {
type Output = C;
type Residual = Flow<Infallible, E>;
fn from_output(output: Self::Output) -> Self {
Continue(output)
}
fn branch(self) -> std::ops::ControlFlow<Self::Residual, Self::Output> {
match self {
Flow::Continue(value) => ControlFlow::Continue(value),
Flow::Exit(e) => ControlFlow::Break(Flow::Exit(e)),
}
}
}
impl<C, E> FromResidual for Flow<C, E> {
fn from_residual(residual: <Self as std::ops::Try>::Residual) -> Self {
match residual {
Flow::Exit(e) => Flow::Exit(e),
Flow::Continue(_) => unreachable!("This should never be reached."),
}
}
}