pipe_chain/pipe/
wrap.rs

1use crate::{Pipe, Result};
2use std::marker::PhantomData;
3/// Wraps the pipe and input/ouput into a closure
4pub trait WrapExt<I, O, E, R> {
5    /// wraps self into a function
6    /// ```rust
7    /// # use pipe_chain::{str::TagStrError, tag, AndExt, Incomplete, Pipe, WrapExt, Result};
8    /// # use std::error::Error as StdError;
9    /// # #[derive(Debug, PartialEq, Eq)]
10    /// # enum Error {
11    /// #     Tag(TagStrError),
12    /// #     Incomplete(Incomplete),
13    /// # }
14    /// #
15    /// # impl std::fmt::Display for Error {
16    /// #     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17    /// #         write!(f, "{self:?}")
18    /// #     }
19    /// # }
20    /// # impl StdError for Error {}
21    /// #
22    /// # impl From<Incomplete> for Error {
23    /// #     fn from(value: Incomplete) -> Error { Error::Incomplete(value) }
24    /// # }
25    /// #
26    /// # impl From<TagStrError> for Error {
27    /// #     fn from(value: TagStrError) -> Error { Error::Tag(value) }
28    /// # }
29    /// #
30    /// pub fn input_offset<'a, O, E>(
31    ///     p: &mut impl Pipe<&'a str, O, E>, input: (&'a str, usize),
32    /// ) -> Result<(&'a str, usize), O, E> {
33    ///     let (i, o) = p.apply(input.0)?;
34    ///     Ok(((i, input.1 + (input.0.len() - i.len())), o))
35    /// }
36    /// assert_eq!(
37    ///     tag::<Error, _, _>("foo").and(tag("bar")).wrap(input_offset).apply(("foobar", 0)),
38    ///     Ok((("", 6), ("foo", "bar")))
39    /// );
40    /// assert_eq!(
41    ///     tag::<Error, _, _>("foo").and(tag("bar")).wrap(input_offset).apply(("foobar", 0)),
42    ///     Ok((("", 6), ("foo", "bar")))
43    /// );
44    /// ```
45    fn wrap<I2, O2, R2, F>(self, f: F) -> Wrap<I, O, R, Self, F>
46    where
47        Self: Pipe<I, O, E, R> + Sized,
48        F: FnMut(&mut Self, I2) -> Result<R2, O2, E>,
49    {
50        Wrap::new(self, f)
51    }
52}
53
54impl<I, O, E, R, P: Pipe<I, O, E, R>> WrapExt<I, O, E, R> for P {}
55
56/// [WrapExt::wrap] implementation
57pub struct Wrap<I, O, R, P, F>(P, F, PhantomData<I>, PhantomData<O>, PhantomData<R>);
58
59impl<I, O, R, P, F> Wrap<I, O, R, P, F> {
60    fn new(p: P, f: F) -> Self { Self(p, f, PhantomData, PhantomData, PhantomData) }
61}
62
63impl<I, O, E, R, I2, O2, R2, P, F> Pipe<I2, O2, E, R2> for Wrap<I, O, R, P, F>
64where
65    P: Pipe<I, O, E, R>,
66    F: FnMut(&mut P, I2) -> Result<R2, O2, E>,
67{
68    fn apply(&mut self, input: I2) -> Result<R2, O2, E> { (self.1)(&mut self.0, input) }
69}