/rust/registry/src/index.crates.io-1949cf8c6b5b557f/winnow-1.0.1/src/parser.rs
Line | Count | Source |
1 | | //! Basic types to build the parsers |
2 | | |
3 | | use crate::combinator::impls; |
4 | | #[cfg(feature = "unstable-recover")] |
5 | | #[cfg(feature = "std")] |
6 | | use crate::error::FromRecoverableError; |
7 | | use crate::error::{AddContext, FromExternalError, ParseError, ParserError, Result}; |
8 | | use crate::stream::{Compare, Location, ParseSlice, Stream, StreamIsPartial}; |
9 | | #[cfg(feature = "unstable-recover")] |
10 | | #[cfg(feature = "std")] |
11 | | use 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] |
47 | | pub 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 | 0 | fn parse(&mut self, mut input: I) -> Result<O, ParseError<I, <E as ParserError<I>>::Inner>> |
63 | 0 | where |
64 | 0 | Self: core::marker::Sized, |
65 | 0 | I: Stream, |
66 | 0 | // Force users to deal with `Incomplete` when `StreamIsPartial<true>` |
67 | 0 | I: StreamIsPartial, |
68 | 0 | E: ParserError<I>, |
69 | 0 | <E as ParserError<I>>::Inner: ParserError<I>, |
70 | | { |
71 | 0 | debug_assert!( |
72 | 0 | !I::is_partial_supported(), |
73 | | "partial streams need to handle `ErrMode::Incomplete`" |
74 | | ); |
75 | | |
76 | 0 | let start = input.checkpoint(); |
77 | 0 | let (o, _) = (self.by_ref(), crate::combinator::eof) |
78 | 0 | .parse_next(&mut input) |
79 | 0 | .map_err(|e| { |
80 | 0 | let e = e.into_inner().unwrap_or_else(|_err| { |
81 | 0 | panic!("complete parsers should not report `ErrMode::Incomplete(_)`") |
82 | | }); |
83 | 0 | ParseError::new(input, start, e) |
84 | 0 | })?; |
85 | 0 | Ok(o) |
86 | 0 | } |
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 | 0 | fn parse_iter(&mut self, input: I) -> impls::ParseIter<'_, Self, I, O, E> |
117 | 0 | where |
118 | 0 | Self: core::marker::Sized, |
119 | 0 | I: Stream, |
120 | 0 | // Force users to deal with `Incomplete` when `StreamIsPartial<true>` |
121 | 0 | I: StreamIsPartial, |
122 | 0 | E: ParserError<I>, |
123 | 0 | <E as ParserError<I>>::Inner: ParserError<I>, |
124 | | { |
125 | 0 | debug_assert!( |
126 | 0 | !I::is_partial_supported(), |
127 | | "partial streams need to handle `ErrMode::Incomplete`" |
128 | | ); |
129 | | |
130 | 0 | let start = input.checkpoint(); |
131 | 0 | impls::ParseIter { |
132 | 0 | parser: self, |
133 | 0 | input: Some(input), |
134 | 0 | start: Some(start), |
135 | 0 | marker: Default::default(), |
136 | 0 | } |
137 | 0 | } |
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 | 0 | fn parse_peek(&mut self, mut input: I) -> Result<(I, O), E> { |
165 | 0 | match self.parse_next(&mut input) { |
166 | 0 | Ok(o) => Ok((input, o)), |
167 | 0 | Err(err) => Err(err), |
168 | | } |
169 | 0 | } |
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 | 0 | fn by_ref(&mut self) -> impls::ByRef<'_, Self, I, O, E> |
218 | 0 | where |
219 | 0 | Self: core::marker::Sized, |
220 | | { |
221 | 0 | impls::ByRef { |
222 | 0 | p: self, |
223 | 0 | marker: Default::default(), |
224 | 0 | } |
225 | 0 | } |
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 | 0 | fn value<O2>(self, val: O2) -> impls::Value<Self, I, O, O2, E> |
248 | 0 | where |
249 | 0 | Self: core::marker::Sized, |
250 | 0 | O2: Clone, |
251 | | { |
252 | 0 | impls::Value { |
253 | 0 | parser: self, |
254 | 0 | val, |
255 | 0 | marker: Default::default(), |
256 | 0 | } |
257 | 0 | } |
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 | 0 | fn default_value<O2>(self) -> impls::DefaultValue<Self, I, O, O2, E> |
279 | 0 | where |
280 | 0 | Self: core::marker::Sized, |
281 | 0 | O2: core::default::Default, |
282 | | { |
283 | 0 | impls::DefaultValue { |
284 | 0 | parser: self, |
285 | 0 | marker: Default::default(), |
286 | 0 | } |
287 | 0 | } |
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 | 0 | fn void(self) -> impls::Void<Self, I, O, E> |
309 | 0 | where |
310 | 0 | Self: core::marker::Sized, |
311 | | { |
312 | 0 | impls::Void { |
313 | 0 | parser: self, |
314 | 0 | marker: Default::default(), |
315 | 0 | } |
316 | 0 | } |
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 | 0 | fn output_into<O2>(self) -> impls::OutputInto<Self, I, O, O2, E> |
341 | 0 | where |
342 | 0 | Self: core::marker::Sized, |
343 | 0 | O: Into<O2>, |
344 | | { |
345 | 0 | impls::OutputInto { |
346 | 0 | parser: self, |
347 | 0 | marker: Default::default(), |
348 | 0 | } |
349 | 0 | } |
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 | 0 | fn take(self) -> impls::Take<Self, I, O, E> |
374 | 0 | where |
375 | 0 | Self: core::marker::Sized, |
376 | 0 | I: Stream, |
377 | | { |
378 | 0 | impls::Take { |
379 | 0 | parser: self, |
380 | 0 | marker: Default::default(), |
381 | 0 | } |
382 | 0 | } |
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 | 0 | fn with_taken(self) -> impls::WithTaken<Self, I, O, E> |
416 | 0 | where |
417 | 0 | Self: core::marker::Sized, |
418 | 0 | I: Stream, |
419 | | { |
420 | 0 | impls::WithTaken { |
421 | 0 | parser: self, |
422 | 0 | marker: Default::default(), |
423 | 0 | } |
424 | 0 | } |
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 | 0 | fn span(self) -> impls::Span<Self, I, O, E> |
449 | 0 | where |
450 | 0 | Self: core::marker::Sized, |
451 | 0 | I: Stream + Location, |
452 | | { |
453 | 0 | impls::Span { |
454 | 0 | parser: self, |
455 | 0 | marker: Default::default(), |
456 | 0 | } |
457 | 0 | } |
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 | 0 | fn with_span(self) -> impls::WithSpan<Self, I, O, E> |
491 | 0 | where |
492 | 0 | Self: core::marker::Sized, |
493 | 0 | I: Stream + Location, |
494 | | { |
495 | 0 | impls::WithSpan { |
496 | 0 | parser: self, |
497 | 0 | marker: Default::default(), |
498 | 0 | } |
499 | 0 | } |
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 | 0 | fn map<G, O2>(self, map: G) -> impls::Map<Self, G, I, O, O2, E> |
524 | 0 | where |
525 | 0 | G: FnMut(O) -> O2, |
526 | 0 | Self: core::marker::Sized, |
527 | | { |
528 | 0 | impls::Map { |
529 | 0 | parser: self, |
530 | 0 | map, |
531 | 0 | marker: Default::default(), |
532 | 0 | } |
533 | 0 | } |
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 | 0 | fn try_map<G, O2, E2>(self, map: G) -> impls::TryMap<Self, G, I, O, O2, E, E2> |
561 | 0 | where |
562 | 0 | Self: core::marker::Sized, |
563 | 0 | G: FnMut(O) -> Result<O2, E2>, |
564 | 0 | I: Stream, |
565 | 0 | E: FromExternalError<I, E2>, |
566 | 0 | E: ParserError<I>, |
567 | | { |
568 | 0 | impls::TryMap { |
569 | 0 | parser: self, |
570 | 0 | map, |
571 | 0 | marker: Default::default(), |
572 | 0 | } |
573 | 0 | } |
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 | 0 | fn verify_map<G, O2>(self, map: G) -> impls::VerifyMap<Self, G, I, O, O2, E> |
604 | 0 | where |
605 | 0 | Self: core::marker::Sized, |
606 | 0 | G: FnMut(O) -> Option<O2>, |
607 | 0 | I: Stream, |
608 | 0 | E: ParserError<I>, |
609 | | { |
610 | 0 | impls::VerifyMap { |
611 | 0 | parser: self, |
612 | 0 | map, |
613 | 0 | marker: Default::default(), |
614 | 0 | } |
615 | 0 | } |
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 | 0 | fn flat_map<G, H, O2>(self, map: G) -> impls::FlatMap<Self, G, H, I, O, O2, E> |
655 | 0 | where |
656 | 0 | Self: core::marker::Sized, |
657 | 0 | G: FnMut(O) -> H, |
658 | 0 | H: Parser<I, O2, E>, |
659 | | { |
660 | 0 | impls::FlatMap { |
661 | 0 | f: self, |
662 | 0 | g: map, |
663 | 0 | marker: Default::default(), |
664 | 0 | } |
665 | 0 | } |
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 | 0 | fn and_then<G, O2>(self, inner: G) -> impls::AndThen<Self, G, I, O, O2, E> |
689 | 0 | where |
690 | 0 | Self: core::marker::Sized, |
691 | 0 | G: Parser<O, O2, E>, |
692 | 0 | O: StreamIsPartial, |
693 | 0 | I: Stream, |
694 | | { |
695 | 0 | impls::AndThen { |
696 | 0 | outer: self, |
697 | 0 | inner, |
698 | 0 | marker: Default::default(), |
699 | 0 | } |
700 | 0 | } |
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 | 0 | fn parse_to<O2>(self) -> impls::ParseTo<Self, I, O, O2, E> |
726 | 0 | where |
727 | 0 | Self: core::marker::Sized, |
728 | 0 | I: Stream, |
729 | 0 | O: ParseSlice<O2>, |
730 | 0 | E: ParserError<I>, |
731 | | { |
732 | 0 | impls::ParseTo { |
733 | 0 | p: self, |
734 | 0 | marker: Default::default(), |
735 | 0 | } |
736 | 0 | } |
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 | 0 | fn verify<G, O2>(self, filter: G) -> impls::Verify<Self, G, I, O, O2, E> |
764 | 0 | where |
765 | 0 | Self: core::marker::Sized, |
766 | 0 | G: FnMut(&O2) -> bool, |
767 | 0 | I: Stream, |
768 | 0 | O: core::borrow::Borrow<O2>, |
769 | 0 | O2: ?Sized, |
770 | 0 | E: ParserError<I>, |
771 | | { |
772 | 0 | impls::Verify { |
773 | 0 | parser: self, |
774 | 0 | filter, |
775 | 0 | marker: Default::default(), |
776 | 0 | } |
777 | 0 | } |
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 | 0 | fn context<C>(self, context: C) -> impls::Context<Self, I, O, E, C> |
809 | 0 | where |
810 | 0 | Self: core::marker::Sized, |
811 | 0 | I: Stream, |
812 | 0 | E: AddContext<I, C>, |
813 | 0 | E: ParserError<I>, |
814 | 0 | C: Clone + core::fmt::Debug, |
815 | | { |
816 | 0 | impls::Context { |
817 | 0 | parser: self, |
818 | 0 | context, |
819 | 0 | marker: Default::default(), |
820 | 0 | } |
821 | 0 | } |
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 | 0 | fn context_with<F, C, FI>(self, context: F) -> impls::ContextWith<Self, I, O, E, F, C, FI> |
855 | 0 | where |
856 | 0 | Self: core::marker::Sized, |
857 | 0 | I: Stream, |
858 | 0 | E: AddContext<I, C>, |
859 | 0 | E: ParserError<I>, |
860 | 0 | F: Fn() -> FI + Clone, |
861 | 0 | C: core::fmt::Debug, |
862 | 0 | FI: Iterator<Item = C>, |
863 | | { |
864 | 0 | impls::ContextWith { |
865 | 0 | parser: self, |
866 | 0 | context, |
867 | 0 | marker: Default::default(), |
868 | 0 | } |
869 | 0 | } |
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 | 0 | fn map_err<G, E2>(self, map: G) -> impls::MapErr<Self, G, I, O, E, E2> |
898 | 0 | where |
899 | 0 | G: FnMut(E) -> E2, |
900 | 0 | Self: core::marker::Sized, |
901 | | { |
902 | 0 | impls::MapErr { |
903 | 0 | parser: self, |
904 | 0 | map, |
905 | 0 | marker: Default::default(), |
906 | 0 | } |
907 | 0 | } |
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 | 0 | fn complete_err(self) -> impls::CompleteErr<Self, I, O, E> |
929 | 0 | where |
930 | 0 | Self: core::marker::Sized, |
931 | | { |
932 | 0 | impls::CompleteErr { |
933 | 0 | p: self, |
934 | 0 | marker: Default::default(), |
935 | 0 | } |
936 | 0 | } |
937 | | |
938 | | /// Convert the parser's error to another type using [`std::convert::From`] |
939 | | #[inline(always)] |
940 | 0 | fn err_into<E2>(self) -> impls::ErrInto<Self, I, O, E, E2> |
941 | 0 | where |
942 | 0 | Self: core::marker::Sized, |
943 | 0 | E: Into<E2>, |
944 | | { |
945 | 0 | impls::ErrInto { |
946 | 0 | parser: self, |
947 | 0 | marker: Default::default(), |
948 | 0 | } |
949 | 0 | } |
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 | | |
999 | | impl<I, O, E, F> Parser<I, O, E> for F |
1000 | | where |
1001 | | F: FnMut(&mut I) -> Result<O, E>, |
1002 | | I: Stream, |
1003 | | { |
1004 | | #[inline(always)] |
1005 | 0 | fn parse_next(&mut self, i: &mut I) -> Result<O, E> { |
1006 | 0 | self(i) |
1007 | 0 | } |
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 | | /// ``` |
1025 | | impl<I, E> Parser<I, u8, E> for u8 |
1026 | | where |
1027 | | I: StreamIsPartial, |
1028 | | I: Stream, |
1029 | | I: Compare<u8>, |
1030 | | E: ParserError<I>, |
1031 | | { |
1032 | | #[inline(always)] |
1033 | 0 | fn parse_next(&mut self, i: &mut I) -> Result<u8, E> { |
1034 | 0 | crate::token::literal(*self).value(*self).parse_next(i) |
1035 | 0 | } |
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 | | /// ``` |
1053 | | impl<I, E> Parser<I, char, E> for char |
1054 | | where |
1055 | | I: StreamIsPartial, |
1056 | | I: Stream, |
1057 | | I: Compare<char>, |
1058 | | E: ParserError<I>, |
1059 | | { |
1060 | | #[inline(always)] |
1061 | 0 | fn parse_next(&mut self, i: &mut I) -> Result<char, E> { |
1062 | 0 | crate::token::literal(*self).value(*self).parse_next(i) |
1063 | 0 | } |
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 | | /// ``` |
1084 | | impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for &'s [u8] |
1085 | | where |
1086 | | I: Compare<&'s [u8]> + StreamIsPartial, |
1087 | | I: Stream, |
1088 | | { |
1089 | | #[inline(always)] |
1090 | 0 | fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> { |
1091 | 0 | crate::token::literal(*self).parse_next(i) |
1092 | 0 | } |
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 | | /// ``` |
1113 | | impl<'s, I, E: ParserError<I>, const N: usize> Parser<I, <I as Stream>::Slice, E> for &'s [u8; N] |
1114 | | where |
1115 | | I: Compare<&'s [u8; N]> + StreamIsPartial, |
1116 | | I: Stream, |
1117 | | { |
1118 | | #[inline(always)] |
1119 | 0 | fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> { |
1120 | 0 | crate::token::literal(*self).parse_next(i) |
1121 | 0 | } |
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 | | /// ``` |
1142 | | impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for &'s str |
1143 | | where |
1144 | | I: Compare<&'s str> + StreamIsPartial, |
1145 | | I: Stream, |
1146 | | { |
1147 | | #[inline(always)] |
1148 | 0 | fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> { |
1149 | 0 | crate::token::literal(*self).parse_next(i) |
1150 | 0 | } |
1151 | | } |
1152 | | |
1153 | | impl<I: Stream, E: ParserError<I>> Parser<I, (), E> for () { |
1154 | | #[inline(always)] |
1155 | 0 | fn parse_next(&mut self, _i: &mut I) -> Result<(), E> { |
1156 | 0 | Ok(()) |
1157 | 0 | } |
1158 | | } |
1159 | | |
1160 | | macro_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 | 0 | fn parse_next(&mut self, i: &mut I) -> Result<($($output),+,), E> { |
1169 | 0 | $(let $output = self.$index.parse_next(i)?;)+ |
1170 | | |
1171 | 0 | Ok(($($output),+,)) |
1172 | 0 | } Unexecuted instantiation: <(_,) as winnow::parser::Parser<_, (_,), _>>::parse_next Unexecuted instantiation: <(_, _) as winnow::parser::Parser<_, (_, _), _>>::parse_next Unexecuted instantiation: <(_, _, _) as winnow::parser::Parser<_, (_, _, _), _>>::parse_next Unexecuted instantiation: <(_, _, _, _) as winnow::parser::Parser<_, (_, _, _, _), _>>::parse_next Unexecuted instantiation: <(_, _, _, _, _) as winnow::parser::Parser<_, (_, _, _, _, _), _>>::parse_next Unexecuted instantiation: <(_, _, _, _, _, _) as winnow::parser::Parser<_, (_, _, _, _, _, _), _>>::parse_next Unexecuted instantiation: <(_, _, _, _, _, _, _) as winnow::parser::Parser<_, (_, _, _, _, _, _, _), _>>::parse_next Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as winnow::parser::Parser<_, (_, _, _, _, _, _, _, _), _>>::parse_next Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as winnow::parser::Parser<_, (_, _, _, _, _, _, _, _, _), _>>::parse_next Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as winnow::parser::Parser<_, (_, _, _, _, _, _, _, _, _, _), _>>::parse_next Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _) as winnow::parser::Parser<_, (_, _, _, _, _, _, _, _, _, _, _), _>>::parse_next |
1173 | | } |
1174 | | ) |
1175 | | } |
1176 | | |
1177 | | macro_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 | | |
1190 | | impl_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")] |
1205 | | use alloc::boxed::Box; |
1206 | | |
1207 | | #[cfg(feature = "alloc")] |
1208 | | impl<I, O, E> Parser<I, O, E> for Box<dyn Parser<I, O, E> + '_> { |
1209 | | #[inline(always)] |
1210 | 0 | fn parse_next(&mut self, i: &mut I) -> Result<O, E> { |
1211 | 0 | (**self).parse_next(i) |
1212 | 0 | } |
1213 | | } |
1214 | | |
1215 | | /// Trait alias for [`Parser`] to be used with [`ModalResult`][crate::error::ModalResult] |
1216 | | pub trait ModalParser<I, O, E>: Parser<I, O, crate::error::ErrMode<E>> {} |
1217 | | |
1218 | | impl<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")] |
1225 | | pub 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")] |
1238 | | impl<P, I, O, R, E> RecoverableParser<I, O, R, E> for P |
1239 | | where |
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"))] |
1284 | | mod 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#" |
1328 | | Ok( |
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#" |
1343 | | Err( |
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#" |
1368 | | Ok( |
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#" |
1397 | | Err( |
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#" |
1411 | | Err( |
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#" |
1423 | | Err( |
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#" |
1450 | | Ok( |
1451 | | ( |
1452 | | "abxsbsh", |
1453 | | (), |
1454 | | ), |
1455 | | ) |
1456 | | |
1457 | | "#]] |
1458 | | .raw() |
1459 | | ); |
1460 | | assert_parse!( |
1461 | | parser.parse_peek("sdfjakdsas"), |
1462 | | str![[r#" |
1463 | | Ok( |
1464 | | ( |
1465 | | "sdfjakdsas", |
1466 | | (), |
1467 | | ), |
1468 | | ) |
1469 | | |
1470 | | "#]] |
1471 | | .raw() |
1472 | | ); |
1473 | | assert_parse!( |
1474 | | parser.parse_peek(""), |
1475 | | str![[r#" |
1476 | | Ok( |
1477 | | ( |
1478 | | "", |
1479 | | (), |
1480 | | ), |
1481 | | ) |
1482 | | |
1483 | | "#]] |
1484 | | .raw() |
1485 | | ); |
1486 | | } |
1487 | | } |