1use super::{Error, Result};
2use crate::{
3 range::RangeArgument,
4 set::Set,
5};
6use std::{
7 fmt::{Debug, Display},
8 ops::{Add, BitOr, Mul, Neg, Not, Shr, Sub},
9 ops::Bound::{Included, Excluded, Unbounded},
10};
11
12type Parse<'a, I, O> = dyn Fn(&'a [I], usize) -> Result<(O, usize)> + 'a;
13
14pub struct Parser<'a, I, O> {
16 pub method: Box<Parse<'a, I, O>>,
17}
18
19impl<'a, I, O> Parser<'a, I, O> {
20 pub fn new<P>(parse: P) -> Self
22 where
23 P: Fn(&'a [I], usize) -> Result<(O, usize)> + 'a,
24 {
25 Self {
26 method: Box::new(parse),
27 }
28 }
29
30 pub fn parse(&self, input: &'a [I]) -> Result<O> {
32 (self.method)(input, 0).map(|(out, _)| out)
33 }
34
35 pub fn parse_at(&self, input: &'a [I], start: usize) -> Result<(O, usize)> {
37 (self.method)(input, start)
38 }
39
40 pub fn map<U, F>(self, f: F) -> Parser<'a, I, U>
42 where
43 F: Fn(O) -> U + 'a,
44 I: 'a,
45 O: 'a,
46 U: 'a,
47 {
48 Parser::new(move |input: &'a [I], start: usize| {
49 (self.method)(input, start).map(|(out, pos)| (f(out), pos))
50 })
51 }
52
53 pub fn convert<U, E, F>(self, f: F) -> Parser<'a, I, U>
55 where
56 F: Fn(O) -> ::std::result::Result<U, E> + 'a,
57 E: Debug,
58 O: 'a,
59 U: 'a,
60 {
61 Parser::new(move |input: &'a [I], start: usize| {
62 (self.method)(input, start).and_then(|(res, pos)| match f(res) {
63 Ok(out) => Ok((out, pos)),
64 Err(err) => Err(Error::Conversion {
65 message: format!("Conversion error: {:?}", err),
66 position: start,
67 }),
68 })
69 })
70 }
71
72 pub fn cache(self) -> Self
74 where
75 O: Clone + 'a,
76 {
77 use std::{cell::RefCell, collections::HashMap};
78 let results = RefCell::new(HashMap::new());
79 Self::new(move |input: &'a [I], start: usize| {
80 let key = (start, format!("{:p}", &self.method));
81 results
82 .borrow_mut()
83 .entry(key)
84 .or_insert_with(|| (self.method)(input, start))
85 .clone()
86 })
87 }
88
89 pub fn pos(self) -> Parser<'a, I, usize>
91 where
92 O: 'a,
93 {
94 Parser::new(move |input: &'a [I], start: usize| {
95 (self.method)(input, start).map(|(_, pos)| (pos, pos))
96 })
97 }
98
99 pub fn collect(self) -> Parser<'a, I, &'a [I]>
101 where
102 O: 'a,
103 {
104 Parser::new(move |input: &'a [I], start: usize| {
105 (self.method)(input, start).map(|(_, end)| (&input[start..end], end))
106 })
107 }
108
109 pub fn discard(self) -> Parser<'a, I, ()>
111 where
112 O: 'a,
113 {
114 Parser::new(move |input: &'a [I], start: usize| {
115 (self.method)(input, start).map(|(_, end)| ((), end))
116 })
117 }
118
119 pub fn opt(self) -> Parser<'a, I, Option<O>>
121 where
122 O: 'a,
123 {
124 Parser::new(
125 move |input: &'a [I], start: usize| match (self.method)(input, start) {
126 Ok((out, pos)) => Ok((Some(out), pos)),
127 Err(_) => Ok((None, start)),
128 },
129 )
130 }
131
132 pub fn repeat<R>(self, range: R) -> Parser<'a, I, Vec<O>>
137 where
138 R: RangeArgument<usize> + Debug + 'a,
139 O: 'a,
140 {
141 Parser::new(move |input: &'a [I], start: usize| {
142 let mut items = vec![];
143 let mut pos = start;
144 loop {
145 match range.end() {
146 Included(&max_count) => {
147 if items.len() >= max_count {
148 break;
149 }
150 }
151 Excluded(&max_count) => {
152 if items.len() + 1 >= max_count {
153 break;
154 }
155 }
156 Unbounded => (),
157 }
158
159 let Ok((item, item_pos)) = (self.method)(input, pos) else { break };
160 items.push(item);
161 pos = item_pos;
162 }
163 if let Included(&min_count) = range.start() {
164 if items.len() < min_count {
165 return Err(Error::Mismatch {
166 message: format!(
167 "expect repeat at least {} times, found {} times",
168 min_count,
169 items.len()
170 ),
171 position: start,
172 });
173 }
174 }
175 Ok((items, pos))
176 })
177 }
178
179 #[cfg(not(feature = "trace"))]
180 pub fn name(self, name: &'a str) -> Self
182 where
183 O: 'a,
184 {
185 Parser::new(
186 move |input: &'a [I], start: usize| match (self.method)(input, start) {
187 res @ Ok(_) => res,
188 Err(err) => match err {
189 Error::Custom { .. } => Err(err),
190 _ => Err(Error::Custom {
191 message: format!("failed to parse {}", name),
192 position: start,
193 inner: Some(Box::new(err)),
194 }),
195 },
196 },
197 )
198 }
199
200 #[cfg(feature = "trace")]
201 pub fn name(self, name: &'a str) -> Self
203 where
204 O: 'a,
205 {
206 Parser::new(
207 move |input: &'a [I], start: usize| {
208 println!("parse: {} ({})", name, start);
209 match (self.method)(input, start) {
210 res @ Ok(_) => {
211 println!(" {} ({}): ok", name, start);
212 res
213 },
214 Err(err) => {
215 println!(" {} ({}): error", name, start);
216 match err {
217 Error::Custom { .. } => Err(err),
218 _ => Err(Error::Custom {
219 message: format!("failed to parse {}", name),
220 position: start,
221 inner: Some(Box::new(err)),
222 }),
223 }
224 },
225 }
226 },
227 )
228 }
229
230 pub fn expect(self, name: &'a str) -> Self
232 where
233 O: 'a,
234 {
235 Parser::new(
236 move |input: &'a [I], start: usize| match (self.method)(input, start) {
237 res @ Ok(_) => res,
238 Err(err) => Err(Error::Expect {
239 message: format!("Expect {}", name),
240 position: start,
241 inner: Box::new(err),
242 }),
243 },
244 )
245 }
246}
247
248pub fn empty<'a, I>() -> Parser<'a, I, ()> {
250 Parser::new(|_: &[I], start: usize| Ok(((), start)))
251}
252
253pub fn any<'a, I>() -> Parser<'a, I, I>
255where
256 I: Clone,
257{
258 Parser::new(|input: &[I], start: usize| {
259 let Some(s) = input.get(start) else {
260 return Err(Error::Mismatch {
261 message: "end of input reached".to_owned(),
262 position: start,
263 })
264 };
265 Ok((s.clone(), start + 1))
266 })
267}
268
269pub fn sym<'a, I>(t: I) -> Parser<'a, I, I>
271where
272 I: Clone + PartialEq + Display,
273{
274 Parser::new(move |input: &'a [I], start: usize| {
275 let Some(s) = input.get(start) else { return Err(Error::Incomplete) };
276 if t != *s {
277 return Err(Error::Mismatch {
278 message: format!("expect: {}, found: {}", t, s),
279 position: start,
280 });
281 }
282 Ok((s.clone(), start + 1))
283 })
284}
285
286pub fn seq<'a, 'b: 'a, I>(tag: &'b [I]) -> Parser<'a, I, &'a [I]>
288where
289 I: PartialEq + Debug,
290{
291 Parser::new(move |input: &'a [I], start: usize| {
292 let mut index = 0;
293 loop {
294 let pos = start + index;
295 if index == tag.len() {
296 return Ok((tag, pos));
297 }
298 let Some(s) = input.get(pos) else { return Err(Error::Incomplete) };
299 if tag[index] != *s {
300 return Err(Error::Mismatch {
301 message: format!("seq {:?} expect: {:?}, found: {:?}", tag, tag[index], s),
302 position: pos,
303 });
304 }
305 index += 1;
306 }
307 })
308}
309
310pub fn tag<'a, 'b: 'a>(tag: &'b str) -> Parser<'a, char, &'a str> {
312 Parser::new(move |input: &'a [char], start: usize| {
313 let mut pos = start;
314 for c in tag.chars() {
315 let Some(&s) = input.get(pos) else { return Err(Error::Incomplete) };
316 if c != s {
317 return Err(Error::Mismatch {
318 message: format!("tag {:?} expect: {:?}, found: {}", tag, c, s),
319 position: pos,
320 });
321 }
322 pos += 1;
323 }
324 Ok((tag, pos))
325 })
326}
327
328pub fn list<'a, I, O, U>(
330 parser: Parser<'a, I, O>,
331 separator: Parser<'a, I, U>,
332) -> Parser<'a, I, Vec<O>>
333where
334 O: 'a,
335 U: 'a,
336{
337 Parser::new(move |input: &'a [I], start: usize| {
338 let mut items = vec![];
339 let mut pos = start;
340 if let Ok((first_item, first_pos)) = (parser.method)(input, pos) {
341 items.push(first_item);
342 pos = first_pos;
343 while let Ok((_, sep_pos)) = (separator.method)(input, pos) {
344 match (parser.method)(input, sep_pos) {
345 Ok((more_item, more_pos)) => {
346 items.push(more_item);
347 pos = more_pos;
348 }
349 Err(_) => break,
350 }
351 }
352 }
353 Ok((items, pos))
354 })
355}
356
357pub fn one_of<'a, I, S>(set: &'a S) -> Parser<'a, I, I>
359where
360 I: Clone + PartialEq + Display + Debug,
361 S: Set<I> + ?Sized,
362{
363 Parser::new(move |input: &'a [I], start: usize| {
364 let Some(s) = input.get(start) else {return Err(Error::Incomplete) };
365 if !set.contains(s) {
366 return Err(Error::Mismatch {
367 message: format!("expect one of: {}, found: {}", set.to_str(), s),
368 position: start,
369 });
370 };
371 Ok((s.clone(), start + 1))
372 })
373}
374
375pub fn none_of<'a, I, S>(set: &'static S) -> Parser<'a, I, I>
377where
378 I: Clone + PartialEq + Display + Debug,
379 S: Set<I> + ?Sized,
380{
381 Parser::new(move |input: &'a [I], start: usize| {
382 let Some(s) = input.get(start) else {return Err(Error::Incomplete) };
383 if set.contains(s) {
384 return Err(Error::Mismatch {
385 message: format!("expect none of: {}, found: {}", set.to_str(), s),
386 position: start,
387 });
388 }
389 Ok((s.clone(), start + 1))
390 })
391}
392
393pub fn is_a<'a, I, F>(predicate: F) -> Parser<'a, I, I>
395where
396 I: Clone + PartialEq + Display + Debug,
397 F: Fn(I) -> bool + 'a,
398{
399 Parser::new(move |input: &'a [I], start: usize| {
400 let Some(s) = input.get(start) else { return Err(Error::Incomplete) };
401 if !predicate(s.clone()) {
402 return Err(Error::Mismatch {
403 message: format!("is_a predicate failed on: {}", s),
404 position: start,
405 });
406 }
407 Ok((s.clone(), start + 1))
408 })
409}
410
411pub fn not_a<'a, I, F>(predicate: F) -> Parser<'a, I, I>
413where
414 I: Clone + PartialEq + Display + Debug,
415 F: Fn(I) -> bool + 'a,
416{
417 Parser::new(move |input: &'a [I], start: usize| {
418 let Some(s) = input.get(start) else { return Err(Error::Incomplete) };
419 if predicate(s.clone()) {
420 return Err(Error::Mismatch {
421 message: format!("not_a predicate failed on: {}", s),
422 position: start,
423 });
424 }
425 Ok((s.clone(), start + 1))
426 })
427}
428
429pub fn take<'a, I>(n: usize) -> Parser<'a, I, &'a [I]> {
431 Parser::new(move |input: &'a [I], start: usize| {
432 let pos = start + n;
433 if input.len() < pos {
434 return Err(Error::Incomplete);
435 }
436 Ok((&input[start..pos], pos))
437 })
438}
439
440pub fn skip<'a, I>(n: usize) -> Parser<'a, I, ()> {
442 Parser::new(move |input: &'a [I], start: usize| {
443 let pos = start + n;
444 if input.len() < pos {
445 return Err(Error::Incomplete);
446 }
447 Ok(((), pos))
448 })
449}
450
451pub fn call<'a, I, O, F>(parser_factory: F) -> Parser<'a, I, O>
453where
454 O: 'a,
455 F: Fn() -> Parser<'a, I, O> + 'a,
456{
457 Parser::new(move |input: &'a [I], start: usize| {
458 let parser = parser_factory();
459 (parser.method)(input, start)
460 })
461}
462
463pub fn end<'a, I>() -> Parser<'a, I, ()>
465where
466 I: Display,
467{
468 Parser::new(|input: &'a [I], start: usize| {
469 if let Some(s) = input.get(start) {
470 return Err(Error::Mismatch {
471 message: format!("expect end of input, found: {}", s),
472 position: start,
473 });
474 }
475 Ok(((), start))
476 })
477}
478
479impl<'a, I, O: 'a, U: 'a> Add<Parser<'a, I, U>> for Parser<'a, I, O> {
481 type Output = Parser<'a, I, (O, U)>;
482
483 fn add(self, other: Parser<'a, I, U>) -> Self::Output {
484 Parser::new(move |input: &'a [I], start: usize| {
485 (self.method)(input, start).and_then(|(out1, pos1)| {
486 (other.method)(input, pos1).map(|(out2, pos2)| ((out1, out2), pos2))
487 })
488 })
489 }
490}
491
492impl<'a, I, O: 'a, U: 'a> Sub<Parser<'a, I, U>> for Parser<'a, I, O> {
494 type Output = Parser<'a, I, O>;
495
496 fn sub(self, other: Parser<'a, I, U>) -> Self::Output {
497 Parser::new(move |input: &'a [I], start: usize| {
498 (self.method)(input, start)
499 .and_then(|(out1, pos1)| (other.method)(input, pos1).map(|(_, pos2)| (out1, pos2)))
500 })
501 }
502}
503
504impl<'a, I: 'a, O: 'a, U: 'a> Mul<Parser<'a, I, U>> for Parser<'a, I, O> {
506 type Output = Parser<'a, I, U>;
507
508 fn mul(self, other: Parser<'a, I, U>) -> Self::Output {
509 Parser::new(move |input: &'a [I], start: usize| {
510 (self.method)(input, start)
511 .and_then(|(_, pos1)| (other.method)(input, pos1).map(|(out2, pos2)| (out2, pos2)))
512 })
513 }
514}
515
516impl<'a, I, O: 'a, U: 'a, F: Fn(O) -> Parser<'a, I, U> + 'a> Shr<F> for Parser<'a, I, O> {
518 type Output = Parser<'a, I, U>;
519
520 fn shr(self, other: F) -> Self::Output {
521 Parser::new(move |input: &'a [I], start: usize| {
522 (self.method)(input, start).and_then(|(out, pos)| (other(out).method)(input, pos))
523 })
524 }
525}
526
527impl<'a, I, O: 'a> BitOr for Parser<'a, I, O> {
529 type Output = Parser<'a, I, O>;
530
531 fn bitor(self, other: Parser<'a, I, O>) -> Self::Output {
532 Parser::new(
533 move |input: &'a [I], start: usize| match (self.method)(input, start) {
534 Ok(out) => Ok(out),
535 Err(err) => match err {
536 Error::Expect { .. } => Err(err),
537 _ => (other.method)(input, start),
538 },
539 },
540 )
541 }
542}
543
544impl<'a, I, O: 'a> Neg for Parser<'a, I, O> {
546 type Output = Parser<'a, I, bool>;
547
548 fn neg(self) -> Self::Output {
549 Parser::new(move |input: &'a [I], start: usize| {
550 (self.method)(input, start).map(|_| (true, start))
551 })
552 }
553}
554
555impl<'a, I, O: 'a> Not for Parser<'a, I, O> {
557 type Output = Parser<'a, I, bool>;
558
559 fn not(self) -> Self::Output {
560 Parser::new(
561 move |input: &'a [I], start: usize| match (self.method)(input, start) {
562 Ok(_) => Err(Error::Mismatch {
563 message: "not predicate failed".to_string(),
564 position: start,
565 }),
566 Err(_) => Ok((true, start)),
567 },
568 )
569 }
570}
571
572#[cfg(test)]
573mod tests {
574 use crate::parser::*;
575 use crate::Error;
576
577 #[test]
578 fn byte_works() {
579 let input = b"abcde";
580 let parser = sym(b'a') + one_of(b"ab") - sym(b'C');
581 let output = parser.parse(input);
582 assert_eq!(
583 output,
584 Err(Error::Mismatch {
585 message: "expect: 67, found: 99".to_string(),
586 position: 2
587 })
588 );
589
590 let parser = sym(b'a') * none_of(b"AB") - sym(b'c') + seq(b"de");
591 let output = parser.parse(input);
592 assert_eq!(output, Ok((b'b', &b"de"[..])));
593 assert_eq!(parser.pos().parse(input), Ok(5));
594
595 let parser = sym(b'e') | sym(b'd').expect("d") | empty().map(|_| b'0');
596 let output = parser.parse(input);
597 assert_eq!(
598 output,
599 Err(Error::Expect {
600 message: "Expect d".to_owned(),
601 position: 0,
602 inner: Box::new(Error::Mismatch {
603 message: "expect: 100, found: 97".to_string(),
604 position: 0
605 })
606 })
607 );
608 }
609
610 #[test]
611 fn char_works() {
612 let input = "abcd".chars().collect::<Vec<char>>();
613 let parser = tag("ab") + sym('c') | sym('d').map(|_| ("", '0'));
614 let output = parser.parse(&input);
615 assert_eq!(output, Ok(("ab", 'c')));
616 }
617
618 #[test]
619 fn recursive_parser() {
620 #[derive(Debug, PartialEq)]
621 enum Expr {
622 Empty,
623 Group(Box<Expr>),
624 }
625 fn expr() -> Parser<'static, u8, Expr> {
626 (sym(b'(') + call(expr) - sym(b')')).map(|(_, e)| Expr::Group(Box::new(e)))
627 | empty().map(|_| Expr::Empty)
628 }
629 let input = b"(())";
630 let parser = expr();
631 let output = parser.parse(input);
632 assert_eq!(
633 output,
634 Ok(Expr::Group(Box::new(Expr::Group(Box::new(Expr::Empty)))))
635 );
636 }
637
638 #[test]
639 fn chain_parser() {
640 let input = b"5oooooooo";
641 {
642 let parser = one_of(b"0123456789").map(|c| c - b'0')
643 >> |n| take(n as usize) + sym(b'o').repeat(0..);
644 assert_eq!(parser.parse(input), Ok((&b"ooooo"[..], vec![b'o'; 3])));
645 }
646 {
647 let parser =
648 skip(1) * take(3) >> |v: &'static [u8]| take(v.len() + 2).map(move |u| (u, v));
649 assert_eq!(parser.parse(input), Ok((&b"ooooo"[..], &b"ooo"[..])));
650 }
651 {
652 let parser = Parser::new(move |input, start| {
653 (skip(1) * take(3))
654 .parse_at(input, start)
655 .and_then(|(v, pos)| {
656 take(v.len() + 2)
657 .parse_at(input, pos)
658 .map(|(u, end)| ((u, v), end))
659 })
660 });
661 assert_eq!(parser.parse(input), Ok((&b"ooooo"[..], &b"ooo"[..])));
662 }
663 }
664
665 #[test]
666 fn repeat_at_least() {
667 let input = b"xxxooo";
668
669 {
670 let parser = sym(b'x').repeat(1..2);
671 let output = parser.parse(input);
672 assert_eq!(output, Ok(vec![b'x'; 1]))
673 }
674
675 {
676 let parser = sym(b'x').repeat(1..);
677 let output = parser.parse(input);
678 assert_eq!(output, Ok(vec![b'x'; 3]))
679 }
680
681 {
682 let parser = sym(b'x').repeat(0..);
683 let output = parser.parse(input);
684 assert_eq!(output, Ok(vec![b'x'; 3]))
685 }
686
687 {
688 let parser = sym(b'y').repeat(0..);
689 let output = parser.parse(input);
690 assert_eq!(output, Ok(vec![]))
691 }
692
693 {
694 let parser = sym(b'y').repeat(1..);
695 let output = parser.parse(input);
696 assert!(output.is_err());
697 }
698
699 {
700 let parser = sym(b'x').repeat(10..);
701 let output = parser.parse(input);
702 assert!(output.is_err());
703 }
704 }
705
706 #[test]
707 fn repeat_up_to() {
708 let input = b"xxxooo";
709
710 {
711 let parser = sym(b'x').repeat(..2);
712 let output = parser.parse(input);
713 assert_eq!(output, Ok(vec![b'x'; 1]))
714 }
715
716 {
717 let parser = sym(b'x').repeat(..4);
718 let output = parser.parse(input);
719 assert_eq!(output, Ok(vec![b'x'; 3]))
720 }
721
722 {
723 let parser = sym(b'x').repeat(..);
724 let output = parser.parse(input);
725 assert_eq!(output, Ok(vec![b'x'; 3]))
726 }
727
728 {
729 let parser = sym(b'x').repeat(..0);
730 let output = parser.parse(input);
731 assert_eq!(output, Ok(vec![]))
732 }
733
734 {
735 let parser = sym(b'x').repeat(..10);
736 let output = parser.parse(input);
737 assert_eq!(output, Ok(vec![b'x'; 3]))
738 }
739 }
740
741 #[test]
742 fn repeat_up_to_inclusive() {
743 let input = b"xxxooo";
744
745 {
746 let parser = sym(b'x').repeat(..=2);
747 let output = parser.parse(input);
748 assert_eq!(output, Ok(vec![b'x'; 2]))
749 }
750
751 {
752 let parser = sym(b'x').repeat(..=4);
753 let output = parser.parse(input);
754 assert_eq!(output, Ok(vec![b'x'; 3]))
755 }
756
757 {
758 let parser = sym(b'x').repeat(..=0);
759 let output = parser.parse(input);
760 assert_eq!(output, Ok(vec![]))
761 }
762
763 {
764 let parser = sym(b'x').repeat(..=10);
765 let output = parser.parse(input);
766 assert_eq!(output, Ok(vec![b'x'; 3]))
767 }
768 }
769
770 #[test]
771 fn repeat_from_to_inclusive() {
772 let input = b"xxxooo";
773
774 {
775 let parser = sym(b'x').repeat(1..=2);
776 let output = parser.parse(input);
777 assert_eq!(output, Ok(vec![b'x'; 2]))
778 }
779
780 {
781 let parser = sym(b'x').repeat(1..=4);
782 let output = parser.parse(input);
783 assert_eq!(output, Ok(vec![b'x'; 3]))
784 }
785
786 {
787 let parser = sym(b'x').repeat(0..=0);
788 let output = parser.parse(input);
789 assert_eq!(output, Ok(vec![]))
790 }
791
792 {
793 let parser = sym(b'x').repeat(3..=10);
794 let output = parser.parse(input);
795 assert_eq!(output, Ok(vec![b'x'; 3]))
796 }
797
798 {
799 let parser = sym(b'x').repeat(4..=10);
800 let output = parser.parse(input);
801 assert!(output.is_err())
802 }
803 }
804
805 #[test]
806 fn repeat_exactly() {
807 let input = b"xxxooo";
808
809 {
810 let parser = sym(b'x').repeat(0);
811 let output = parser.parse(input);
812 assert_eq!(output, Ok(vec![]))
813 }
814
815 {
816 let parser = sym(b'x').repeat(1);
817 let output = parser.parse(input);
818 assert_eq!(output, Ok(vec![b'x'; 1]))
819 }
820
821 {
822 let parser = sym(b'x').repeat(2);
823 let output = parser.parse(input);
824 assert_eq!(output, Ok(vec![b'x'; 2]))
825 }
826
827 {
828 let parser = sym(b'x').repeat(3);
829 let output = parser.parse(input);
830 assert_eq!(output, Ok(vec![b'x'; 3]))
831 }
832
833 {
834 let parser = sym(b'x').repeat(4);
835 let output = parser.parse(input);
836 assert!(output.is_err())
837 }
838 }
839
840 #[cfg(not(feature = "trace"))]
841 #[test]
842 fn named() {
843 let input = b"xxxooo";
844
845 {
846 let parser = sym(b'x').repeat(3);
847 let output = parser.name("name_test_ok").parse(input);
848 assert_eq!(output, Ok(vec![b'x'; 3]))
849 }
850
851 {
852 let parser = sym(b'x').repeat(4);
853 let output = parser.name("name_test_err").parse(input);
854 assert_eq!(output, Err(
855 Error::Custom {
856 message: "failed to parse name_test_err".into(),
857 position: 0,
858 inner: Some(Box::new(Error::Mismatch {
859 message: "expect repeat at least 4 times, found 3 times".into(),
860 position: 0
861 }))
862 }
863 ))
864 }
865 }
866
867 #[cfg(feature = "trace")]
868 #[test]
869 fn named() {
872 let input = b"xxxooo";
873
874 {
875 let parser = sym(b'x').repeat(3);
876 let output = parser.name("name_test_ok").parse(input);
877 assert_eq!(output, Ok(vec![b'x'; 3]))
878 }
879
880 {
881 let parser = sym(b'x').repeat(4);
882 let output = parser.name("name_test_err").parse(input);
883 assert_eq!(output, Err(
884 Error::Custom {
885 message: "failed to parse name_test_err".into(),
886 position: 0,
887 inner: Some(Box::new(Error::Mismatch {
888 message: "expect repeat at least 4 times, found 3 times".into(),
889 position: 0
890 }))
891 }
892 ))
893 }
894 }
895}