1use std::ops::{
2 Range,
3 RangeFrom,
4 RangeFull,
5 RangeTo,
6};
7use std::str::FromStr;
8
9use nom::{
10 AsBytes,
11 Compare,
12 CompareResult,
13 Err,
14 FindSubstring,
15 FindToken,
16 InputIter,
17 InputLength,
18 InputTake,
19 InputTakeAtPosition,
20 Needed,
21 Offset,
22 ParseTo,
23 Slice,
24};
25use nom::error::{
26 ErrorKind,
27 ParseError,
28};
29
30#[derive(Debug, Clone)]
32pub struct InputAux<Aux, I> {
33 pub aux: Aux,
35
36 pub input: I
38}
39
40impl<Aux, I> InputAux<Aux, I> {
41 pub fn new(aux: Aux, buf: I) -> Self {
43 InputAux{aux, input: buf}
44 }
45}
46
47pub trait ContextAware<EE> {
48 fn push_context(&mut self, context: &'static str) -> Option<Result<EE, EE>>;
50 fn pop_context<I, O, E: nom::error::FromExternalError<I, EE>>(&mut self, res: &nom::IResult<I, O, E>) -> Option<Result<EE, EE>>;
51}
52
53pub fn context<EE, Aux: Clone + ContextAware<EE>, I: Clone, E: nom::error::FromExternalError<InputAux<Aux, I>, EE> + nom::error::ContextError<InputAux<Aux, I>>, F, O>(
54 ctxt: &'static str,
55 mut f: F,
56) -> impl FnMut(InputAux<Aux, I>) -> nom::IResult<InputAux<Aux, I>, O, E>
57where
58 F: nom::Parser<InputAux<Aux, I>, O, E>,
59{
60 move |mut i: InputAux<Aux, I>| {
61 match i.aux.push_context(ctxt) {
62 None => (),
63 Some(Ok(e)) => return Err(Err::Error(E::from_external_error(i, ErrorKind::Not, e))),
64 Some(Err(f)) => return Err(Err::Failure(E::from_external_error(i, ErrorKind::Not, f))),
65 };
66 let res = f.parse(i.clone());
67 match i.aux.pop_context(&res) {
68 None => (),
69 Some(Ok(e)) => return Err(Err::Error(E::from_external_error(i, ErrorKind::Not, e))),
70 Some(Err(f)) => return Err(Err::Failure(E::from_external_error(i, ErrorKind::Not, f))),
71 };
72 match res {
73 Ok(o) => Ok(o),
74 Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
75 Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, ctxt, e))),
76 Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, ctxt, e))),
77 }
78 }
79}
80
81impl <Aux: Copy, I> InputAux<Aux, I> {
82 pub fn wrap_with(&self, buf: I) -> Self {
84 Self::new(self.aux, buf)
85 }
86
87 pub fn split_aux(&self, t1: I, t2: I) -> (Self, Self) {
89 (Self::new(self.aux, t1), Self::new(self.aux, t2))
90 }
91}
92
93impl <Aux: Default, I> From<I> for InputAux<Aux, I> {
94 fn from(i: I) -> Self { InputAux::new(Default::default(), i) }
95}
96
97impl <Aux, I: PartialEq> PartialEq for InputAux<Aux, I> {
98 fn eq(&self, rhs: &Self) -> bool {
99 self.input == rhs.input
100 }
101}
102
103impl <Aux, I: Eq> Eq for InputAux<Aux, I> { }
104
105impl <Aux: Copy, I: Copy> Copy for InputAux<Aux, I> { }
106
107impl <Aux, I> std::borrow::Borrow<I> for InputAux<Aux, &I> {
108 fn borrow(&self) -> &I {
109 self.input
110 }
111}
112
113impl<Aux, I: InputLength> InputLength for InputAux<Aux, I> {
114 #[inline]
115 fn input_len(&self) -> usize {
116 self.input.input_len()
117 }
118}
119
120
121impl<Aux, I: Offset> Offset for InputAux<Aux, I> {
122 fn offset(&self, second: &Self) -> usize {
123 self.input.offset(&second.input)
124 }
125}
126
127
128impl<Aux, I: AsBytes> AsBytes for InputAux<Aux, I> {
129 #[inline(always)]
130 fn as_bytes(&self) -> &[u8] {
131 self.input.as_bytes()
132 }
133}
134
135impl <Aux, I: InputIter> InputIter for InputAux<Aux, I> {
136 type Item = <I as InputIter>::Item;
137 type Iter = <I as InputIter>::Iter;
138 type IterElem = <I as InputIter>::IterElem;
139
140 fn iter_indices(&self) -> Self::Iter { self.input.iter_indices() }
141
142 fn iter_elements(&self) -> Self::IterElem { self.input.iter_elements() }
143
144 fn position<P: Fn(Self::Item) -> bool>(&self, p: P) -> Option<usize> {
145 self.input.position(p)
146 }
147
148 fn slice_index(&self, i: usize) -> Result<usize, Needed> {
149 self.input.slice_index(i)
150 }
151}
152
153impl <Aux: Copy, I: InputTake> InputTake for InputAux<Aux, I> {
154 fn take(&self, n: usize) -> Self {
155 InputAux::new(self.aux, self.input.take(n))
156 }
157
158 fn take_split(&self, n: usize) -> (Self, Self) {
159 let (t1, t2) = self.input.take_split(n);
160
161 (InputAux::new(self.aux, t1), InputAux::new(self.aux, t2))
162 }
163}
164
165
166impl <Aux: Copy, I: InputIter + InputTakeAtPosition> InputTakeAtPosition for InputAux<Aux, I> {
167 type Item = <I as InputTakeAtPosition>::Item;
168
169 fn split_at_position<P: Fn(Self::Item) -> bool, E: ParseError<Self>>(&self, pred: P) -> Result<(Self, Self), Err<E>> {
170 let r = self.input.split_at_position::<P, (I, ErrorKind)>(pred);
171 let r = r.map(|(p1, p2)| self.split_aux(p1, p2));
172 let r = r.map_err(|e| e.map(|i| E::from_error_kind(self.wrap_with(i.0), i.1)));
173 r
174 }
175
176 fn split_at_position1<P: Fn(Self::Item) -> bool, E: ParseError<Self>>(&self, pred: P, kind: ErrorKind) -> Result<(Self, Self), Err<E>> {
177 let r = self.input.split_at_position1::<P, (I, ErrorKind)>(pred, kind);
178 let r = r.map(|(p1, p2)| self.split_aux(p1, p2));
179 let r = r.map_err(|e| { let ee = e.map(|i| { let o: E = E::from_error_kind(self.wrap_with(i.0), i.1); o }); ee });
180 r
181 }
182
183 fn split_at_position_complete<P: Fn(Self::Item) -> bool, E: ParseError<Self>>(&self, pred: P) -> Result<(Self, Self), Err<E>> {
184 let r = self.input.split_at_position_complete::<P, (I, ErrorKind)>(pred);
185 let r = r.map(|(p1, p2)| self.split_aux(p1, p2));
186 let r = r.map_err(|e| { let ee = e.map(|i| { let o: E = E::from_error_kind(self.wrap_with(i.0), i.1); o }); ee });
187 r
188 }
189
190 fn split_at_position1_complete<P, E>(&self, pred: P, kind: ErrorKind) -> Result<(Self, Self), Err<E>>
191 where
192 P: Fn(Self::Item) -> bool,
193 E: ParseError<Self>,
194 {
195 let r = self.input.split_at_position1_complete::<P, (I, ErrorKind)>(pred, kind);
196 let r = r.map(|(p1, p2)| self.split_aux(p1, p2));
197 let r = r.map_err(|e| { let ee = e.map(|i| { let o: E = E::from_error_kind(self.wrap_with(i.0), i.1); o }); ee });
198 r
199 }
200}
201
202
203impl <'a, Aux, I: Compare<&'a str>> Compare<&'a str> for InputAux<Aux, I> {
216 fn compare(&self, v: &'a str) -> CompareResult {
217 self.input.compare(v)
218 }
219
220 fn compare_no_case(&self, v: &'a str) -> CompareResult {
221 self.input.compare_no_case(v)
222 }
223}
224
225
226impl <'a, Aux, I: Compare<&'a [u8]>> Compare<&'a [u8]> for InputAux<Aux, I> {
227 fn compare(&self, v: &'a [u8]) -> CompareResult {
228 self.input.compare(v)
229 }
230
231 fn compare_no_case(&self, v: &'a [u8]) -> CompareResult {
232 self.input.compare_no_case(v)
233 }
234}
235
236
237impl<Aux, T, I: FindToken<T>> FindToken<T> for InputAux<Aux, I> {
238 fn find_token(&self, token: T) -> bool {
239 self.input.find_token(token)
240 }
241}
242
243
244impl<Aux, T, I: FindSubstring<T>> FindSubstring<T> for InputAux<Aux, I> {
245 fn find_substring(&self, substr: T) -> Option<usize> {
246 self.input.find_substring(substr)
247 }
248}
249
250
251impl<Aux, R: FromStr, I: ParseTo<R>> ParseTo<R> for InputAux<Aux, I> {
252 fn parse_to(&self) -> Option<R> {
253 self.input.parse_to()
254 }
255}
256
257
258macro_rules! aux_wrap {
259 ( $ty:ty ) => {
260 impl <Aux: Copy, I: Slice<$ty>> Slice<$ty> for InputAux<Aux, I> {
261 fn slice(&self, r: $ty) -> Self {
262 self.wrap_with(self.input.slice(r))
263 }
264 }
265 }
266}
267
268aux_wrap! {Range<usize>}
269aux_wrap! {RangeTo<usize>}
270aux_wrap! {RangeFrom<usize>}
271aux_wrap! {RangeFull}
272
273impl<Aux, I: std::ops::Deref> std::ops::Deref for InputAux<Aux, I> {
274 type Target = <I as std::ops::Deref>::Target;
275
276 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
277 self.input.deref()
278 }
279}
280
281#[cfg(test)]
282mod test {
283 #[cfg(feature = "alloc")]
284 use nom::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many1};
285 use nom::{
286 bytes::complete::{is_a, is_not, tag, take, take_till, take_until},
287 error::{self, ErrorKind},
288 Err, IResult,
289 Needed,
290 };
291 use crate::InputAux;
292
293 #[test]
294 fn tagtr_succeed() {
295 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "Hello World!" };
296 const TAG: &str = "Hello";
297 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
298 tag(TAG)(input)
299 }
300
301 match test(INPUT) {
302 Ok((extra, output)) => {
303 assert!(extra.input == " World!", "Parser `tag` consumed leftover input.");
304 assert!(
305 output.input == TAG,
306 "Parser `tag` doesn't return the tag it matched on success. \
307 Expected `{}`, got `{}`.",
308 TAG,
309 output.input
310 );
311 }
312 other => panic!(
313 "Parser `tag` didn't succeed when it should have. \
314 Got `{:?}`.",
315 other
316 ),
317 };
318 }
319
320 #[test]
321 fn tagtr_incomplete() {
322 use nom::bytes::streaming::tag;
323
324 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "Hello" };
325 const TAG: &str = "Hello World!";
326
327 let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
328 match res {
329 Err(Err::Incomplete(_)) => (),
330 other => {
331 panic!(
332 "Parser `tag` didn't require more input when it should have. \
333 Got `{:?}`.",
334 other
335 );
336 }
337 };
338 }
339
340 #[test]
341 fn tagtr_error() {
342 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "Hello World!" };
343 const TAG: &str = "Random"; let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
346 match res {
347 Err(Err::Error(_)) => (),
348 other => {
349 panic!(
350 "Parser `tag` didn't fail when it should have. Got `{:?}`.`",
351 other
352 );
353 }
354 };
355 }
356
357 #[test]
358 fn take_s_succeed() {
359 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
360 const CONSUMED: &str = "βèƒôřèÂßÇ";
361 const LEFTOVER: &str = "áƒƭèř";
362
363 let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT);
364 match res {
365 Ok((extra, output)) => {
366 assert!(
367 extra.input == LEFTOVER,
368 "Parser `take_s` consumed leftover input. Leftover `{}`.",
369 extra.input
370 );
371 assert!(
372 output.input == CONSUMED,
373 "Parser `take_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
374 CONSUMED,
375 output.input
376 );
377 }
378 other => panic!(
379 "Parser `take_s` didn't succeed when it should have. \
380 Got `{:?}`.",
381 other
382 ),
383 };
384 }
385
386 #[test]
387 fn take_until_succeed() {
388 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇ∂áƒƭèř" };
389 const FIND: &str = "ÂßÇ∂";
390 const CONSUMED: &str = "βèƒôřè";
391 const LEFTOVER: &str = "ÂßÇ∂áƒƭèř";
392
393 let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
394 match res {
395 Ok((extra, output)) => {
396 assert!(
397 extra.input == LEFTOVER,
398 "Parser `take_until`\
399 consumed leftover input. Leftover `{}`.",
400 extra.input
401 );
402 assert!(
403 output.input == CONSUMED,
404 "Parser `take_until`\
405 doens't return the string it consumed on success. Expected `{}`, got `{}`.",
406 CONSUMED,
407 output.input
408 );
409 }
410 other => panic!(
411 "Parser `take_until` didn't succeed when it should have. \
412 Got `{:?}`.",
413 other
414 ),
415 };
416 }
417
418 #[test]
419 fn take_s_incomplete() {
420 use nom::bytes::streaming::take;
421
422 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇá" };
423
424 let res: IResult<_, _, (_, ErrorKind)> = take(13_usize)(INPUT);
425 match res {
426 Err(Err::Incomplete(_)) => (),
427 other => panic!(
428 "Parser `take` didn't require more input when it should have. \
429 Got `{:?}`.",
430 other
431 ),
432 }
433 }
434
435 fn is_alphabetic(c: char) -> bool {
436 (c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A)
437 }
438
439 #[test]
440 fn take_while() {
441 use nom::bytes::streaming::take_while;
442
443 fn f(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
444 take_while(is_alphabetic)(i)
445 }
446 let a = "";
447 let b = "abcd";
448 let c = "abcd123";
449 let d = "123";
450
451 assert_eq!(f((&a[..]).into()), Err(Err::Incomplete(Needed::new(1))));
452 assert_eq!(f((&b[..]).into()), Err(Err::Incomplete(Needed::new(1))));
453 assert_eq!(f((&c[..]).into()), Ok(((&d[..]).into(), (&b[..]).into())));
454 assert_eq!(f((&d[..]).into()), Ok(((&d[..]).into(), (&a[..]).into())));
455 }
456
457 #[test]
458 fn take_while1() {
459 use nom::bytes::streaming::take_while1;
460
461 fn f(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
462 take_while1(is_alphabetic)(i)
463 }
464 let a = "";
465 let b = "abcd";
466 let c = "abcd123";
467 let d = "123";
468
469 assert_eq!(f((&a[..]).into()), Err(Err::Incomplete(Needed::new(1))));
470 assert_eq!(f((&b[..]).into()), Err(Err::Incomplete(Needed::new(1))));
471 assert_eq!(f((&c[..]).into()), Ok(((&"123"[..]).into(), (&b[..]).into())));
472 assert_eq!(
473 f((&d[..]).into()),
474 Err(Err::Error(nom::error_position!((&d[..]).into(), ErrorKind::TakeWhile1)))
475 );
476 }
477
478 #[test]
479 fn take_till_s_succeed() {
480 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
481 const CONSUMED: &str = "βèƒôřèÂßÇ";
482 const LEFTOVER: &str = "áƒƭèř";
483 fn till_s(c: char) -> bool {
484 c == 'á'
485 }
486 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
487 take_till(till_s)(input)
488 }
489 match test(INPUT) {
490 Ok((extra, output)) => {
491 assert!(
492 extra.input == LEFTOVER,
493 "Parser `take_till` consumed leftover input."
494 );
495 assert!(
496 output.input == CONSUMED,
497 "Parser `take_till` doesn't return the string it consumed on success. \
498 Expected `{}`, got `{}`.",
499 CONSUMED,
500 output.input
501 );
502 }
503 other => panic!(
504 "Parser `take_till` didn't succeed when it should have. \
505 Got `{:?}`.",
506 other
507 ),
508 };
509 }
510
511 #[test]
512 fn take_while_succeed_none() {
513 use nom::bytes::complete::take_while;
514
515 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
516 const CONSUMED: &str = "";
517 const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř";
518 fn while_s(c: char) -> bool {
519 c == '9'
520 }
521 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
522 take_while(while_s)(input)
523 }
524 match test(INPUT) {
525 Ok((extra, output)) => {
526 assert!(
527 extra.input == LEFTOVER,
528 "Parser `take_while` consumed leftover input."
529 );
530 assert!(
531 output.input == CONSUMED,
532 "Parser `take_while` doesn't return the string it consumed on success. \
533 Expected `{}`, got `{}`.",
534 CONSUMED,
535 output.input
536 );
537 }
538 other => panic!(
539 "Parser `take_while` didn't succeed when it should have. \
540 Got `{:?}`.",
541 other
542 ),
543 };
544 }
545
546 #[test]
547 fn is_not_succeed() {
548 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
549 const AVOID: &str = "£úçƙ¥á";
550 const CONSUMED: &str = "βèƒôřèÂßÇ";
551 const LEFTOVER: &str = "áƒƭèř";
552 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
553 is_not(AVOID)(input)
554 }
555 match test(INPUT) {
556 Ok((extra, output)) => {
557 assert!(
558 extra.input == LEFTOVER,
559 "Parser `is_not` consumed leftover input. Leftover `{}`.",
560 extra.input
561 );
562 assert!(
563 output.input == CONSUMED,
564 "Parser `is_not` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
565 CONSUMED,
566 output.input
567 );
568 }
569 other => panic!(
570 "Parser `is_not` didn't succeed when it should have. \
571 Got `{:?}`.",
572 other
573 ),
574 };
575 }
576
577 #[test]
578 fn take_while_succeed_some() {
579 use nom::bytes::complete::take_while;
580
581 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
582 const CONSUMED: &str = "βèƒôřèÂßÇ";
583 const LEFTOVER: &str = "áƒƭèř";
584 fn while_s(c: char) -> bool {
585 c == 'β'
586 || c == 'è'
587 || c == 'ƒ'
588 || c == 'ô'
589 || c == 'ř'
590 || c == 'è'
591 || c == 'Â'
592 || c == 'ß'
593 || c == 'Ç'
594 }
595 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
596 take_while(while_s)(input)
597 }
598 match test(INPUT) {
599 Ok((extra, output)) => {
600 assert!(
601 extra.input == LEFTOVER,
602 "Parser `take_while` consumed leftover input."
603 );
604 assert!(
605 output.input == CONSUMED,
606 "Parser `take_while` doesn't return the string it consumed on success. \
607 Expected `{}`, got `{}`.",
608 CONSUMED,
609 output.input
610 );
611 }
612 other => panic!(
613 "Parser `take_while` didn't succeed when it should have. \
614 Got `{:?}`.",
615 other
616 ),
617 };
618 }
619
620 #[test]
621 fn is_not_fail() {
622 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
623 const AVOID: InputAux<(), &str> = InputAux { aux: (), input: "βúçƙ¥" };
624 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
625 is_not(AVOID)(input)
626 }
627 match test(INPUT) {
628 Err(Err::Error(_)) => (),
629 other => panic!(
630 "Parser `is_not` didn't fail when it should have. Got `{:?}`.",
631 other
632 ),
633 };
634 }
635
636 #[test]
637 fn take_while1_succeed() {
638 use nom::bytes::complete::take_while1;
639
640 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
641 const CONSUMED: &str = "βèƒôřèÂßÇ";
642 const LEFTOVER: &str = "áƒƭèř";
643 fn while1_s(c: char) -> bool {
644 c == 'β'
645 || c == 'è'
646 || c == 'ƒ'
647 || c == 'ô'
648 || c == 'ř'
649 || c == 'è'
650 || c == 'Â'
651 || c == 'ß'
652 || c == 'Ç'
653 }
654 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
655 take_while1(while1_s)(input)
656 }
657 match test(INPUT) {
658 Ok((extra, output)) => {
659 assert!(
660 extra.input == LEFTOVER,
661 "Parser `take_while1` consumed leftover input."
662 );
663 assert!(
664 output.input == CONSUMED,
665 "Parser `take_while1` doesn't return the string it consumed on success. \
666 Expected `{}`, got `{}`.",
667 CONSUMED,
668 output.input
669 );
670 }
671 other => panic!(
672 "Parser `take_while1` didn't succeed when it should have. \
673 Got `{:?}`.",
674 other
675 ),
676 };
677 }
678
679 #[test]
680 fn take_until_incomplete() {
681 use nom::bytes::streaming::take_until;
682
683 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřè" };
684 const FIND: &str = "βèƒôřèÂßÇ";
685
686 let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
687 match res {
688 Err(Err::Incomplete(_)) => (),
689 other => panic!(
690 "Parser `take_until` didn't require more input when it should have. \
691 Got `{:?}`.",
692 other
693 ),
694 };
695 }
696
697 #[test]
698 fn is_a_succeed() {
699 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
700 const MATCH: &str = "βèƒôřèÂßÇ";
701 const CONSUMED: &str = "βèƒôřèÂßÇ";
702 const LEFTOVER: &str = "áƒƭèř";
703 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
704 is_a(MATCH)(input)
705 }
706 match test(INPUT) {
707 Ok((extra, output)) => {
708 assert!(
709 extra.input == LEFTOVER,
710 "Parser `is_a` consumed leftover input. Leftover `{}`.",
711 extra.input
712 );
713 assert!(
714 output.input == CONSUMED,
715 "Parser `is_a` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
716 CONSUMED,
717 output.input
718 );
719 }
720 other => panic!(
721 "Parser `is_a` didn't succeed when it should have. \
722 Got `{:?}`.",
723 other
724 ),
725 };
726 }
727
728 #[test]
729 fn take_while1_fail() {
730 use nom::bytes::complete::take_while1;
731
732 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
733 fn while1_s(c: char) -> bool {
734 c == '9'
735 }
736 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
737 take_while1(while1_s)(input)
738 }
739 match test(INPUT) {
740 Err(Err::Error(_)) => (),
741 other => panic!(
742 "Parser `take_while1` didn't fail when it should have. \
743 Got `{:?}`.",
744 other
745 ),
746 };
747 }
748
749 #[test]
750 fn is_a_fail() {
751 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
752 const MATCH: &str = "Ûñℓúçƙ¥";
753 fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
754 is_a(MATCH)(input)
755 }
756 match test(INPUT) {
757 Err(Err::Error(_)) => (),
758 other => panic!(
759 "Parser `is_a` didn't fail when it should have. Got `{:?}`.",
760 other
761 ),
762 };
763 }
764
765 #[test]
766 fn take_until_error() {
767 use nom::bytes::streaming::take_until;
768
769 const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
770 const FIND: &str = "Ráñδô₥";
771
772 let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
773 match res {
774 Err(Err::Incomplete(_)) => (),
775 other => panic!(
776 "Parser `take_until` didn't fail when it should have. \
777 Got `{:?}`.",
778 other
779 ),
780 };
781 }
782
783 #[test]
784 #[cfg(feature = "alloc")]
785 fn recognize_is_a() {
786 let a = "aabbab";
787 let b = "ababcd";
788
789 fn f(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
790 recognize(many1(alt((tag("a"), tag("b")))))(i)
791 }
792
793 assert_eq!(f((&a[..]).into()), Ok(((&a[6..]).into(), (&a[..]).into())));
794 assert_eq!(f((&b[..]).into()), Ok(((&b[4..]).into(), (&b[..4]).into())));
795 }
796
797 #[test]
798 fn utf8_indexing() {
799 fn dot(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
800 tag(".")(i)
801 }
802
803 let _ = dot("點".into());
804 }
805
806 #[cfg(feature = "alloc")]
807 #[test]
808 fn case_insensitive() {
809 fn test(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
810 tag_no_case("ABcd")(i)
811 }
812 assert_eq!(test("aBCdefgh".into()), Ok(("efgh".into(), "aBCd".into())));
813 assert_eq!(test("abcdefgh".into()), Ok(("efgh".into(), "abcd".into())));
814 assert_eq!(test("ABCDefgh".into()), Ok(("efgh".into(), "ABCD".into())));
815 }
816
817 #[test]
818 fn recurse_limit() {
819 use nom::branch::alt;
820 use nom::bytes::complete::tag;
821 use nom::sequence::delimited;
822
823 const DEPTH: i32 = 8;
824 const INPUT: InputAux<i32, &str> = InputAux { aux: 0, input: "([([([([x])])])]) World!" };
825
826 fn test(depth: i32, mut input: InputAux<i32, &str>) -> nom::IResult<InputAux<i32, &str>, InputAux<i32, &str>> {
827 fn cp(mut i: InputAux<i32, &str>) -> nom::IResult<InputAux<i32, &str>, InputAux<i32, &str>> {
828 i.aux -= 1;
829 if i.aux < 0 {
830 tag("never match")(i)
831 } else {
832 delimited(tag("("), alt((tag("x"), cp, csp)), tag(")"))(i)
833 }
834 }
835 fn csp(mut i: InputAux<i32, &str>) -> nom::IResult<InputAux<i32, &str>, InputAux<i32, &str>> {
836 i.aux -= 1;
837 if i.aux < 0 {
838 tag("never match")(i)
839 } else {
840 delimited(tag("["), alt((tag("x"), cp, csp)), tag("]"))(i)
841 }
842 }
843 input.aux = depth;
844 alt((cp, csp))(input)
845 }
846
847 match test(DEPTH, INPUT) {
848 Ok((extra, output)) => {
849 assert!(extra.input == " World!", "Parser `tag` consumed leftover input.");
850 assert!(output.aux == 0, "Depth left over not what should be {} != 0.", output.aux);
851 assert!(
852 output.input == "x",
853 "Parser `tag` doesn't return the tag it matched on success. \
854 Expected `{}`, got `{}`.",
855 "x",
856 output.input
857 );
858 }
859 other => panic!(
860 "Parser `tag` didn't succeed when it should have. \
861 Got `{:?}`.",
862 other
863 ),
864 };
865
866 match test(DEPTH - 1, INPUT) {
867 Err(Err::Error(_)) => (),
868 other => panic!(
869 "Parser didn't reach max depth when it should have. \
870 Got `{:?}`.",
871 other
872 ),
873 };
874 }
875
876 #[test]
877 fn double_parsing() {
878 assert!(1.0 < nom::number::complete::double::<_, (_, ErrorKind)>("1.2").map(|v| v.1).unwrap_or(0.0));
879 assert!(1.0 < nom::number::complete::double::<_, (_, ErrorKind)>("1.2".as_bytes()).map(|v| v.1).unwrap_or(0.0));
880 assert!(1.0 < nom::number::complete::double::<_, (_, ErrorKind)>(InputAux{aux: (), input: "1.2"}).map(|v| v.1).unwrap_or(0.0));
881 }
882}