1use typle::typle;
2
3use crate::byte_stream::ByteStream;
4use crate::iterable::OutputToByteStream;
5use crate::repeatable::Repeatable;
6use crate::{Extract, ParseResult};
7
8#[typle(Tuple for 1..=12)]
9pub struct TupleAny<T> {
10 tuple: T,
11}
12
13#[typle(Tuple for 1..=12)]
14impl<T> Extract for TupleAny<T>
15where
16 T: Tuple,
17 T<_>: Extract<Output = ByteStream>,
18{
19 type State = typle_for!(i in .. => Option<Option<T<{i}>::State>>);
22 type Output = ByteStream;
23
24 fn extract(
25 &self,
26 input: ByteStream,
27 state: Option<Self::State>,
28 last: bool,
29 ) -> ParseResult<Self::State, Self::Output> {
30 let mut exhausted = true;
31 let mut state = state.unwrap_or(typle_for!(.. => Some(None)));
32 for typle_index!(i) in 0..T::LEN {
33 if let Some(inner_state) = &mut state[[i]] {
34 let input = input.clone();
35 match self.tuple[[i]].extract(input, inner_state.take(), last) {
36 ParseResult::NoMatch(_) => {
37 state[[i]] = None;
38 }
39 ParseResult::Partial(new_state) => {
40 *inner_state = Some(new_state);
41 if !last {
42 exhausted = false;
43 }
44 }
45 ParseResult::Match(output, input) => {
46 return ParseResult::Match(output, input);
47 }
48 }
49 }
50 }
51 if exhausted {
52 ParseResult::NoMatch(input.position())
53 } else {
54 ParseResult::Partial(state)
55 }
56 }
57}
58
59#[typle(Tuple for 1..=12)]
60impl<T> Repeatable for TupleAny<T>
61where
62 T: Tuple,
63 T<_>: Extract<Output = ByteStream>,
64{
65}
66
67#[typle(Tuple for 1..=12)]
68impl<T> OutputToByteStream for TupleAny<T>
69where
70 T: Tuple,
71 T<_>: Extract<Output = ByteStream>,
72{
73 fn output_to_bytestream(output: Self::Output) -> ByteStream {
74 output
75 }
76}
77
78pub struct TupleFirst<T> {
79 tuple: T,
80}
81
82#[typle(Tuple for 1..=12)]
83impl<T> Extract for TupleFirst<T>
84where
85 T: Tuple,
86 T<_>: Extract<Output = ByteStream>,
87{
88 type State = typle_for!(i in .. => Option<ParseResult<T<{i}>::State, ByteStream>>);
91 type Output = ByteStream;
92
93 fn extract(
94 &self,
95 input: ByteStream,
96 state: Option<Self::State>,
97 last: bool,
98 ) -> ParseResult<Self::State, Self::Output> {
99 let mut first = true;
100 let mut state = state.unwrap_or(typle_for!(.. => None));
101 for typle_index!(i) in 0..T::LEN {
102 state[[i]] = match state[[i]].take() {
103 Some(ParseResult::NoMatch(position)) => Some(ParseResult::NoMatch(position)),
104 Some(ParseResult::Partial(inner_state)) => {
105 let res = self.tuple[[i]].extract(input.clone(), Some(inner_state), last);
106 match res {
107 ParseResult::NoMatch(position) => Some(ParseResult::NoMatch(position)),
108 ParseResult::Partial(state) => {
109 if !last {
110 first = false;
111 }
112 Some(ParseResult::Partial(state))
113 }
114 ParseResult::Match(output, input) => {
115 if first {
116 return ParseResult::Match(output, input);
117 }
118 Some(ParseResult::Match(output, input))
119 }
120 }
121 }
122 Some(ParseResult::Match(output, input)) => {
123 if first {
124 return ParseResult::Match(output, input);
125 }
126 Some(ParseResult::Match(output, input))
127 }
128 None => {
129 let res = self.tuple[[i]].extract(input.clone(), None, last);
130 match res {
131 ParseResult::NoMatch(position) => Some(ParseResult::NoMatch(position)),
132 ParseResult::Partial(state) => {
133 if !last {
134 first = false;
135 }
136 Some(ParseResult::Partial(state))
137 }
138 ParseResult::Match(output, input) => {
139 if first {
140 return ParseResult::Match(output, input);
141 }
142 Some(ParseResult::Match(output, input))
143 }
144 }
145 }
146 };
147 }
148 if first {
149 ParseResult::NoMatch(input.position())
150 } else {
151 ParseResult::Partial(state)
152 }
153 }
154}
155
156#[typle(Tuple for 1..=12)]
157impl<T> Repeatable for TupleFirst<T>
158where
159 T: Tuple,
160 T<_>: Extract<Output = ByteStream>,
161{
162}
163
164#[typle(Tuple for 1..=12)]
165impl<T> OutputToByteStream for TupleFirst<T>
166where
167 T: Tuple,
168 T<_>: Extract<Output = ByteStream>,
169{
170 fn output_to_bytestream(output: Self::Output) -> ByteStream {
171 output
172 }
173}
174
175#[typle(Tuple for 1..=12)]
176pub enum TupleSequenceState<T>
177where
178 T: Tuple,
179 T<_>: Extract,
180{
181 S = typle_variant!(i in ..T::MAX =>
182 typle_for!(j in ..i => T::<{j}>::Output), Option<T<{i}>::State>
183 ),
184}
185
186pub struct TupleSequence<T> {
187 tuple: T,
188}
189
190#[typle(Tuple for 1..=12, never=std::convert::Infallible)]
191impl<T> Extract for TupleSequence<T>
192where
193 T: Tuple,
194 T<_>: Extract,
195{
196 type State = TupleSequenceState<T<{ ..T::MAX }>>;
199 type Output = typle_for!(i in .. => <T<{i}> as Extract>::Output);
200
201 fn extract(
202 &self,
203 mut input: ByteStream,
204 state: Option<Self::State>,
205 last: bool,
206 ) -> ParseResult<Self::State, Self::Output> {
207 let default_position = input.position();
208 #[typle_attr_if(T::LEN == 1, allow(unused_mut))]
209 let mut state = state.unwrap_or(Self::State::S::<typle_ident!(0)>((), None));
210 for typle_index!(i) in 0..T::LEN {
211 if let Self::State::S::<typle_ident!(i)>(output, inner_state) = state {
212 match self.tuple[[i]].extract(input, inner_state, last) {
213 ParseResult::NoMatch(position) => {
214 return ParseResult::NoMatch(position);
215 }
216 ParseResult::Partial(inner_state) => {
217 if last {
218 return ParseResult::NoMatch(default_position);
219 } else {
220 return ParseResult::Partial(Self::State::S::<typle_ident!(i)>(
221 output,
222 Some(inner_state),
223 ));
224 }
225 }
226 ParseResult::Match(matched, remain) => {
227 let output = (output[[..i]], matched);
229 input = remain;
230 if typle_const!(i + 1 == T::LEN) {
231 return ParseResult::Match(output, input);
232 } else {
233 state = Self::State::S::<typle_ident!(i + 1)>(output, None);
234 }
235 }
236 }
237 }
238 }
239 unreachable!();
240 }
241}
242
243#[typle(Tuple for 1..=12)]
244impl<T> Repeatable for TupleSequence<T>
245where
246 T: Tuple,
247 T<_>: Extract,
248{
249}
250
251#[typle(Tuple for 1..=12)]
252impl<T> OutputToByteStream for TupleSequence<T>
253where
254 T: Tuple,
255 T<_>: OutputToByteStream,
256{
257 fn output_to_bytestream(output: Self::Output) -> ByteStream {
258 #[typle_attr_if(T::LEN == 1, allow(unused_mut))]
259 let mut byte_stream = T::<0>::output_to_bytestream(output.0);
260 for typle_index!(i) in 1..T::LEN {
261 byte_stream.merge(T::<{ i }>::output_to_bytestream(output[[i]]));
262 }
263 byte_stream
264 }
265}
266
267pub trait ExtractTuple {
268 type TupleAny;
269 type TupleFirst;
270 type TupleSequence;
271
272 fn any(self) -> Self::TupleAny;
273
274 fn first(self) -> Self::TupleFirst;
275
276 fn seq(self) -> Self::TupleSequence;
277}
278
279#[typle(Tuple for 1..=12)]
280impl<T> ExtractTuple for T
281where
282 T: Tuple,
283 T<_>: Extract,
284{
285 type TupleAny = TupleAny<T>;
286 type TupleFirst = TupleFirst<T>;
287 type TupleSequence = TupleSequence<T>;
288
289 fn any(self) -> Self::TupleAny {
290 TupleAny { tuple: self }
291 }
292
293 fn first(self) -> Self::TupleFirst {
294 TupleFirst { tuple: self }
295 }
296
297 fn seq(self) -> Self::TupleSequence {
298 TupleSequence { tuple: self }
299 }
300}
301
302#[cfg(test)]
303mod tests {
304 use crate::byte_stream::ByteStream;
305 use crate::repeatable::Repeatable;
306 use crate::{Extract, ExtractTuple, ParseResult, ParseWhen};
307
308 #[test]
309 fn test_sequence() {
310 let input = ByteStream::from("hello3a");
311 let ParseResult::Match((out1, out2, out3), input) = (
312 "hello",
313 char::when(|c: char| c.is_ascii_digit()),
314 char::when(char::is_alphabetic),
315 )
316 .seq()
317 .extract(input, None, true)
318 else {
319 panic!()
320 };
321 assert_eq!(out1.to_string(), "hello");
322 assert_eq!(out2.to_string(), "3");
323 assert_eq!(out3.to_string(), "a");
324 assert!(input.is_empty());
325
326 let mut buffer = ByteStream::from("hello3a");
327 let input = buffer.take_before(3);
328 let ParseResult::Partial(state) = ("hello", char::when(char::is_alphabetic))
329 .seq()
330 .extract(input, None, false)
331 else {
332 panic!()
333 };
334 let ParseResult::NoMatch(5) =
335 ("hello", char::when(char::is_alphabetic))
336 .seq()
337 .extract(buffer, Some(state), false)
338 else {
339 panic!()
340 };
341 }
342
343 #[test]
344 fn test_optional_sequence() {
345 let input = ByteStream::from("hello, world!");
346 let ParseResult::Match((out1, out2), input) =
347 ("hello", char::when(|c: char| c.is_ascii_digit()))
348 .seq()
349 .optional()
350 .extract(input, None, true)
351 else {
352 panic!()
353 };
354 assert!(out1.is_empty());
355 assert!(out2.is_empty());
356 assert_eq!(input.to_string(), "hello, world!");
357
358 let ParseResult::Match((out1, out2), input) = ("hello, ", "world!")
359 .seq()
360 .optional()
361 .extract(input, None, true)
362 else {
363 panic!()
364 };
365 assert_eq!(out1.to_string(), "hello, ");
366 assert_eq!(out2.to_string(), "world!");
367 assert!(input.is_empty());
368 }
369
370 #[test]
371 fn test_any() {
372 let input = ByteStream::from("hello3a");
373 let ParseResult::Match(output, input) = ("hello", char::when(|c: char| c.is_ascii_digit()))
374 .any()
375 .extract(input, None, false)
376 else {
377 panic!()
378 };
379 assert_eq!(output.to_string(), "hello");
380 let ParseResult::Match(output, input) = ("hello", char::when(|c: char| c.is_ascii_digit()))
381 .any()
382 .extract(input, None, true)
383 else {
384 panic!()
385 };
386 assert_eq!(output.to_string(), "3");
387 assert_eq!(input.to_string(), "a");
388 }
389
390 #[test]
391 fn test_first() {
392 let input = ByteStream::from("hello3a");
393 let ParseResult::Match(output, input) = ("hello", char::when(|c: char| c.is_ascii_digit()))
394 .first()
395 .extract(input, None, false)
396 else {
397 panic!()
398 };
399 assert_eq!(output.to_string(), "hello");
400 let ParseResult::Match(output, input) = ("hello", char::when(|c: char| c.is_ascii_digit()))
401 .first()
402 .extract(input, None, true)
403 else {
404 panic!()
405 };
406 assert_eq!(output.to_string(), "3");
407 assert_eq!(input.to_string(), "a");
408 }
409
410 #[test]
413 fn test_precedence_any() {
414 let mut buffer = ByteStream::from("hello3a");
415 let input = buffer.take_before(3);
416 let ParseResult::Match(output, input) = ("hello", char::when(char::is_alphabetic))
417 .any()
418 .extract(input, None, false)
419 else {
420 panic!()
421 };
422 assert_eq!(output.to_string(), "h");
423 assert_eq!(input.to_string(), "el");
424 }
425
426 #[test]
429 fn test_precedence_first() {
430 let mut buffer = ByteStream::from("hello3a");
431 let input = buffer.take_before(3);
432 let ParseResult::Partial(state) = ("hello", char::when(char::is_alphabetic))
433 .first()
434 .extract(input, None, false)
435 else {
436 panic!()
437 };
438 let ParseResult::Match(output, input) = ("hello", char::when(char::is_alphabetic))
439 .first()
440 .extract(buffer, Some(state), false)
441 else {
442 panic!()
443 };
444 assert_eq!(output.to_string(), "hello");
445 assert_eq!(input.to_string(), "3a");
446 }
447}