pipe_chain/pipe/
until.rs

1use crate::{Pipe, Repetition, Result};
2use std::marker::PhantomData;
3use tuplify::{Extend, HList, Unpack};
4
5/// Until combinator
6pub trait UntilExt<I, O, E> {
7    /// Applies a [Pipe] until the 2nd succeeds
8    fn until<O2, P>(self, p: P) -> Until<Self, P, O, O2>
9    where
10        I: Clone,
11        O: Unpack,
12        O2: HList,
13        (Vec<O::Output>,): Extend<O2>,
14        Self: Sized,
15        P: Pipe<I, O2, E>,
16    {
17        Until::new(self, p)
18    }
19
20    /// Applies `self` until `p` succeeds, `self` is applied 0 or more times
21    fn no_more_until<O2, P>(self, p: P) -> NoMoreUntil<Self, P, O, O2>
22    where
23        I: Clone,
24        O: Unpack,
25        O2: HList,
26        (Vec<O::Output>,): Extend<O2>,
27        Self: Sized,
28        P: Pipe<I, O2, E>,
29    {
30        NoMoreUntil::new(self, p)
31    }
32
33    /// repeats `self` with the given repetition then applies `p`
34    fn repeat_until<O2, R, P>(self, r: R, p: P) -> RepeatUntil<Self, P, O, O2>
35    where
36        I: Clone,
37        O: Unpack,
38        O2: HList,
39        R: TryInto<Repetition>,
40        R::Error: std::error::Error,
41        (Vec<O::Output>,): Extend<O2>,
42        Self: Sized,
43        P: Pipe<I, O2, E>,
44    {
45        RepeatUntil::new(self, p, r.try_into().unwrap())
46    }
47}
48
49impl<I, O, E, P: Pipe<I, O, E>> UntilExt<I, O, E> for P {}
50
51/// [UntilExt::until] implementation
52pub struct Until<P1, P2, O, O2>(P1, P2, PhantomData<O>, PhantomData<O2>);
53
54impl<P1, P2, O, O2> Until<P1, P2, O, O2> {
55    fn new(p1: P1, p2: P2) -> Self { Self(p1, p2, PhantomData, PhantomData) }
56}
57
58impl<I, O, O2, E, P1, P2> Pipe<I, <(Vec<O::Output>,) as Extend<O2>>::Output, E>
59    for Until<P1, P2, O, O2>
60where
61    I: Clone,
62    O: Unpack,
63    O2: HList,
64    (Vec<O::Output>,): Extend<O2>,
65    P1: Pipe<I, O, E>,
66    P2: Pipe<I, O2, E>,
67{
68    fn apply(
69        &mut self, mut input: I,
70    ) -> Result<I, <(Vec<O::Output>,) as Extend<O2>>::Output, E> {
71        let mut r = vec![];
72        loop {
73            match self.1.apply(input.clone()) {
74                Ok((i, x)) => return Ok((i, (r,).extend(x))),
75                Err(_) => match self.0.apply(input) {
76                    Ok((i, x)) => {
77                        input = i;
78                        r.push(x.unpack());
79                    }
80                    Err(x) => return Err(x),
81                },
82            }
83        }
84    }
85}
86
87/// [UntilExt::no_more_until] implementation
88pub struct NoMoreUntil<P1, P2, O, O2>(P1, P2, PhantomData<O>, PhantomData<O2>);
89
90impl<P1, P2, O, O2> NoMoreUntil<P1, P2, O, O2> {
91    fn new(p1: P1, p2: P2) -> Self { Self(p1, p2, PhantomData, PhantomData) }
92}
93
94impl<I, O, O2, E, P1, P2> Pipe<I, <(Vec<O::Output>,) as Extend<O2>>::Output, E>
95    for NoMoreUntil<P1, P2, O, O2>
96where
97    I: Clone,
98    O: Unpack,
99    O2: HList,
100    (Vec<O::Output>,): Extend<O2>,
101    P1: Pipe<I, O, E>,
102    P2: Pipe<I, O2, E>,
103{
104    fn apply(
105        &mut self, mut input: I,
106    ) -> Result<I, <(Vec<O::Output>,) as Extend<O2>>::Output, E> {
107        let mut r = vec![];
108        loop {
109            match self.0.apply(input.clone()) {
110                Ok((i, x)) => {
111                    input = i;
112                    r.push(x.unpack());
113                }
114                Err(_) => match self.1.apply(input) {
115                    Ok((i, x)) => return Ok((i, (r,).extend(x))),
116                    Err(x) => return Err(x),
117                },
118            }
119        }
120    }
121}
122
123/// [UntilExt::repeat_until] implementation
124pub struct RepeatUntil<P1, P2, O, O2>(
125    P1,
126    P2,
127    Repetition,
128    PhantomData<O>,
129    PhantomData<O2>,
130);
131
132impl<P1, P2, O, O2> RepeatUntil<P1, P2, O, O2> {
133    fn new(p1: P1, p2: P2, r: Repetition) -> Self {
134        Self(p1, p2, r, PhantomData, PhantomData)
135    }
136}
137
138impl<I, O, O2, E, P1, P2> Pipe<I, <(Vec<O::Output>,) as Extend<O2>>::Output, E>
139    for RepeatUntil<P1, P2, O, O2>
140where
141    I: Clone,
142    O: Unpack,
143    O2: HList,
144    (Vec<O::Output>,): Extend<O2>,
145    P1: Pipe<I, O, E>,
146    P2: Pipe<I, O2, E>,
147{
148    fn apply(
149        &mut self, mut input: I,
150    ) -> Result<I, <(Vec<O::Output>,) as Extend<O2>>::Output, E> {
151        let mut r = vec![];
152        let mut nb = 0;
153        loop {
154            if self.2.is_max(nb) {
155                let (i, x) = self.1.apply(input)?;
156                return Ok((i, (r,).extend(x)));
157            }
158            if self.2.needs_more(nb) {
159                let (i, x) = self.0.apply(input)?;
160                input = i;
161                r.push(x.unpack());
162            } else {
163                match self.1.apply(input.clone()) {
164                    Ok((i, x)) => {
165                        return Ok((i, (r,).extend(x)));
166                    }
167                    Err(_) => {
168                        let (i, x) = self.0.apply(input)?;
169                        input = i;
170                        r.push(x.unpack());
171                    }
172                }
173            }
174            nb += 1;
175        }
176    }
177}