mod seq;
pub use seq::*;
#[must_use = "routines are lazy and do nothing unless consumed"]
pub trait Routine<R> {
type Output;
type Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error>;
fn and<T>(self, next: T) -> And<Self, T>
where
Self: Sized,
T: Routine<R, Error = Self::Error>,
{
And {
first: self,
second: next,
}
}
fn and_then<F, T>(self, f: F) -> AndThen<Self, F>
where
Self: Sized,
F: FnMut(<Self as Routine<R>>::Output) -> T,
T: Routine<R, Error = Self::Error>,
{
AndThen { routine: self, f }
}
fn or<T>(self, other: T) -> Or<Self, T>
where
Self: Sized,
T: Routine<R, Output = Self::Output>,
{
Or {
first: self,
second: other,
}
}
fn or_else<F, T>(self, f: F) -> OrElse<Self, F>
where
Self: Sized,
F: FnMut(<Self as Routine<R>>::Error) -> T,
T: Routine<R, Output = Self::Output>,
{
OrElse { routine: self, f }
}
fn map<F, T>(self, f: F) -> Map<Self, F>
where
Self: Sized,
F: FnMut(Self::Output) -> T,
{
Map { routine: self, f }
}
fn map_err<F, T>(self, f: F) -> MapErr<Self, F>
where
Self: Sized,
F: FnMut(Self::Error) -> T,
{
MapErr { routine: self, f }
}
fn repeat(self, n: usize) -> Repeat<Self>
where
Self: Sized,
{
Repeat {
routine: self,
count: n,
}
}
fn repeat_while<F>(self, f: F) -> While<Self, F>
where
Self: Sized,
F: FnMut() -> bool,
{
While { routine: self, f }
}
fn join<T>(self, other: T) -> Join<Self, T>
where
Self: Sized,
T: Routine<R>,
{
Join { a: self, b: other }
}
}
impl<R, T> Routine<R> for &mut T
where
T: Routine<R> + ?Sized,
{
type Output = <T as Routine<R>>::Output;
type Error = <T as Routine<R>>::Error;
fn run(&mut self, resource: &mut R) -> Result<Self::Output, Self::Error> {
(*self).run(resource)
}
}
impl<R, T> Routine<R> for Box<T>
where
T: Routine<R> + ?Sized,
{
type Output = <T as Routine<R>>::Output;
type Error = <T as Routine<R>>::Error;
fn run(&mut self, resource: &mut R) -> Result<Self::Output, Self::Error> {
self.as_mut().run(resource)
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct Map<R, F> {
routine: R,
f: F,
}
impl<R, S, F, T> Routine<R> for Map<S, F>
where
F: FnMut(<S as Routine<R>>::Output) -> T,
S: Routine<R>,
{
type Output = T;
type Error = <S as Routine<R>>::Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
match self.routine.run(resource) {
Ok(value) => Ok((self.f)(value)),
Err(err) => Err(err),
}
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct MapErr<R, F> {
routine: R,
f: F,
}
impl<R, S, F, T> Routine<R> for MapErr<S, F>
where
F: FnMut(<S as Routine<R>>::Error) -> T,
S: Routine<R>,
{
type Output = <S as Routine<R>>::Output;
type Error = T;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
match self.routine.run(resource) {
Err(err) => Err((self.f)(err)),
Ok(value) => Ok(value),
}
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct And<S, T> {
first: S,
second: T,
}
impl<E, R, S, T> Routine<R> for And<S, T>
where
S: Routine<R, Error = E>,
T: Routine<R, Error = E>,
{
type Output = <T as Routine<R>>::Output;
type Error = <T as Routine<R>>::Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
let _ = self.first.run(resource)?;
self.second.run(resource)
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct AndThen<T, F> {
routine: T,
f: F,
}
impl<E, F, R, S, T> Routine<R> for AndThen<S, F>
where
F: FnMut(<S as Routine<R>>::Output) -> T,
S: Routine<R, Error = E>,
T: Routine<R, Error = E>,
{
type Output = <T as Routine<R>>::Output;
type Error = <S as Routine<R>>::Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
let output = self.routine.run(resource)?;
(self.f)(output).run(resource)
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct Or<S, T> {
first: S,
second: T,
}
impl<O, R, S, T> Routine<R> for Or<S, T>
where
S: Routine<R, Output = O>,
T: Routine<R, Output = O>,
{
type Output = <S as Routine<R>>::Output;
type Error = <T as Routine<R>>::Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
match self.first.run(resource) {
Err(_) => self.second.run(resource),
Ok(ok) => Ok(ok),
}
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct OrElse<T, F> {
routine: T,
f: F,
}
impl<F, O, R, S, T> Routine<R> for OrElse<S, F>
where
F: FnMut(<S as Routine<R>>::Error) -> T,
S: Routine<R, Output = O>,
T: Routine<R, Output = O>,
{
type Output = <T as Routine<R>>::Output;
type Error = <T as Routine<R>>::Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
match self.routine.run(resource) {
Err(err) => (self.f)(err).run(resource),
Ok(value) => Ok(value),
}
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct Repeat<T> {
routine: T,
count: usize,
}
impl<R, T> Routine<R> for Repeat<T>
where
T: Routine<R>,
{
type Output = Option<<T as Routine<R>>::Output>;
type Error = <T as Routine<R>>::Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
let mut value = None;
for _ in 0..self.count {
value = Some(self.routine.run(resource)?);
}
Ok(value)
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct While<T, F> {
routine: T,
f: F,
}
impl<F, R, T> Routine<R> for While<T, F>
where
T: Routine<R>,
F: FnMut() -> bool,
{
type Output = Option<<T as Routine<R>>::Output>;
type Error = <T as Routine<R>>::Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
let mut value = None;
while (self.f)() {
value = Some(self.routine.run(resource)?);
}
Ok(value)
}
}
#[derive(Debug)]
#[must_use = "routines are lazy and do nothing unless consumed"]
pub struct Join<A, B> {
a: A,
b: B,
}
impl<A, B, E, R> Routine<R> for Join<A, B>
where
A: Routine<R, Error = E>,
B: Routine<R, Error = E>,
{
type Output = (<A as Routine<R>>::Output, <B as Routine<R>>::Output);
type Error = <A as Routine<R>>::Error;
fn run(&mut self, resource: &'_ mut R) -> Result<Self::Output, Self::Error> {
Ok((self.a.run(resource)?, self.b.run(resource)?))
}
}
pub trait IntoRoutine<R> {
type Output;
type Error;
type IntoRoutine: Routine<R, Output = Self::Output, Error = Self::Error>;
fn into_routine(self) -> Self::IntoRoutine;
}
impl<R, T> IntoRoutine<R> for T
where
T: Routine<R>,
{
type Output = <T as Routine<R>>::Output;
type Error = <T as Routine<R>>::Error;
type IntoRoutine = T;
fn into_routine(self) -> Self::IntoRoutine {
self
}
}
#[cfg(test)]
mod test {
#[allow(clippy::wildcard_imports)]
use super::*;
#[derive(Debug, Copy, Clone)]
struct OkRoutine<T>(T);
impl<T> Routine<()> for OkRoutine<T>
where
T: Copy,
{
type Output = T;
type Error = i32;
fn run(&mut self, _: &'_ mut ()) -> Result<Self::Output, Self::Error> {
Ok(self.0)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct ErrRoutine(i32);
impl Routine<()> for ErrRoutine {
type Output = i32;
type Error = i32;
fn run(&mut self, _: &'_ mut ()) -> Result<Self::Output, Self::Error> {
Err(self.0)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct IterRoutine {
value: i32,
count: usize,
called_count: usize,
}
impl Routine<()> for IterRoutine {
type Output = i32;
type Error = i32;
fn run(&mut self, _: &'_ mut ()) -> Result<Self::Output, Self::Error> {
self.called_count += 1;
let is_ok = self.count > 0;
self.count = self.count.saturating_sub(1);
if is_ok {
Ok(self.value)
} else {
Err(self.value)
}
}
}
#[test]
fn map() {
assert_eq!(Ok(2), OkRoutine(1).map(|x| 2 * x).run(&mut ()));
assert_eq!(Err(1), ErrRoutine(1).map(|x| 2 * x).run(&mut ()));
}
#[test]
fn map_err() {
assert_eq!(Ok(1), OkRoutine(1).map_err(|x| 2.0 * x as f32).run(&mut ()));
assert_eq!(
Err(2.0),
ErrRoutine(1).map_err(|x| 2.0 * x as f32).run(&mut ())
);
}
#[test]
fn and() {
assert_eq!(Ok("hi"), OkRoutine(1).and(OkRoutine("hi")).run(&mut ()));
assert_eq!(Err(1), ErrRoutine(1).and(OkRoutine("hi")).run(&mut ()));
}
#[test]
fn and_then() {
assert_eq!(
Ok(2),
OkRoutine(1)
.and_then(|value| OkRoutine(value * 2))
.run(&mut ())
);
assert_eq!(
Err(1),
ErrRoutine(1)
.and_then(|value| OkRoutine(value * 2))
.run(&mut ())
);
}
#[test]
fn or() {
assert_eq!(Ok(1), OkRoutine(1).or(OkRoutine(2)).run(&mut ()));
assert_eq!(Ok(1), OkRoutine(1).or(ErrRoutine(2)).run(&mut ()));
assert_eq!(Ok(2), ErrRoutine(1).or(OkRoutine(2)).run(&mut ()));
assert_eq!(Err(2), ErrRoutine(1).or(ErrRoutine(2)).run(&mut ()));
}
#[test]
fn or_else() {
assert_eq!(
Ok(1),
OkRoutine(1).or_else(|_err| OkRoutine(2)).run(&mut ())
);
assert_eq!(
Ok(1),
OkRoutine(1).or_else(|_err| ErrRoutine(2)).run(&mut ())
);
assert_eq!(
Ok(2),
ErrRoutine(1).or_else(|_err| OkRoutine(2)).run(&mut ())
);
assert_eq!(
Err(2),
ErrRoutine(1).or_else(|_err| ErrRoutine(2)).run(&mut ())
);
}
#[test]
fn repeat() {
let mut routine = IterRoutine {
value: 3,
count: 5,
called_count: 0,
};
let value = (&mut routine).repeat(5).run(&mut ()).unwrap();
assert_eq!(value, Some(3));
assert_eq!(routine.called_count, 5);
let value = (&mut routine).repeat(5).run(&mut ()).unwrap_err();
assert_eq!(value, 3);
assert_eq!(routine.called_count, 6);
let value = OkRoutine(1).repeat(0).run(&mut ()).unwrap();
assert!(value.is_none());
}
#[test]
fn repeat_while() {
let mut count = 0;
let mut routine = IterRoutine {
value: 3,
count: 5,
called_count: 0,
};
let value = (&mut routine)
.repeat_while(|| {
let temp = count;
count += 1;
temp < 3
})
.run(&mut ())
.unwrap();
assert_eq!(value, Some(3));
assert_eq!(routine.called_count, 3);
let value = (&mut routine)
.repeat_while(|| true)
.run(&mut ())
.unwrap_err();
assert_eq!(value, 3);
assert_eq!(routine.called_count, 6);
let value = (&mut routine).repeat_while(|| false).run(&mut ()).unwrap();
assert_eq!(value, None);
assert_eq!(routine.called_count, 6);
}
#[test]
fn join() {
let values = OkRoutine(1).join(OkRoutine(2)).run(&mut ()).unwrap();
assert_eq!(values, (1, 2));
}
}