oni_comb_parser/primitive/
take_while_n_m.rs1use core::marker::PhantomData;
2
3use crate::error::{ExpectError, Expected};
4use crate::fail::{Fail, PResult};
5use crate::input::Input;
6use crate::parser::Parser;
7
8pub struct TakeWhileNM<F, I: Input> {
9 min: usize,
10 max: usize,
11 f: F,
12 _marker: PhantomData<fn(&mut I)>,
13}
14
15pub fn take_while_n_m<I: Input, F: FnMut(I::Token) -> bool>(min: usize, max: usize, f: F) -> TakeWhileNM<F, I> {
16 TakeWhileNM {
17 min,
18 max,
19 f,
20 _marker: PhantomData,
21 }
22}
23
24impl<I: Input, F> Parser<I> for TakeWhileNM<F, I>
25where
26 F: FnMut(I::Token) -> bool,
27{
28 type Error = I::Error;
29 type Output = I::Slice;
30
31 #[inline]
32 fn parse_next(&mut self, input: &mut I) -> PResult<I::Slice, I::Error> {
33 let pos = input.offset();
34 let cp = input.checkpoint();
35 let mut count = 0;
36 while count < self.max {
37 let item_cp = input.checkpoint();
38 match input.next_token() {
39 Some(t) if (self.f)(t) => {
40 count += 1;
41 }
42 Some(_) => {
43 input.reset(item_cp);
44 break;
45 }
46 None => break,
47 }
48 }
49 if count < self.min {
50 input.reset(cp);
51 return Err(Fail::Backtrack(I::Error::from_expected(
52 pos,
53 Expected::Description("not enough matching tokens"),
54 )));
55 }
56 Ok(input.slice_since(cp))
57 }
58}