1 //! Module containing zero-copy parsers.
2 //!
3 //! These parsers require the [`RangeStream`][] bound instead of a plain [`Stream`][].
4 //!
5 //! [`RangeStream`]: ../../stream/trait.RangeStream.html
6 //! [`Stream`]: ../../stream/trait.Stream.html
7 
8 use crate::{
9     error::{
10         self, ParseError,
11         ParseResult::{self, *},
12         ResultExt, StreamError, Tracked,
13     },
14     lib::{convert::TryFrom, marker::PhantomData},
15     parser::ParseMode,
16 };
17 
18 #[cfg(feature = "std")]
19 use crate::lib::error::Error as StdError;
20 
21 #[cfg(not(feature = "std"))]
22 use crate::lib::fmt;
23 
24 use crate::stream::{
25     uncons_range, uncons_while, uncons_while1, wrap_stream_error, Range as StreamRange,
26     RangeStream, StreamErrorFor, StreamOnce,
27 };
28 
29 use crate::Parser;
30 
31 pub struct Range<Input>(Input::Range)
32 where
33     Input: RangeStream;
34 
35 impl<Input> Parser<Input> for Range<Input>
36 where
37     Input: RangeStream,
38     Input::Range: PartialEq + crate::stream::Range,
39 {
40     type Output = Input::Range;
41     type PartialState = ();
42 
43     #[inline]
parse_lazy( &mut self, input: &mut Input, ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>44     fn parse_lazy(
45         &mut self,
46         input: &mut Input,
47     ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> {
48         use crate::stream::Range;
49 
50         let position = input.position();
51         match input.uncons_range(self.0.len()) {
52             Ok(other) => {
53                 if other == self.0 {
54                     CommitOk(other)
55                 } else {
56                     PeekErr(Input::Error::empty(position).into())
57                 }
58             }
59             Err(err) => wrap_stream_error(input, err),
60         }
61     }
add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>)62     fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
63         // TODO Add unexpected message?
64         errors.error.add_expected(error::Range(self.0.clone()));
65     }
66 }
67 
68 parser! {
69     #[derive(Clone)]
70     pub struct Recognize;
71     type PartialState = <RecognizeWithValue<P> as Parser<Input>>::PartialState;
72     /// Zero-copy parser which returns committed input range.
73     ///
74     /// [`combinator::recognize`][] is a non-`RangeStream` alternative.
75     ///
76     /// [`combinator::recognize`]: ../../parser/combinator/fn.recognize.html
77     /// ```
78     /// # extern crate combine;
79     /// # use combine::parser::range::recognize;
80     /// # use combine::parser::char::letter;
81     /// # use combine::*;
82     /// # fn main() {
83     /// let mut parser = recognize(skip_many1(letter()));
84     /// assert_eq!(parser.parse("hello world"), Ok(("hello", " world")));
85     /// assert!(parser.parse("!").is_err());
86     /// # }
87     /// ```
88     pub fn recognize[Input, P](parser: P)(Input) -> <Input as StreamOnce>::Range
89     where [
90         P: Parser<Input>,
91         Input: RangeStream,
92         <Input as StreamOnce>::Range: crate::stream::Range,
93     ]
94     {
95         recognize_with_value(parser).map(|(range, _)| range)
96     }
97 }
98 
99 #[inline]
parse_partial_range<M, F, G, S, Input>( mode: M, input: &mut Input, distance_state: &mut usize, state: S, first: F, resume: G, ) -> ParseResult<Input::Range, Input::Error> where M: ParseMode, F: FnOnce(&mut Input, S) -> ParseResult<Input::Range, <Input as StreamOnce>::Error>, G: FnOnce(&mut Input, S) -> ParseResult<Input::Range, <Input as StreamOnce>::Error>, Input: RangeStream,100 fn parse_partial_range<M, F, G, S, Input>(
101     mode: M,
102     input: &mut Input,
103     distance_state: &mut usize,
104     state: S,
105     first: F,
106     resume: G,
107 ) -> ParseResult<Input::Range, Input::Error>
108 where
109     M: ParseMode,
110     F: FnOnce(&mut Input, S) -> ParseResult<Input::Range, <Input as StreamOnce>::Error>,
111     G: FnOnce(&mut Input, S) -> ParseResult<Input::Range, <Input as StreamOnce>::Error>,
112     Input: RangeStream,
113 {
114     let before = input.checkpoint();
115 
116     if !input.is_partial() {
117         first(input, state)
118     } else if mode.is_first() || *distance_state == 0 {
119         let result = first(input, state);
120         if let CommitErr(_) = result {
121             *distance_state = input.distance(&before);
122             ctry!(input.reset(before).committed());
123         }
124         result
125     } else {
126         if input.uncons_range(*distance_state).is_err() {
127             panic!("recognize errored when restoring the input stream to its expected state");
128         }
129 
130         match resume(input, state) {
131             CommitOk(_) | PeekOk(_) => (),
132             PeekErr(err) => return PeekErr(err),
133             CommitErr(err) => {
134                 *distance_state = input.distance(&before);
135                 ctry!(input.reset(before).committed());
136                 return CommitErr(err);
137             }
138         }
139 
140         let distance = input.distance(&before);
141         ctry!(input.reset(before).committed());
142         take(distance).parse_lazy(input).map(|range| {
143             *distance_state = 0;
144             range
145         })
146     }
147 }
148 
149 #[derive(Clone)]
150 pub struct RecognizeWithValue<P>(P);
151 
152 impl<Input, P> Parser<Input> for RecognizeWithValue<P>
153 where
154     P: Parser<Input>,
155     Input: RangeStream,
156     <Input as StreamOnce>::Range: crate::stream::Range,
157 {
158     type Output = (<Input as StreamOnce>::Range, P::Output);
159     type PartialState = (usize, P::PartialState);
160 
161     parse_mode!(Input);
162     #[inline]
parse_mode<M>( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> where M: ParseMode,163     fn parse_mode<M>(
164         &mut self,
165         mode: M,
166         input: &mut Input,
167         state: &mut Self::PartialState,
168     ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
169     where
170         M: ParseMode,
171     {
172         let (ref mut distance_state, ref mut child_state) = *state;
173 
174         let before = input.checkpoint();
175         if !mode.is_first() && input.uncons_range(*distance_state).is_err() {
176             panic!("recognize errored when restoring the input stream to its expected state");
177         }
178 
179         let value = match self.0.parse_mode(mode, input, child_state) {
180             CommitOk(x) | PeekOk(x) => x,
181             PeekErr(err) => return PeekErr(err),
182             CommitErr(err) => {
183                 *distance_state = input.distance(&before);
184                 ctry!(input.reset(before).committed());
185                 return CommitErr(err);
186             }
187         };
188 
189         let distance = input.distance(&before);
190         ctry!(input.reset(before).committed());
191         take(distance).parse_lazy(input).map(|range| {
192             *distance_state = 0;
193             (range, value)
194         })
195     }
add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>)196     fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
197         self.0.add_error(errors)
198     }
199 }
200 
201 /// Zero-copy parser which returns a pair: (committed input range, parsed value).
202 ///
203 ///
204 /// [`combinator::recognize_with_value`] is a non-`RangeStream` alternative.
205 ///
206 /// [`combinator::recognize_with_value`]: recognize_with_value
207 /// ```
208 /// # extern crate combine;
209 /// # use combine::parser::range::recognize_with_value;
210 /// # use combine::parser::char::{digit, char};
211 /// # use combine::*;
212 /// # fn main() {
213 /// let mut parser = recognize_with_value((
214 ///     skip_many1(digit()),
215 ///     optional((attempt(char('.')), skip_many1(digit()))),
216 /// ).map(|(_, opt)| opt.is_some()));
217 ///
218 /// assert_eq!(parser.parse("1234!"), Ok((("1234", false), "!")));
219 /// assert_eq!(parser.parse("1234.0001!"), Ok((("1234.0001", true), "!")));
220 /// assert!(parser.parse("!").is_err());
221 /// assert!(parser.parse("1234.").is_err());
222 /// # }
223 /// ```
recognize_with_value<Input, P>(parser: P) -> RecognizeWithValue<P> where P: Parser<Input>, Input: RangeStream, <Input as StreamOnce>::Range: crate::stream::Range,224 pub fn recognize_with_value<Input, P>(parser: P) -> RecognizeWithValue<P>
225 where
226     P: Parser<Input>,
227     Input: RangeStream,
228     <Input as StreamOnce>::Range: crate::stream::Range,
229 {
230     RecognizeWithValue(parser)
231 }
232 
233 /// Zero-copy parser which reads a range of length `i.len()` and succeeds if `i` is equal to that
234 /// range.
235 ///
236 /// [`tokens`] is a non-`RangeStream` alternative.
237 ///
238 /// [`tokens`]: super::token::tokens
239 /// ```
240 /// # extern crate combine;
241 /// # use combine::parser::range::range;
242 /// # use combine::*;
243 /// # fn main() {
244 /// let mut parser = range("hello");
245 /// let result = parser.parse("hello world");
246 /// assert_eq!(result, Ok(("hello", " world")));
247 /// let result = parser.parse("hel world");
248 /// assert!(result.is_err());
249 /// # }
250 /// ```
range<Input>(i: Input::Range) -> Range<Input> where Input: RangeStream, Input::Range: PartialEq,251 pub fn range<Input>(i: Input::Range) -> Range<Input>
252 where
253     Input: RangeStream,
254     Input::Range: PartialEq,
255 {
256     Range(i)
257 }
258 
259 pub struct Take<Input>(usize, PhantomData<fn(Input)>);
260 impl<Input> Parser<Input> for Take<Input>
261 where
262     Input: RangeStream,
263 {
264     type Output = Input::Range;
265     type PartialState = ();
266 
267     #[inline]
parse_lazy( &mut self, input: &mut Input, ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>268     fn parse_lazy(
269         &mut self,
270         input: &mut Input,
271     ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> {
272         uncons_range(input, self.0)
273     }
274 }
275 
276 /// Zero-copy parser which reads a range of length `n`.
277 ///
278 /// [`count_min_max`][] is a non-`RangeStream` alternative.
279 ///
280 /// [`count_min_max`]: ../../parser/repeat/fn.count_min_max.html
281 /// ```
282 /// # extern crate combine;
283 /// # use combine::parser::range::take;
284 /// # use combine::*;
285 /// # fn main() {
286 /// let mut parser = take(1);
287 /// let result = parser.parse("1");
288 /// assert_eq!(result, Ok(("1", "")));
289 /// let mut parser = take(4);
290 /// let result = parser.parse("123abc");
291 /// assert_eq!(result, Ok(("123a", "bc")));
292 /// let result = parser.parse("abc");
293 /// assert!(result.is_err());
294 /// # }
295 /// ```
take<Input>(n: usize) -> Take<Input> where Input: RangeStream,296 pub fn take<Input>(n: usize) -> Take<Input>
297 where
298     Input: RangeStream,
299 {
300     Take(n, PhantomData)
301 }
302 
303 pub struct TakeWhile<Input, F>(F, PhantomData<fn(Input) -> Input>);
304 impl<Input, F> Parser<Input> for TakeWhile<Input, F>
305 where
306     Input: RangeStream,
307     Input::Range: crate::stream::Range,
308     F: FnMut(Input::Token) -> bool,
309 {
310     type Output = Input::Range;
311     type PartialState = usize;
312 
313     parse_mode!(Input);
314     #[inline]
parse_mode_impl<M>( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> where M: ParseMode,315     fn parse_mode_impl<M>(
316         &mut self,
317         mode: M,
318         input: &mut Input,
319         state: &mut Self::PartialState,
320     ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
321     where
322         M: ParseMode,
323     {
324         parse_partial_range(
325             mode,
326             input,
327             state,
328             &mut self.0,
329             |input, predicate| uncons_while(input, predicate),
330             |input, predicate| uncons_while(input, predicate),
331         )
332     }
333 }
334 
335 /// Zero-copy parser which reads a range of 0 or more tokens which satisfy `f`.
336 ///
337 /// [`many`][] is a non-`RangeStream` alternative.
338 ///
339 /// [`many`]: ../../parser/repeat/fn.many.html
340 /// ```
341 /// # extern crate combine;
342 /// # use combine::parser::range::take_while;
343 /// # use combine::*;
344 /// # fn main() {
345 /// let mut parser = take_while(|c: char| c.is_digit(10));
346 /// let result = parser.parse("123abc");
347 /// assert_eq!(result, Ok(("123", "abc")));
348 /// let result = parser.parse("abc");
349 /// assert_eq!(result, Ok(("", "abc")));
350 /// # }
351 /// ```
take_while<Input, F>(f: F) -> TakeWhile<Input, F> where Input: RangeStream, Input::Range: crate::stream::Range, F: FnMut(Input::Token) -> bool,352 pub fn take_while<Input, F>(f: F) -> TakeWhile<Input, F>
353 where
354     Input: RangeStream,
355     Input::Range: crate::stream::Range,
356     F: FnMut(Input::Token) -> bool,
357 {
358     TakeWhile(f, PhantomData)
359 }
360 
361 pub struct TakeWhile1<Input, F>(F, PhantomData<fn(Input) -> Input>);
362 impl<Input, F> Parser<Input> for TakeWhile1<Input, F>
363 where
364     Input: RangeStream,
365     Input::Range: crate::stream::Range,
366     F: FnMut(Input::Token) -> bool,
367 {
368     type Output = Input::Range;
369     type PartialState = usize;
370 
371     parse_mode!(Input);
372     #[inline]
parse_mode_impl<M>( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> where M: ParseMode,373     fn parse_mode_impl<M>(
374         &mut self,
375         mode: M,
376         input: &mut Input,
377         state: &mut Self::PartialState,
378     ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
379     where
380         M: ParseMode,
381     {
382         parse_partial_range(
383             mode,
384             input,
385             state,
386             &mut self.0,
387             |input, predicate| uncons_while1(input, predicate),
388             |input, predicate| uncons_while(input, predicate),
389         )
390     }
391 }
392 
393 /// Zero-copy parser which reads a range of 1 or more tokens which satisfy `f`.
394 ///
395 /// [`many1`][] is a non-`RangeStream` alternative.
396 ///
397 /// [`many1`]: ../../parser/repeat/fn.many1.html
398 /// ```
399 /// # extern crate combine;
400 /// # use combine::parser::range::take_while1;
401 /// # use combine::*;
402 /// # fn main() {
403 /// let mut parser = take_while1(|c: char| c.is_digit(10));
404 /// let result = parser.parse("123abc");
405 /// assert_eq!(result, Ok(("123", "abc")));
406 /// let result = parser.parse("abc");
407 /// assert!(result.is_err());
408 /// # }
409 /// ```
take_while1<Input, F>(f: F) -> TakeWhile1<Input, F> where Input: RangeStream, Input::Range: crate::stream::Range, F: FnMut(Input::Token) -> bool,410 pub fn take_while1<Input, F>(f: F) -> TakeWhile1<Input, F>
411 where
412     Input: RangeStream,
413     Input::Range: crate::stream::Range,
414     F: FnMut(Input::Token) -> bool,
415 {
416     TakeWhile1(f, PhantomData)
417 }
418 
419 pub struct TakeUntilRange<Input>(Input::Range)
420 where
421     Input: RangeStream;
422 impl<Input> Parser<Input> for TakeUntilRange<Input>
423 where
424     Input: RangeStream,
425     Input::Range: PartialEq + crate::stream::Range,
426 {
427     type Output = Input::Range;
428     type PartialState = usize;
429 
430     #[inline]
parse_partial( &mut self, input: &mut Input, to_consume: &mut Self::PartialState, ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>431     fn parse_partial(
432         &mut self,
433         input: &mut Input,
434         to_consume: &mut Self::PartialState,
435     ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> {
436         use crate::stream::Range;
437 
438         let len = self.0.len();
439         let before = input.checkpoint();
440         let mut first_stream_error = None;
441 
442         // Skip until the end of the last parse attempt
443         ctry!(uncons_range(input, *to_consume));
444 
445         loop {
446             let look_ahead_input = input.checkpoint();
447 
448             match input.uncons_range(len) {
449                 Ok(xs) => {
450                     if xs == self.0 {
451                         let distance = input.distance(&before) - len;
452                         ctry!(input.reset(before).committed());
453 
454                         if let Ok(committed) = input.uncons_range(distance) {
455                             if distance == 0 {
456                                 return PeekOk(committed);
457                             } else {
458                                 *to_consume = 0;
459                                 return CommitOk(committed);
460                             }
461                         }
462 
463                         // We are guaranteed able to uncons to_consume characters here
464                         // because we've already done it on look_ahead_input.
465                         unreachable!();
466                     } else {
467                         // Reset the stream back to where it was when we entered the top of the loop
468                         ctry!(input.reset(look_ahead_input).committed());
469 
470                         // Advance the stream by one token
471                         if input.uncons().is_err() {
472                             unreachable!();
473                         }
474                     }
475                 }
476                 Err(first_error) => {
477                     // If we are unable to find a successful parse even after advancing with `uncons`
478                     // below we must reset the stream to its state before the first error.
479                     // If we don't we may try and match the range `::` against `:<EOF>` which would
480                     // fail as only one `:` is present at this parse attempt. But when we later resume
481                     // with more input we must start parsing again at the first time we errored so we
482                     // can see the entire `::`
483                     if first_stream_error.is_none() {
484                         first_stream_error = Some((first_error, input.distance(&before)));
485                     }
486 
487                     // Reset the stream back to where it was when we entered the top of the loop
488                     ctry!(input.reset(look_ahead_input).committed());
489 
490                     // See if we can advance anyway
491                     if input.uncons().is_err() {
492                         let (first_error, first_error_distance) = first_stream_error.unwrap();
493 
494                         // Reset the stream
495                         ctry!(input.reset(before).committed());
496                         *to_consume = first_error_distance;
497 
498                         // Return the original error if uncons failed
499                         return wrap_stream_error(input, first_error);
500                     }
501                 }
502             };
503         }
504     }
505 }
506 
507 /// Zero-copy parser which reads a range of 0 or more tokens until `r` is found.
508 ///
509 /// The range `r` will not be committed. If `r` is not found, the parser will
510 /// return an error.
511 ///
512 /// [`repeat::take_until`][] is a non-`RangeStream` alternative.
513 ///
514 /// [`repeat::take_until`]: ../../parser/repeat/fn.take_until.html
515 /// ```
516 /// # extern crate combine;
517 /// # use combine::parser::range::{range, take_until_range};
518 /// # use combine::*;
519 /// # fn main() {
520 /// let mut parser = take_until_range("\r\n");
521 /// let result = parser.parse("To: [email protected]\r\n");
522 /// assert_eq!(result, Ok(("To: [email protected]", "\r\n")));
523 /// let result = parser.parse("Hello, world\n");
524 /// assert!(result.is_err());
525 /// # }
526 /// ```
take_until_range<Input>(r: Input::Range) -> TakeUntilRange<Input> where Input: RangeStream,527 pub fn take_until_range<Input>(r: Input::Range) -> TakeUntilRange<Input>
528 where
529     Input: RangeStream,
530 {
531     TakeUntilRange(r)
532 }
533 
534 #[derive(Debug, PartialEq)]
535 pub enum TakeRange {
536     /// Found the pattern at this offset
537     Found(usize),
538     /// Did not find the pattern but the parser can skip ahead to this offset.
539     NotFound(usize),
540 }
541 
542 impl From<Option<usize>> for TakeRange {
from(opt: Option<usize>) -> TakeRange543     fn from(opt: Option<usize>) -> TakeRange {
544         match opt {
545             Some(i) => TakeRange::Found(i),
546             None => TakeRange::NotFound(0),
547         }
548     }
549 }
550 
551 pub struct TakeFn<F, Input> {
552     searcher: F,
553     _marker: PhantomData<fn(Input)>,
554 }
555 
556 impl<Input, F, R> Parser<Input> for TakeFn<F, Input>
557 where
558     F: FnMut(Input::Range) -> R,
559     R: Into<TakeRange>,
560     Input: RangeStream,
561     Input::Range: crate::stream::Range,
562 {
563     type Output = Input::Range;
564     type PartialState = usize;
565 
566     parse_mode!(Input);
567     #[inline]
parse_mode<M>( &mut self, mode: M, input: &mut Input, offset: &mut Self::PartialState, ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> where M: ParseMode,568     fn parse_mode<M>(
569         &mut self,
570         mode: M,
571         input: &mut Input,
572         offset: &mut Self::PartialState,
573     ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
574     where
575         M: ParseMode,
576     {
577         let checkpoint = input.checkpoint();
578 
579         if mode.is_first() {
580             *offset = 0;
581         } else {
582             let _ = input.uncons_range(*offset);
583         }
584 
585         match (self.searcher)(input.range()).into() {
586             TakeRange::Found(i) => {
587                 ctry!(input.reset(checkpoint).committed());
588                 let result = uncons_range(input, *offset + i);
589                 if result.is_ok() {
590                     *offset = 0;
591                 }
592                 result
593             }
594             TakeRange::NotFound(next_offset) => {
595                 *offset = next_offset;
596 
597                 let range = input.range();
598                 let _ = input.uncons_range(range.len());
599                 let position = input.position();
600                 ctry!(input.reset(checkpoint).committed());
601 
602                 let err = Input::Error::from_error(position, StreamError::end_of_input());
603                 if !input.is_partial() && range.is_empty() {
604                     PeekErr(err.into())
605                 } else {
606                     CommitErr(err)
607                 }
608             }
609         }
610     }
611 }
612 
613 /// Searches the entire range using `searcher` and then consumes a range of `Some(n)`.
614 /// If `f` can not find anything in the range it must return `None/NotFound` which indicates an end of input error.
615 ///
616 /// If partial parsing is used the `TakeRange` enum can be returned instead of `Option`. By
617 /// returning `TakeRange::NotFound(n)` it indicates that the input can skip ahead until `n`
618 /// when parsing is next resumed.
619 ///
620 /// See [`take_until_bytes`](../byte/fn.take_until_bytes.html) for a usecase.
take_fn<F, R, Input>(searcher: F) -> TakeFn<F, Input> where F: FnMut(Input::Range) -> R, R: Into<TakeRange>, Input: RangeStream, Input::Range: crate::stream::Range,621 pub fn take_fn<F, R, Input>(searcher: F) -> TakeFn<F, Input>
622 where
623     F: FnMut(Input::Range) -> R,
624     R: Into<TakeRange>,
625     Input: RangeStream,
626     Input::Range: crate::stream::Range,
627 {
628     TakeFn {
629         searcher,
630         _marker: PhantomData,
631     }
632 }
633 
634 #[cfg(feature = "std")]
635 parser! {
636 /// Takes a parser which parses a `length` then extracts a range of that length and returns it.
637 /// Commonly used in binary formats
638 ///
639 /// ```
640 /// # use combine::parser::{byte::num::be_u16, range::length_prefix};
641 /// # use combine::*;
642 /// # fn main() {
643 /// let mut input = Vec::new();
644 /// input.extend_from_slice(&3u16.to_be_bytes());
645 /// input.extend_from_slice(b"1234");
646 ///
647 /// let mut parser = length_prefix(be_u16());
648 /// let result = parser.parse(&input[..]);
649 /// assert_eq!(result, Ok((&b"123"[..], &b"4"[..])));
650 /// # }
651 /// ```
652 pub fn length_prefix[Input, P](len: P)(Input) -> Input::Range
653 where [
654     Input: RangeStream,
655     P: Parser<Input>,
656     usize: TryFrom<P::Output>,
657     <usize as TryFrom<P::Output>>::Error: StdError + Send + Sync + 'static,
658 ]
659 {
660     len
661         .and_then(|u| {
662             usize::try_from(u)
663                 .map_err(StreamErrorFor::<Input>::other)
664         })
665         .then_partial(|&mut len| take(len))
666 }
667 }
668 
669 #[cfg(not(feature = "std"))]
670 parser! {
671 /// Takes a parser which parses a `length` then extracts a range of that length and returns it.
672 /// Commonly used in binary formats
673 ///
674 /// ```
675 /// # use combine::parser::{byte::num::be_u16, range::length_prefix};
676 /// # use combine::*;
677 /// # fn main() {
678 /// let mut input = Vec::new();
679 /// input.extend_from_slice(&3u16.to_be_bytes());
680 /// input.extend_from_slice(b"1234");
681 ///
682 /// let mut parser = length_prefix(be_u16());
683 /// let result = parser.parse(&input[..]);
684 /// assert_eq!(result, Ok((&b"123"[..], &b"4"[..])));
685 /// # }
686 /// ```
687 pub fn length_prefix[Input, P](len: P)(Input) -> Input::Range
688 where [
689     Input: RangeStream,
690     P: Parser<Input>,
691     usize: TryFrom<P::Output>,
692     <usize as TryFrom<P::Output>>::Error: fmt::Display + Send + Sync + 'static,
693 ]
694 {
695     len
696         .and_then(|u| {
697             usize::try_from(u)
698                 .map_err(StreamErrorFor::<Input>::message_format)
699         })
700         .then_partial(|&mut len| take(len))
701 }
702 }
703 
704 #[cfg(test)]
705 mod tests {
706 
707     use crate::Parser;
708 
709     use super::*;
710 
711     #[test]
take_while_test()712     fn take_while_test() {
713         let result = take_while(|c: char| c.is_digit(10)).parse("123abc");
714         assert_eq!(result, Ok(("123", "abc")));
715         let result = take_while(|c: char| c.is_digit(10)).parse("abc");
716         assert_eq!(result, Ok(("", "abc")));
717     }
718 
719     #[test]
take_while1_test()720     fn take_while1_test() {
721         let result = take_while1(|c: char| c.is_digit(10)).parse("123abc");
722         assert_eq!(result, Ok(("123", "abc")));
723         let result = take_while1(|c: char| c.is_digit(10)).parse("abc");
724         assert!(result.is_err());
725     }
726 
727     #[test]
range_string_no_char_boundary_error()728     fn range_string_no_char_boundary_error() {
729         let mut parser = range("hello");
730         let result = parser.parse("hell\u{00EE} world");
731         assert!(result.is_err());
732     }
733 
734     #[test]
take_until_range_1()735     fn take_until_range_1() {
736         let result = take_until_range("\"").parse("Foo baz bar quux\"");
737         assert_eq!(result, Ok(("Foo baz bar quux", "\"")));
738     }
739 
740     #[test]
take_until_range_2()741     fn take_until_range_2() {
742         let result = take_until_range("===").parse("if ((pointless_comparison == 3) === true) {");
743         assert_eq!(
744             result,
745             Ok(("if ((pointless_comparison == 3) ", "=== true) {"))
746         );
747     }
748 
749     #[test]
take_until_range_unicode_1()750     fn take_until_range_unicode_1() {
751         let result = take_until_range("��")
752             .parse("�� Ferris the friendly rustacean �� and his snake friend ��");
753         assert_eq!(
754             result,
755             Ok((
756                 "�� Ferris the friendly rustacean ",
757                 "�� and his snake friend ��"
758             ))
759         );
760     }
761 
762     #[test]
take_until_range_unicode_2()763     fn take_until_range_unicode_2() {
764         let result = take_until_range("⁘⁙/⁘").parse("⚙️��️��=��️⁘⁙⁘⁘⁙/⁘⁘⁙/⁘");
765         assert_eq!(result, Ok(("⚙️��️��=��️⁘⁙⁘", "⁘⁙/⁘⁘⁙/⁘")));
766     }
767 }
768