1use crate::{Pipe, Repetition, Result};
2use std::marker::PhantomData;
3use tuplify::{Extend, HList, Unpack};
4
5pub trait UntilExt<I, O, E> {
7 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 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 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
51pub 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
87pub 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
123pub 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}