winnow/parser.rs
1//! Basic types to build the parsers
2
3use crate::combinator::impls;
4#[cfg(feature = "unstable-recover")]
5#[cfg(feature = "std")]
6use crate::error::FromRecoverableError;
7use crate::error::{AddContext, FromExternalError, ParseError, ParserError, Result};
8use crate::stream::{Compare, Location, ParseSlice, Stream, StreamIsPartial};
9#[cfg(feature = "unstable-recover")]
10#[cfg(feature = "std")]
11use crate::stream::{Recover, Recoverable};
12
13/// Core trait for parsing
14///
15/// The simplest way to implement a `Parser` is with a function
16/// ```rust
17/// use winnow::prelude::*;
18///
19/// fn empty(input: &mut &str) -> ModalResult<()> {
20/// let output = ();
21/// Ok(output)
22/// }
23///
24/// let (input, output) = empty.parse_peek("Hello").unwrap();
25/// assert_eq!(input, "Hello"); // We didn't consume any input
26/// ```
27///
28/// which can be made stateful by returning a function
29/// ```rust
30/// use winnow::prelude::*;
31///
32/// fn empty<O: Clone>(output: O) -> impl FnMut(&mut &str) -> ModalResult<O> {
33/// move |input: &mut &str| {
34/// let output = output.clone();
35/// Ok(output)
36/// }
37/// }
38///
39/// let (input, output) = empty("World").parse_peek("Hello").unwrap();
40/// assert_eq!(input, "Hello"); // We didn't consume any input
41/// assert_eq!(output, "World");
42/// ```
43///
44/// Additionally, some basic types implement `Parser` as well, including
45/// - `u8` and `char`, see [`winnow::token::one_of`][crate::token::one_of]
46/// - `&[u8]` and `&str`, see [`winnow::token::literal`][crate::token::literal]
47pub trait Parser<I, O, E> {
48 /// Parse all of `input`, generating `O` from it
49 ///
50 /// This is intended for integrating your parser into the rest of your application.
51 ///
52 /// For one [`Parser`] to drive another [`Parser`] forward or for
53 /// [incremental parsing][StreamIsPartial], see instead [`Parser::parse_next`].
54 ///
55 /// This assumes the [`Parser`] intends to read all of `input` and will return an
56 /// [`eof`][crate::combinator::eof] error if it does not.
57 /// To ignore trailing `input`, combine your parser with a [`rest`][crate::token::rest]
58 /// (e.g. `(parser, rest).parse(input)`).
59 ///
60 /// See also the [tutorial][crate::_tutorial::chapter_6].
61 #[inline]
62 fn parse(&mut self, mut input: I) -> Result<O, ParseError<I, <E as ParserError<I>>::Inner>>
63 where
64 Self: core::marker::Sized,
65 I: Stream,
66 // Force users to deal with `Incomplete` when `StreamIsPartial<true>`
67 I: StreamIsPartial,
68 E: ParserError<I>,
69 <E as ParserError<I>>::Inner: ParserError<I>,
70 {
71 debug_assert!(
72 !I::is_partial_supported(),
73 "partial streams need to handle `ErrMode::Incomplete`"
74 );
75
76 let start = input.checkpoint();
77 let (o, _) = (self.by_ref(), crate::combinator::eof)
78 .parse_next(&mut input)
79 .map_err(|e| {
80 let e = e.into_inner().unwrap_or_else(|_err| {
81 panic!("complete parsers should not report `ErrMode::Incomplete(_)`")
82 });
83 ParseError::new(input, start, e)
84 })?;
85 Ok(o)
86 }
87
88 /// Repeat this parse until all of `input` is consumed, generating `O` from it
89 ///
90 /// This is intended for integrating your parser into the rest of your application.
91 /// To instead iterate inside of a parser, see [iterator][crate::combinator::iterator].
92 ///
93 /// This assumes the [`Parser`] intends to read all of `input` and will return an
94 /// [`eof`][crate::combinator::eof] error if it does not.
95 ///
96 /// # Example
97 ///
98 /// ```rust
99 /// # #[cfg(feature = "ascii")] {
100 /// # use winnow::ascii::dec_uint;
101 /// # use winnow::ascii::newline;
102 /// # use winnow::combinator::terminated;
103 /// # use winnow::combinator::opt;
104 /// # use winnow::prelude::*;
105 /// fn number(input: &mut &str) -> Result<u32, ()> {
106 /// terminated(dec_uint, opt(newline)).parse_next(input)
107 /// }
108 ///
109 /// let input = "10\n20\n30";
110 /// let numbers = number.parse_iter(input)
111 /// .map(|r| r.unwrap()).collect::<Vec<_>>();
112 /// assert_eq!(numbers, vec![10, 20, 30]);
113 /// # }
114 /// ```
115 #[inline]
116 fn parse_iter(&mut self, input: I) -> impls::ParseIter<'_, Self, I, O, E>
117 where
118 Self: core::marker::Sized,
119 I: Stream,
120 // Force users to deal with `Incomplete` when `StreamIsPartial<true>`
121 I: StreamIsPartial,
122 E: ParserError<I>,
123 <E as ParserError<I>>::Inner: ParserError<I>,
124 {
125 debug_assert!(
126 !I::is_partial_supported(),
127 "partial streams need to handle `ErrMode::Incomplete`"
128 );
129
130 let start = input.checkpoint();
131 impls::ParseIter {
132 parser: self,
133 input: Some(input),
134 start: Some(start),
135 marker: Default::default(),
136 }
137 }
138
139 /// Take tokens from the [`Stream`], turning it into the output
140 ///
141 /// This includes advancing the input [`Stream`] to the next location.
142 ///
143 /// On error, `input` will be left pointing at the error location.
144 ///
145 /// This is intended for a [`Parser`] to drive another [`Parser`] forward or for
146 /// [incremental parsing][StreamIsPartial]
147 fn parse_next(&mut self, input: &mut I) -> Result<O, E>;
148
149 /// Take tokens from the [`Stream`], turning it into the output
150 ///
151 /// This returns a copy of the [`Stream`] advanced to the next location.
152 ///
153 /// <div class="warning">
154 ///
155 /// Generally, prefer [`Parser::parse_next`].
156 /// This is primarily intended for:
157 /// - Migrating from older versions / `nom`
158 /// - Testing [`Parser`]s
159 ///
160 /// For look-ahead parsing, see instead [`peek`][crate::combinator::peek].
161 ///
162 /// </div>
163 #[inline(always)]
164 fn parse_peek(&mut self, mut input: I) -> Result<(I, O), E> {
165 match self.parse_next(&mut input) {
166 Ok(o) => Ok((input, o)),
167 Err(err) => Err(err),
168 }
169 }
170
171 /// Treat `&mut Self` as a parser
172 ///
173 /// This helps when needing to move a `Parser` when all you have is a `&mut Parser`.
174 ///
175 /// # Example
176 ///
177 /// Because parsers are `FnMut`, they can be called multiple times. This prevents moving `f`
178 /// into [`length_take`][crate::binary::length_take] and `g` into
179 /// [`Parser::complete_err`]:
180 /// ```rust,compile_fail
181 /// # use winnow::prelude::*;
182 /// # use winnow::Parser;
183 /// # use winnow::error::ParserError;
184 /// # use winnow::binary::length_take;
185 /// pub fn length_value<'i, O, E: ParserError<&'i [u8]>>(
186 /// mut f: impl Parser<&'i [u8], usize, E>,
187 /// mut g: impl Parser<&'i [u8], O, E>
188 /// ) -> impl Parser<&'i [u8], O, E> {
189 /// move |i: &mut &'i [u8]| {
190 /// let mut data = length_take(f).parse_next(i)?;
191 /// let o = g.complete_err().parse_next(&mut data)?;
192 /// Ok(o)
193 /// }
194 /// }
195 /// ```
196 ///
197 /// By adding `by_ref`, we can make this work:
198 /// ```rust
199 /// # #[cfg(feature = "binary")] {
200 /// # use winnow::prelude::*;
201 /// # use winnow::Parser;
202 /// # use winnow::error::ParserError;
203 /// # use winnow::binary::length_take;
204 /// pub fn length_value<'i, O, E: ParserError<&'i [u8]>>(
205 /// mut f: impl Parser<&'i [u8], usize, E>,
206 /// mut g: impl Parser<&'i [u8], O, E>
207 /// ) -> impl Parser<&'i [u8], O, E> {
208 /// move |i: &mut &'i [u8]| {
209 /// let mut data = length_take(f.by_ref()).parse_next(i)?;
210 /// let o = g.by_ref().complete_err().parse_next(&mut data)?;
211 /// Ok(o)
212 /// }
213 /// }
214 /// # }
215 /// ```
216 #[inline(always)]
217 fn by_ref(&mut self) -> impls::ByRef<'_, Self, I, O, E>
218 where
219 Self: core::marker::Sized,
220 {
221 impls::ByRef {
222 p: self,
223 marker: Default::default(),
224 }
225 }
226
227 /// Produce the provided value
228 ///
229 /// # Example
230 ///
231 /// ```rust
232 /// # #[cfg(feature = "ascii")] {
233 /// # use winnow::{error::ErrMode, Parser};
234 /// # use winnow::prelude::*;
235 /// use winnow::ascii::alpha1;
236 ///
237 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<i32> {
238 /// alpha1.value(1234).parse_next(input)
239 /// }
240 ///
241 /// assert_eq!(parser.parse_peek("abcd"), Ok(("", 1234)));
242 /// assert!(parser.parse_peek("123abcd;").is_err());
243 /// # }
244 /// ```
245 #[doc(alias = "to")]
246 #[inline(always)]
247 fn value<O2>(self, val: O2) -> impls::Value<Self, I, O, O2, E>
248 where
249 Self: core::marker::Sized,
250 O2: Clone,
251 {
252 impls::Value {
253 parser: self,
254 val,
255 marker: Default::default(),
256 }
257 }
258
259 /// Produce a type's default value
260 ///
261 /// # Example
262 ///
263 /// ```rust
264 /// # #[cfg(feature = "ascii")] {
265 /// # use winnow::{error::ErrMode, Parser};
266 /// # use winnow::prelude::*;
267 /// use winnow::ascii::alpha1;
268 ///
269 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<u32> {
270 /// alpha1.default_value().parse_next(input)
271 /// }
272 ///
273 /// assert_eq!(parser.parse_peek("abcd"), Ok(("", 0)));
274 /// assert!(parser.parse_peek("123abcd;").is_err());
275 /// # }
276 /// ```
277 #[inline(always)]
278 fn default_value<O2>(self) -> impls::DefaultValue<Self, I, O, O2, E>
279 where
280 Self: core::marker::Sized,
281 O2: core::default::Default,
282 {
283 impls::DefaultValue {
284 parser: self,
285 marker: Default::default(),
286 }
287 }
288
289 /// Discards the output of the `Parser`
290 ///
291 /// # Example
292 ///
293 /// ```rust
294 /// # #[cfg(feature = "ascii")] {
295 /// # use winnow::{error::ErrMode, Parser};
296 /// # use winnow::prelude::*;
297 /// use winnow::ascii::alpha1;
298 ///
299 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<()> {
300 /// alpha1.void().parse_next(input)
301 /// }
302 ///
303 /// assert_eq!(parser.parse_peek("abcd"), Ok(("", ())));
304 /// assert!(parser.parse_peek("123abcd;").is_err());
305 /// # }
306 /// ```
307 #[inline(always)]
308 fn void(self) -> impls::Void<Self, I, O, E>
309 where
310 Self: core::marker::Sized,
311 {
312 impls::Void {
313 parser: self,
314 marker: Default::default(),
315 }
316 }
317
318 /// Convert the parser's output to another type using [`std::convert::From`]
319 ///
320 /// # Example
321 ///
322 /// ```rust
323 /// # #[cfg(feature = "ascii")] {
324 /// # use winnow::prelude::*;
325 /// # use winnow::error::ContextError;
326 /// use winnow::ascii::alpha1;
327 ///
328 /// fn parser1<'s>(i: &mut &'s str) -> ModalResult<&'s str> {
329 /// alpha1(i)
330 /// }
331 ///
332 /// let mut parser2 = parser1.output_into();
333 ///
334 /// // the parser converts the &str output of the child parser into a Vec<u8>
335 /// let bytes: ModalResult<(_, Vec<u8>), _> = parser2.parse_peek("abcd");
336 /// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100])));
337 /// # }
338 /// ```
339 #[inline(always)]
340 fn output_into<O2>(self) -> impls::OutputInto<Self, I, O, O2, E>
341 where
342 Self: core::marker::Sized,
343 O: Into<O2>,
344 {
345 impls::OutputInto {
346 parser: self,
347 marker: Default::default(),
348 }
349 }
350
351 /// Produce the consumed input as produced value.
352 ///
353 /// # Example
354 ///
355 /// ```rust
356 /// # #[cfg(feature = "ascii")] {
357 /// # use winnow::{error::ErrMode, Parser};
358 /// # use winnow::prelude::*;
359 /// use winnow::ascii::{alpha1};
360 /// use winnow::combinator::separated_pair;
361 ///
362 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
363 /// separated_pair(alpha1, ',', alpha1).take().parse_next(input)
364 /// }
365 ///
366 /// assert_eq!(parser.parse_peek("abcd,efgh"), Ok(("", "abcd,efgh")));
367 /// assert!(parser.parse_peek("abcd;").is_err());
368 /// # }
369 /// ```
370 #[doc(alias = "concat")]
371 #[doc(alias = "recognize")]
372 #[inline(always)]
373 fn take(self) -> impls::Take<Self, I, O, E>
374 where
375 Self: core::marker::Sized,
376 I: Stream,
377 {
378 impls::Take {
379 parser: self,
380 marker: Default::default(),
381 }
382 }
383
384 /// Produce the consumed input with the output
385 ///
386 /// Functions similarly to [take][Parser::take] except it
387 /// returns the parser output as well.
388 ///
389 /// This can be useful especially in cases where the output is not the same type
390 /// as the input, or the input is a user defined type.
391 ///
392 /// Returned tuple is of the format `(produced output, consumed input)`.
393 ///
394 /// # Example
395 ///
396 /// ```rust
397 /// # #[cfg(feature = "ascii")] {
398 /// # use winnow::prelude::*;
399 /// # use winnow::{error::ErrMode};
400 /// use winnow::ascii::{alpha1};
401 /// use winnow::token::literal;
402 /// use winnow::combinator::separated_pair;
403 ///
404 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<(bool, &'i str)> {
405 /// separated_pair(alpha1, ',', alpha1).value(true).with_taken().parse_next(input)
406 /// }
407 ///
408 /// assert_eq!(parser.parse_peek("abcd,efgh1"), Ok(("1", (true, "abcd,efgh"))));
409 /// assert!(parser.parse_peek("abcd;").is_err());
410 /// # }
411 /// ```
412 #[doc(alias = "consumed")]
413 #[doc(alias = "with_recognized")]
414 #[inline(always)]
415 fn with_taken(self) -> impls::WithTaken<Self, I, O, E>
416 where
417 Self: core::marker::Sized,
418 I: Stream,
419 {
420 impls::WithTaken {
421 parser: self,
422 marker: Default::default(),
423 }
424 }
425
426 /// Produce the location of the consumed input as produced value.
427 ///
428 /// # Example
429 ///
430 /// ```rust
431 /// # #[cfg(feature = "ascii")] {
432 /// # use winnow::prelude::*;
433 /// # use winnow::{error::ErrMode, stream::Stream};
434 /// # use std::ops::Range;
435 /// use winnow::stream::LocatingSlice;
436 /// use winnow::ascii::alpha1;
437 /// use winnow::combinator::separated_pair;
438 ///
439 /// fn parser<'i>(input: &mut LocatingSlice<&'i str>) -> ModalResult<(Range<usize>, Range<usize>)> {
440 /// separated_pair(alpha1.span(), ',', alpha1.span()).parse_next(input)
441 /// }
442 ///
443 /// assert_eq!(parser.parse(LocatingSlice::new("abcd,efgh")), Ok((0..4, 5..9)));
444 /// assert!(parser.parse_peek(LocatingSlice::new("abcd;")).is_err());
445 /// # }
446 /// ```
447 #[inline(always)]
448 fn span(self) -> impls::Span<Self, I, O, E>
449 where
450 Self: core::marker::Sized,
451 I: Stream + Location,
452 {
453 impls::Span {
454 parser: self,
455 marker: Default::default(),
456 }
457 }
458
459 /// Produce the location of consumed input with the output
460 ///
461 /// Functions similarly to [`Parser::span`] except it
462 /// returns the parser output as well.
463 ///
464 /// This can be useful especially in cases where the output is not the same type
465 /// as the input, or the input is a user defined type.
466 ///
467 /// Returned tuple is of the format `(produced output, consumed input)`.
468 ///
469 /// # Example
470 ///
471 /// ```rust
472 /// # #[cfg(feature = "ascii")] {
473 /// # use winnow::prelude::*;
474 /// # use winnow::{error::ErrMode, stream::Stream};
475 /// # use std::ops::Range;
476 /// use winnow::stream::LocatingSlice;
477 /// use winnow::ascii::alpha1;
478 /// use winnow::token::literal;
479 /// use winnow::combinator::separated_pair;
480 ///
481 /// fn parser<'i>(input: &mut LocatingSlice<&'i str>) -> ModalResult<((usize, Range<usize>), (usize, Range<usize>))> {
482 /// separated_pair(alpha1.value(1).with_span(), ',', alpha1.value(2).with_span()).parse_next(input)
483 /// }
484 ///
485 /// assert_eq!(parser.parse(LocatingSlice::new("abcd,efgh")), Ok(((1, 0..4), (2, 5..9))));
486 /// assert!(parser.parse_peek(LocatingSlice::new("abcd;")).is_err());
487 /// # }
488 /// ```
489 #[inline(always)]
490 fn with_span(self) -> impls::WithSpan<Self, I, O, E>
491 where
492 Self: core::marker::Sized,
493 I: Stream + Location,
494 {
495 impls::WithSpan {
496 parser: self,
497 marker: Default::default(),
498 }
499 }
500
501 /// Maps a function over the output of a parser
502 ///
503 /// # Example
504 ///
505 /// ```rust
506 /// # #[cfg(feature = "ascii")] {
507 /// # use winnow::prelude::*;
508 /// # use winnow::{error::ErrMode, Parser};
509 /// # use winnow::ascii::digit1;
510 ///
511 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<usize> {
512 /// digit1.map(|s: &str| s.len()).parse_next(input)
513 /// }
514 ///
515 /// // the parser will count how many characters were returned by digit1
516 /// assert_eq!(parser.parse_peek("123456"), Ok(("", 6)));
517 ///
518 /// // this will fail if digit1 fails
519 /// assert!(parser.parse_peek("abc").is_err());
520 /// # }
521 /// ```
522 #[inline(always)]
523 fn map<G, O2>(self, map: G) -> impls::Map<Self, G, I, O, O2, E>
524 where
525 G: FnMut(O) -> O2,
526 Self: core::marker::Sized,
527 {
528 impls::Map {
529 parser: self,
530 map,
531 marker: Default::default(),
532 }
533 }
534
535 /// Applies a function returning a `Result` over the output of a parser.
536 ///
537 /// # Example
538 ///
539 /// ```rust
540 /// # #[cfg(feature = "ascii")] {
541 /// # use winnow::{error::ErrMode, Parser};
542 /// # use winnow::prelude::*;
543 /// use winnow::ascii::digit1;
544 ///
545 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<u8> {
546 /// digit1.try_map(|s: &str| s.parse::<u8>()).parse_next(input)
547 /// }
548 ///
549 /// // the parser will convert the result of digit1 to a number
550 /// assert_eq!(parser.parse_peek("123"), Ok(("", 123)));
551 ///
552 /// // this will fail if digit1 fails
553 /// assert!(parser.parse_peek("abc").is_err());
554 ///
555 /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
556 /// assert!(parser.parse_peek("123456").is_err());
557 /// # }
558 /// ```
559 #[inline(always)]
560 fn try_map<G, O2, E2>(self, map: G) -> impls::TryMap<Self, G, I, O, O2, E, E2>
561 where
562 Self: core::marker::Sized,
563 G: FnMut(O) -> Result<O2, E2>,
564 I: Stream,
565 E: FromExternalError<I, E2>,
566 E: ParserError<I>,
567 {
568 impls::TryMap {
569 parser: self,
570 map,
571 marker: Default::default(),
572 }
573 }
574
575 /// Apply both [`Parser::verify`] and [`Parser::map`].
576 ///
577 /// # Example
578 ///
579 /// ```rust
580 /// # #[cfg(feature = "ascii")] {
581 /// # use winnow::{error::ErrMode, Parser};
582 /// # use winnow::prelude::*;
583 /// use winnow::ascii::digit1;
584 ///
585 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<u8> {
586 /// digit1.verify_map(|s: &str| s.parse::<u8>().ok()).parse_next(input)
587 /// }
588 ///
589 /// // the parser will convert the result of digit1 to a number
590 /// assert_eq!(parser.parse_peek("123"), Ok(("", 123)));
591 ///
592 /// // this will fail if digit1 fails
593 /// assert!(parser.parse_peek("abc").is_err());
594 ///
595 /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
596 /// assert!(parser.parse_peek("123456").is_err());
597 /// # }
598 /// ```
599 #[doc(alias = "satisfy_map")]
600 #[doc(alias = "filter_map")]
601 #[doc(alias = "map_opt")]
602 #[inline(always)]
603 fn verify_map<G, O2>(self, map: G) -> impls::VerifyMap<Self, G, I, O, O2, E>
604 where
605 Self: core::marker::Sized,
606 G: FnMut(O) -> Option<O2>,
607 I: Stream,
608 E: ParserError<I>,
609 {
610 impls::VerifyMap {
611 parser: self,
612 map,
613 marker: Default::default(),
614 }
615 }
616
617 /// Creates a parser from the output of this one
618 ///
619 /// # Example
620 ///
621 /// ```rust
622 /// # #[cfg(feature = "binary")] {
623 /// # use winnow::{error::ErrMode, ModalResult, Parser};
624 /// use winnow::token::take;
625 /// use winnow::binary::u8;
626 ///
627 /// fn length_take<'s>(input: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
628 /// u8.flat_map(take).parse_next(input)
629 /// }
630 ///
631 /// assert_eq!(length_take.parse_peek(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
632 /// assert!(length_take.parse_peek(&[4, 0, 1, 2][..]).is_err());
633 /// # }
634 /// ```
635 ///
636 /// which is the same as
637 /// ```rust
638 /// # #[cfg(feature = "binary")] {
639 /// # use winnow::{error::ErrMode, ModalResult, Parser};
640 /// use winnow::token::take;
641 /// use winnow::binary::u8;
642 ///
643 /// fn length_take<'s>(input: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
644 /// let length = u8.parse_next(input)?;
645 /// let data = take(length).parse_next(input)?;
646 /// Ok(data)
647 /// }
648 ///
649 /// assert_eq!(length_take.parse_peek(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
650 /// assert!(length_take.parse_peek(&[4, 0, 1, 2][..]).is_err());
651 /// # }
652 /// ```
653 #[inline(always)]
654 fn flat_map<G, H, O2>(self, map: G) -> impls::FlatMap<Self, G, H, I, O, O2, E>
655 where
656 Self: core::marker::Sized,
657 G: FnMut(O) -> H,
658 H: Parser<I, O2, E>,
659 {
660 impls::FlatMap {
661 f: self,
662 g: map,
663 marker: Default::default(),
664 }
665 }
666
667 /// Applies a second parser over the output of the first one
668 ///
669 /// # Example
670 ///
671 /// ```rust
672 /// # #[cfg(feature = "ascii")] {
673 /// # use winnow::{error::ErrMode, Parser};
674 /// # use winnow::prelude::*;
675 /// use winnow::ascii::digit1;
676 /// use winnow::token::take;
677 ///
678 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
679 /// take(5u8).and_then(digit1).parse_next(input)
680 /// }
681 ///
682 /// assert_eq!(parser.parse_peek("12345"), Ok(("", "12345")));
683 /// assert_eq!(parser.parse_peek("123ab"), Ok(("", "123")));
684 /// assert!(parser.parse_peek("123").is_err());
685 /// # }
686 /// ```
687 #[inline(always)]
688 fn and_then<G, O2>(self, inner: G) -> impls::AndThen<Self, G, I, O, O2, E>
689 where
690 Self: core::marker::Sized,
691 G: Parser<O, O2, E>,
692 O: StreamIsPartial,
693 I: Stream,
694 {
695 impls::AndThen {
696 outer: self,
697 inner,
698 marker: Default::default(),
699 }
700 }
701
702 /// Apply [`std::str::FromStr`] to the output of the parser
703 ///
704 /// # Example
705 ///
706 /// ```rust
707 /// # #[cfg(feature = "ascii")] {
708 /// # use winnow::prelude::*;
709 /// use winnow::{error::ErrMode, Parser};
710 /// use winnow::ascii::digit1;
711 ///
712 /// fn parser<'s>(input: &mut &'s str) -> ModalResult<u64> {
713 /// digit1.parse_to().parse_next(input)
714 /// }
715 ///
716 /// // the parser will count how many characters were returned by digit1
717 /// assert_eq!(parser.parse_peek("123456"), Ok(("", 123456)));
718 ///
719 /// // this will fail if digit1 fails
720 /// assert!(parser.parse_peek("abc").is_err());
721 /// # }
722 /// ```
723 #[doc(alias = "from_str")]
724 #[inline(always)]
725 fn parse_to<O2>(self) -> impls::ParseTo<Self, I, O, O2, E>
726 where
727 Self: core::marker::Sized,
728 I: Stream,
729 O: ParseSlice<O2>,
730 E: ParserError<I>,
731 {
732 impls::ParseTo {
733 p: self,
734 marker: Default::default(),
735 }
736 }
737
738 /// Returns the output of the child parser if it satisfies a verification function.
739 ///
740 /// The verification function takes as argument a reference to the output of the
741 /// parser.
742 ///
743 /// # Example
744 ///
745 /// ```rust
746 /// # #[cfg(feature = "ascii")] {
747 /// # use winnow::{error::ErrMode, Parser};
748 /// # use winnow::ascii::alpha1;
749 /// # use winnow::prelude::*;
750 ///
751 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
752 /// alpha1.verify(|s: &str| s.len() == 4).parse_next(input)
753 /// }
754 ///
755 /// assert_eq!(parser.parse_peek("abcd"), Ok(("", "abcd")));
756 /// assert!(parser.parse_peek("abcde").is_err());
757 /// assert!(parser.parse_peek("123abcd;").is_err());
758 /// # }
759 /// ```
760 #[doc(alias = "satisfy")]
761 #[doc(alias = "filter")]
762 #[inline(always)]
763 fn verify<G, O2>(self, filter: G) -> impls::Verify<Self, G, I, O, O2, E>
764 where
765 Self: core::marker::Sized,
766 G: FnMut(&O2) -> bool,
767 I: Stream,
768 O: core::borrow::Borrow<O2>,
769 O2: ?Sized,
770 E: ParserError<I>,
771 {
772 impls::Verify {
773 parser: self,
774 filter,
775 marker: Default::default(),
776 }
777 }
778
779 /// If parsing fails, add context to the error
780 ///
781 /// This is used mainly to add user friendly information
782 /// to errors when backtracking through a parse tree.
783 ///
784 /// See also [tutorial][crate::_tutorial::chapter_7].
785 ///
786 /// # Example
787 ///
788 /// ```rust
789 /// # #[cfg(feature = "ascii")] {
790 /// # use winnow::prelude::*;
791 /// # use winnow::{error::ErrMode, Parser};
792 /// # use winnow::ascii::digit1;
793 /// # use winnow::error::StrContext;
794 /// # use winnow::error::StrContextValue;
795 ///
796 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
797 /// digit1
798 /// .context(StrContext::Expected(StrContextValue::Description("digit")))
799 /// .parse_next(input)
800 /// }
801 ///
802 /// assert_eq!(parser.parse_peek("123456"), Ok(("", "123456")));
803 /// assert!(parser.parse_peek("abc").is_err());
804 /// # }
805 /// ```
806 #[doc(alias = "labelled")]
807 #[inline(always)]
808 fn context<C>(self, context: C) -> impls::Context<Self, I, O, E, C>
809 where
810 Self: core::marker::Sized,
811 I: Stream,
812 E: AddContext<I, C>,
813 E: ParserError<I>,
814 C: Clone + core::fmt::Debug,
815 {
816 impls::Context {
817 parser: self,
818 context,
819 marker: Default::default(),
820 }
821 }
822
823 /// If parsing fails, dynamically add context to the error
824 ///
825 /// This is used mainly to add user friendly information
826 /// to errors when backtracking through a parse tree.
827 ///
828 /// See also [tutorial][crate::_tutorial::chapter_7].
829 ///
830 /// # Example
831 ///
832 /// ```rust
833 /// # #[cfg(feature = "ascii")] {
834 /// # use winnow::prelude::*;
835 /// # use winnow::{error::ErrMode, Parser};
836 /// # use winnow::ascii::digit1;
837 /// # use winnow::error::StrContext;
838 /// # use winnow::error::StrContextValue;
839 ///
840 /// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
841 /// digit1
842 /// .context_with(|| {
843 /// "0123456789".chars().map(|c| StrContext::Expected(c.into()))
844 /// })
845 /// .parse_next(input)
846 /// }
847 ///
848 /// assert_eq!(parser.parse_peek("123456"), Ok(("", "123456")));
849 /// assert!(parser.parse_peek("abc").is_err());
850 /// # }
851 /// ```
852 #[doc(alias = "labelled")]
853 #[inline(always)]
854 fn context_with<F, C, FI>(self, context: F) -> impls::ContextWith<Self, I, O, E, F, C, FI>
855 where
856 Self: core::marker::Sized,
857 I: Stream,
858 E: AddContext<I, C>,
859 E: ParserError<I>,
860 F: Fn() -> FI + Clone,
861 C: core::fmt::Debug,
862 FI: Iterator<Item = C>,
863 {
864 impls::ContextWith {
865 parser: self,
866 context,
867 marker: Default::default(),
868 }
869 }
870
871 /// Maps a function over the error of a parser
872 ///
873 /// # Example
874 ///
875 /// ```rust
876 /// # #[cfg(feature = "ascii")] {
877 /// # use winnow::prelude::*;
878 /// # use winnow::Parser;
879 /// # use winnow::Result;
880 /// # use winnow::ascii::digit1;
881 /// # use winnow::error::StrContext;
882 /// # use winnow::error::AddContext;
883 /// # use winnow::error::ContextError;
884 ///
885 /// fn parser<'i>(input: &mut &'i str) -> Result<&'i str> {
886 /// digit1.map_err(|mut e: ContextError| {
887 /// e.extend("0123456789".chars().map(|c| StrContext::Expected(c.into())));
888 /// e
889 /// }).parse_next(input)
890 /// }
891 ///
892 /// assert_eq!(parser.parse_peek("123456"), Ok(("", "123456")));
893 /// assert!(parser.parse_peek("abc").is_err());
894 /// # }
895 /// ```
896 #[inline(always)]
897 fn map_err<G, E2>(self, map: G) -> impls::MapErr<Self, G, I, O, E, E2>
898 where
899 G: FnMut(E) -> E2,
900 Self: core::marker::Sized,
901 {
902 impls::MapErr {
903 parser: self,
904 map,
905 marker: Default::default(),
906 }
907 }
908
909 /// Transforms [`Incomplete`][crate::error::ErrMode::Incomplete] into [`Backtrack`][crate::error::ErrMode::Backtrack]
910 ///
911 /// # Example
912 ///
913 /// ```rust
914 /// # use winnow::{error::ErrMode, error::InputError, stream::Partial, Parser};
915 /// # use winnow::token::take;
916 /// # use winnow::prelude::*;
917 /// # fn main() {
918 ///
919 /// fn parser<'i>(input: &mut Partial<&'i str>) -> ModalResult<&'i str, InputError<Partial<&'i str>>> {
920 /// take(5u8).complete_err().parse_next(input)
921 /// }
922 ///
923 /// assert_eq!(parser.parse_peek(Partial::new("abcdefg")), Ok((Partial::new("fg"), "abcde")));
924 /// assert_eq!(parser.parse_peek(Partial::new("abcd")), Err(ErrMode::Backtrack(InputError::at(Partial::new("abcd")))));
925 /// # }
926 /// ```
927 #[inline(always)]
928 fn complete_err(self) -> impls::CompleteErr<Self, I, O, E>
929 where
930 Self: core::marker::Sized,
931 {
932 impls::CompleteErr {
933 p: self,
934 marker: Default::default(),
935 }
936 }
937
938 /// Convert the parser's error to another type using [`std::convert::From`]
939 #[inline(always)]
940 fn err_into<E2>(self) -> impls::ErrInto<Self, I, O, E, E2>
941 where
942 Self: core::marker::Sized,
943 E: Into<E2>,
944 {
945 impls::ErrInto {
946 parser: self,
947 marker: Default::default(),
948 }
949 }
950
951 /// Recover from an error by skipping everything `recover` consumes and trying again
952 ///
953 /// If `recover` consumes nothing, the error is returned, allowing an alternative recovery
954 /// method.
955 ///
956 /// This commits the parse result, preventing alternative branch paths like with
957 /// [`winnow::combinator::alt`][crate::combinator::alt].
958 #[inline(always)]
959 #[cfg(feature = "unstable-recover")]
960 #[cfg(feature = "std")]
961 fn retry_after<R>(self, recover: R) -> impls::RetryAfter<Self, R, I, O, E>
962 where
963 Self: core::marker::Sized,
964 R: Parser<I, (), E>,
965 I: Stream,
966 I: Recover<E>,
967 E: ParserError<I> + FromRecoverableError<I, E>,
968 {
969 impls::RetryAfter {
970 parser: self,
971 recover,
972 marker: Default::default(),
973 }
974 }
975
976 /// Recover from an error by skipping this parse and everything `recover` consumes
977 ///
978 /// This commits the parse result, preventing alternative branch paths like with
979 /// [`winnow::combinator::alt`][crate::combinator::alt].
980 #[inline(always)]
981 #[cfg(feature = "unstable-recover")]
982 #[cfg(feature = "std")]
983 fn resume_after<R>(self, recover: R) -> impls::ResumeAfter<Self, R, I, O, E>
984 where
985 Self: core::marker::Sized,
986 R: Parser<I, (), E>,
987 I: Stream,
988 I: Recover<E>,
989 E: ParserError<I> + FromRecoverableError<I, E>,
990 {
991 impls::ResumeAfter {
992 parser: self,
993 recover,
994 marker: Default::default(),
995 }
996 }
997}
998
999impl<I, O, E, F> Parser<I, O, E> for F
1000where
1001 F: FnMut(&mut I) -> Result<O, E>,
1002 I: Stream,
1003{
1004 #[inline(always)]
1005 fn parse_next(&mut self, i: &mut I) -> Result<O, E> {
1006 self(i)
1007 }
1008}
1009
1010/// This is a shortcut for [`one_of`][crate::token::one_of].
1011///
1012/// # Example
1013///
1014/// ```rust
1015/// # use winnow::prelude::*;
1016/// # use winnow::{error::ErrMode, error::ContextError};
1017/// fn parser<'s>(i: &mut &'s [u8]) -> ModalResult<u8> {
1018/// b'a'.parse_next(i)
1019/// }
1020/// assert_eq!(parser.parse_peek(&b"abc"[..]), Ok((&b"bc"[..], b'a')));
1021/// assert!(parser.parse_peek(&b" abc"[..]).is_err());
1022/// assert!(parser.parse_peek(&b"bc"[..]).is_err());
1023/// assert!(parser.parse_peek(&b""[..]).is_err());
1024/// ```
1025impl<I, E> Parser<I, u8, E> for u8
1026where
1027 I: StreamIsPartial,
1028 I: Stream,
1029 I: Compare<u8>,
1030 E: ParserError<I>,
1031{
1032 #[inline(always)]
1033 fn parse_next(&mut self, i: &mut I) -> Result<u8, E> {
1034 crate::token::literal(*self).value(*self).parse_next(i)
1035 }
1036}
1037
1038/// This is a shortcut for [`one_of`][crate::token::one_of].
1039///
1040/// # Example
1041///
1042/// ```rust
1043/// # use winnow::prelude::*;
1044/// # use winnow::{error::ErrMode, error::ContextError};
1045/// fn parser<'s>(i: &mut &'s str) -> ModalResult<char> {
1046/// 'a'.parse_next(i)
1047/// }
1048/// assert_eq!(parser.parse_peek("abc"), Ok(("bc", 'a')));
1049/// assert!(parser.parse_peek(" abc").is_err());
1050/// assert!(parser.parse_peek("bc").is_err());
1051/// assert!(parser.parse_peek("").is_err());
1052/// ```
1053impl<I, E> Parser<I, char, E> for char
1054where
1055 I: StreamIsPartial,
1056 I: Stream,
1057 I: Compare<char>,
1058 E: ParserError<I>,
1059{
1060 #[inline(always)]
1061 fn parse_next(&mut self, i: &mut I) -> Result<char, E> {
1062 crate::token::literal(*self).value(*self).parse_next(i)
1063 }
1064}
1065
1066/// This is a shortcut for [`literal`][crate::token::literal].
1067///
1068/// # Example
1069/// ```rust
1070/// # use winnow::prelude::*;
1071/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
1072/// # use winnow::combinator::alt;
1073/// # use winnow::token::take;
1074///
1075/// fn parser<'s>(s: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
1076/// alt((&"Hello"[..], take(5usize))).parse_next(s)
1077/// }
1078///
1079/// assert_eq!(parser.parse_peek(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
1080/// assert_eq!(parser.parse_peek(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
1081/// assert!(parser.parse_peek(&b"Some"[..]).is_err());
1082/// assert!(parser.parse_peek(&b""[..]).is_err());
1083/// ```
1084impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for &'s [u8]
1085where
1086 I: Compare<&'s [u8]> + StreamIsPartial,
1087 I: Stream,
1088{
1089 #[inline(always)]
1090 fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
1091 crate::token::literal(*self).parse_next(i)
1092 }
1093}
1094
1095/// This is a shortcut for [`literal`][crate::token::literal].
1096///
1097/// # Example
1098/// ```rust
1099/// # use winnow::prelude::*;
1100/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
1101/// # use winnow::combinator::alt;
1102/// # use winnow::token::take;
1103///
1104/// fn parser<'s>(s: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
1105/// alt((b"Hello", take(5usize))).parse_next(s)
1106/// }
1107///
1108/// assert_eq!(parser.parse_peek(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
1109/// assert_eq!(parser.parse_peek(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
1110/// assert!(parser.parse_peek(&b"Some"[..]).is_err());
1111/// assert!(parser.parse_peek(&b""[..]).is_err());
1112/// ```
1113impl<'s, I, E: ParserError<I>, const N: usize> Parser<I, <I as Stream>::Slice, E> for &'s [u8; N]
1114where
1115 I: Compare<&'s [u8; N]> + StreamIsPartial,
1116 I: Stream,
1117{
1118 #[inline(always)]
1119 fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
1120 crate::token::literal(*self).parse_next(i)
1121 }
1122}
1123
1124/// This is a shortcut for [`literal`][crate::token::literal].
1125///
1126/// # Example
1127/// ```rust
1128/// # use winnow::prelude::*;
1129/// # use winnow::{error::ErrMode, error::ContextError};
1130/// # use winnow::combinator::alt;
1131/// # use winnow::token::take;
1132///
1133/// fn parser<'s>(s: &mut &'s str) -> ModalResult<&'s str> {
1134/// alt(("Hello", take(5usize))).parse_next(s)
1135/// }
1136///
1137/// assert_eq!(parser.parse_peek("Hello, World!"), Ok((", World!", "Hello")));
1138/// assert_eq!(parser.parse_peek("Something"), Ok(("hing", "Somet")));
1139/// assert!(parser.parse_peek("Some").is_err());
1140/// assert!(parser.parse_peek("").is_err());
1141/// ```
1142impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for &'s str
1143where
1144 I: Compare<&'s str> + StreamIsPartial,
1145 I: Stream,
1146{
1147 #[inline(always)]
1148 fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
1149 crate::token::literal(*self).parse_next(i)
1150 }
1151}
1152
1153impl<I: Stream, E: ParserError<I>> Parser<I, (), E> for () {
1154 #[inline(always)]
1155 fn parse_next(&mut self, _i: &mut I) -> Result<(), E> {
1156 Ok(())
1157 }
1158}
1159
1160macro_rules! impl_parser_for_tuple {
1161 ($($index:tt $parser:ident $output:ident),+) => (
1162 #[allow(non_snake_case)]
1163 impl<I: Stream, $($output),+, E: ParserError<I>, $($parser),+> Parser<I, ($($output),+,), E> for ($($parser),+,)
1164 where
1165 $($parser: Parser<I, $output, E>),+
1166 {
1167 #[inline(always)]
1168 fn parse_next(&mut self, i: &mut I) -> Result<($($output),+,), E> {
1169 $(let $output = self.$index.parse_next(i)?;)+
1170
1171 Ok(($($output),+,))
1172 }
1173 }
1174 )
1175}
1176
1177macro_rules! impl_parser_for_tuples {
1178 ($index1:tt $parser1:ident $output1:ident, $($index:tt $parser:ident $output:ident),+) => {
1179 impl_parser_for_tuples!(__impl $index1 $parser1 $output1; $($index $parser $output),+);
1180 };
1181 (__impl $($index:tt $parser:ident $output:ident),+; $index1:tt $parser1:ident $output1:ident $(,$index2:tt $parser2:ident $output2:ident)*) => {
1182 impl_parser_for_tuple!($($index $parser $output),+);
1183 impl_parser_for_tuples!(__impl $($index $parser $output),+, $index1 $parser1 $output1; $($index2 $parser2 $output2),*);
1184 };
1185 (__impl $($index:tt $parser:ident $output:ident),+;) => {
1186 impl_parser_for_tuple!($($index $parser $output),+);
1187 }
1188}
1189
1190impl_parser_for_tuples!(
1191 0 P0 O0,
1192 1 P1 O1,
1193 2 P2 O2,
1194 3 P3 O3,
1195 4 P4 O4,
1196 5 P5 O5,
1197 6 P6 O6,
1198 7 P7 O7,
1199 8 P8 O8,
1200 9 P9 O9,
1201 10 P10 O10
1202);
1203
1204#[cfg(feature = "alloc")]
1205use alloc::boxed::Box;
1206
1207#[cfg(feature = "alloc")]
1208impl<I, O, E> Parser<I, O, E> for Box<dyn Parser<I, O, E> + '_> {
1209 #[inline(always)]
1210 fn parse_next(&mut self, i: &mut I) -> Result<O, E> {
1211 (**self).parse_next(i)
1212 }
1213}
1214
1215/// Trait alias for [`Parser`] to be used with [`ModalResult`][crate::error::ModalResult]
1216pub trait ModalParser<I, O, E>: Parser<I, O, crate::error::ErrMode<E>> {}
1217
1218impl<I, O, E, P> ModalParser<I, O, E> for P where P: Parser<I, O, crate::error::ErrMode<E>> {}
1219
1220/// Collect all errors when parsing the input
1221///
1222/// [`Parser`]s will need to use [`Recoverable<I, _>`] for their input.
1223#[cfg(feature = "unstable-recover")]
1224#[cfg(feature = "std")]
1225pub trait RecoverableParser<I, O, R, E> {
1226 /// Collect all errors when parsing the input
1227 ///
1228 /// If `self` fails, this acts like [`Parser::resume_after`] and returns `Ok(None)`.
1229 /// Generally, this should be avoided by using
1230 /// [`Parser::retry_after`] and [`Parser::resume_after`] throughout your parser.
1231 ///
1232 /// The empty `input` is returned to allow turning the errors into [`ParserError`]s.
1233 fn recoverable_parse(&mut self, input: I) -> (I, Option<O>, Vec<R>);
1234}
1235
1236#[cfg(feature = "unstable-recover")]
1237#[cfg(feature = "std")]
1238impl<P, I, O, R, E> RecoverableParser<I, O, R, E> for P
1239where
1240 P: Parser<Recoverable<I, R>, O, E>,
1241 I: Stream,
1242 I: StreamIsPartial,
1243 R: FromRecoverableError<Recoverable<I, R>, E>,
1244 R: core::fmt::Debug,
1245 E: FromRecoverableError<Recoverable<I, R>, E>,
1246 E: ParserError<Recoverable<I, R>>,
1247 E: core::fmt::Debug,
1248{
1249 fn recoverable_parse(&mut self, input: I) -> (I, Option<O>, Vec<R>) {
1250 debug_assert!(
1251 !I::is_partial_supported(),
1252 "partial streams need to handle `ErrMode::Incomplete`"
1253 );
1254
1255 let start = input.checkpoint();
1256 let mut input = Recoverable::new(input);
1257 let start_token = input.checkpoint();
1258 let result = (
1259 self.by_ref(),
1260 crate::combinator::eof.resume_after(crate::token::rest.void()),
1261 )
1262 .parse_next(&mut input);
1263
1264 let (o, err) = match result {
1265 Ok((o, _)) => (Some(o), None),
1266 Err(err) => {
1267 let err_start = input.checkpoint();
1268 let err = R::from_recoverable_error(&start_token, &err_start, &input, err);
1269 (None, Some(err))
1270 }
1271 };
1272
1273 let (mut input, mut errs) = input.into_parts();
1274 input.reset(&start);
1275 if let Some(err) = err {
1276 errs.push(err);
1277 }
1278
1279 (input, o, errs)
1280 }
1281}
1282
1283#[cfg(all(test, feature = "ascii", feature = "binary"))]
1284mod tests {
1285 use super::*;
1286
1287 use snapbox::prelude::*;
1288 use snapbox::str;
1289
1290 use crate::binary::be_u16;
1291 use crate::error::ErrMode;
1292 use crate::error::Needed;
1293 use crate::error::TestResult;
1294 use crate::token::take;
1295 use crate::Partial;
1296
1297 #[doc(hidden)]
1298 #[macro_export]
1299 macro_rules! assert_size (
1300 ($t:ty, $sz:expr) => (
1301 assert!(core::mem::size_of::<$t>() <= $sz, "{} <= {} failed", core::mem::size_of::<$t>(), $sz);
1302 );
1303 );
1304
1305 #[test]
1306 #[cfg(target_pointer_width = "64")]
1307 fn size_test() {
1308 assert_size!(Result<&[u8], (&[u8], u32)>, 40);
1309 assert_size!(Result<&str, u32>, 40);
1310 assert_size!(Needed, 8);
1311 assert_size!(ErrMode<u32>, 16);
1312 }
1313
1314 #[test]
1315 fn err_map_test() {
1316 let e = ErrMode::Backtrack(1);
1317 assert_eq!(e.map(|v| v + 1), ErrMode::Backtrack(2));
1318 }
1319
1320 #[test]
1321 fn single_element_tuples() {
1322 use crate::ascii::alpha1;
1323
1324 let mut parser = (alpha1,);
1325 assert_parse!(
1326 parser.parse_peek("abc123def"),
1327 str![[r#"
1328Ok(
1329 (
1330 "123def",
1331 (
1332 "abc",
1333 ),
1334 ),
1335)
1336
1337"#]]
1338 .raw()
1339 );
1340 assert_parse!(
1341 parser.parse_peek("123def"),
1342 str![[r#"
1343Err(
1344 Backtrack(
1345 InputError {
1346 input: "123def",
1347 },
1348 ),
1349)
1350
1351"#]]
1352 .raw()
1353 );
1354 }
1355
1356 #[test]
1357 fn tuple_test() {
1358 #[allow(clippy::type_complexity)]
1359 fn tuple_3<'i>(
1360 i: &mut Partial<&'i [u8]>,
1361 ) -> TestResult<Partial<&'i [u8]>, (u16, &'i [u8], &'i [u8])> {
1362 (be_u16, take(3u8), "fg").parse_next(i)
1363 }
1364
1365 assert_parse!(
1366 tuple_3.parse_peek(Partial::new(&b"abcdefgh"[..])),
1367 str![[r#"
1368Ok(
1369 (
1370 Partial {
1371 input: [
1372 104,
1373 ],
1374 partial: true,
1375 },
1376 (
1377 24930,
1378 [
1379 99,
1380 100,
1381 101,
1382 ],
1383 [
1384 102,
1385 103,
1386 ],
1387 ),
1388 ),
1389)
1390
1391"#]]
1392 .raw()
1393 );
1394 assert_parse!(
1395 tuple_3.parse_peek(Partial::new(&b"abcd"[..])),
1396 str![[r#"
1397Err(
1398 Incomplete(
1399 Size(
1400 1,
1401 ),
1402 ),
1403)
1404
1405"#]]
1406 .raw()
1407 );
1408 assert_parse!(
1409 tuple_3.parse_peek(Partial::new(&b"abcde"[..])),
1410 str![[r#"
1411Err(
1412 Incomplete(
1413 Unknown,
1414 ),
1415)
1416
1417"#]]
1418 .raw()
1419 );
1420 assert_parse!(
1421 tuple_3.parse_peek(Partial::new(&b"abcdejk"[..])),
1422 str![[r#"
1423Err(
1424 Backtrack(
1425 InputError {
1426 input: Partial {
1427 input: [
1428 106,
1429 107,
1430 ],
1431 partial: true,
1432 },
1433 },
1434 ),
1435)
1436
1437"#]]
1438 .raw()
1439 );
1440 }
1441
1442 #[test]
1443 fn unit_type() {
1444 fn parser<'i>(i: &mut &'i str) -> TestResult<&'i str, ()> {
1445 ().parse_next(i)
1446 }
1447 assert_parse!(
1448 parser.parse_peek("abxsbsh"),
1449 str![[r#"
1450Ok(
1451 (
1452 "abxsbsh",
1453 (),
1454 ),
1455)
1456
1457"#]]
1458 .raw()
1459 );
1460 assert_parse!(
1461 parser.parse_peek("sdfjakdsas"),
1462 str![[r#"
1463Ok(
1464 (
1465 "sdfjakdsas",
1466 (),
1467 ),
1468)
1469
1470"#]]
1471 .raw()
1472 );
1473 assert_parse!(
1474 parser.parse_peek(""),
1475 str![[r#"
1476Ok(
1477 (
1478 "",
1479 (),
1480 ),
1481)
1482
1483"#]]
1484 .raw()
1485 );
1486 }
1487}