1use 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")]
19use crate::lib::error::Error as StdError;
20
21#[cfg(not(feature = "std"))]
22use crate::lib::fmt;
23
24use crate::stream::{
25 uncons_range, uncons_while, uncons_while1, wrap_stream_error, Range as StreamRange,
26 RangeStream, StreamErrorFor, StreamOnce,
27};
28
29use crate::Parser;
30
31pub struct Range<Input>(Input::Range)
32where
33 Input: RangeStream;
34
35impl<Input> Parser<Input> for Range<Input>
36where
37 Input: RangeStream,
38 Input::Range: PartialEq + crate::stream::Range,
39{
40 type Output = Input::Range;
41 type PartialState = ();
42
43 #[inline]
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 }
62 fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
63 errors.error.add_expected(error::Range(self.0.clone()));
65 }
66}
67
68parser! {
69 #[derive(Clone)]
70 pub struct Recognize;
71 type PartialState = <RecognizeWithValue<P> as Parser<Input>>::PartialState;
72 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]
100fn 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>
108where
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)]
150pub struct RecognizeWithValue<P>(P);
151
152impl<Input, P> Parser<Input> for RecognizeWithValue<P>
153where
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]
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 }
196 fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
197 self.0.add_error(errors)
198 }
199}
200
201pub fn recognize_with_value<Input, P>(parser: P) -> RecognizeWithValue<P>
225where
226 P: Parser<Input>,
227 Input: RangeStream,
228 <Input as StreamOnce>::Range: crate::stream::Range,
229{
230 RecognizeWithValue(parser)
231}
232
233pub fn range<Input>(i: Input::Range) -> Range<Input>
252where
253 Input: RangeStream,
254 Input::Range: PartialEq,
255{
256 Range(i)
257}
258
259pub struct Take<Input>(usize, PhantomData<fn(Input)>);
260impl<Input> Parser<Input> for Take<Input>
261where
262 Input: RangeStream,
263{
264 type Output = Input::Range;
265 type PartialState = ();
266
267 #[inline]
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
276pub fn take<Input>(n: usize) -> Take<Input>
297where
298 Input: RangeStream,
299{
300 Take(n, PhantomData)
301}
302
303pub struct TakeWhile<Input, F>(F, PhantomData<fn(Input) -> Input>);
304impl<Input, F> Parser<Input> for TakeWhile<Input, F>
305where
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]
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
335pub fn take_while<Input, F>(f: F) -> TakeWhile<Input, F>
353where
354 Input: RangeStream,
355 Input::Range: crate::stream::Range,
356 F: FnMut(Input::Token) -> bool,
357{
358 TakeWhile(f, PhantomData)
359}
360
361pub struct TakeWhile1<Input, F>(F, PhantomData<fn(Input) -> Input>);
362impl<Input, F> Parser<Input> for TakeWhile1<Input, F>
363where
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]
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
393pub fn take_while1<Input, F>(f: F) -> TakeWhile1<Input, F>
411where
412 Input: RangeStream,
413 Input::Range: crate::stream::Range,
414 F: FnMut(Input::Token) -> bool,
415{
416 TakeWhile1(f, PhantomData)
417}
418
419pub struct TakeUntilRange<Input>(Input::Range)
420where
421 Input: RangeStream;
422impl<Input> Parser<Input> for TakeUntilRange<Input>
423where
424 Input: RangeStream,
425 Input::Range: PartialEq + crate::stream::Range,
426{
427 type Output = Input::Range;
428 type PartialState = usize;
429
430 #[inline]
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 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 unreachable!();
466 } else {
467 ctry!(input.reset(look_ahead_input).committed());
469
470 if input.uncons().is_err() {
472 unreachable!();
473 }
474 }
475 }
476 Err(first_error) => {
477 if first_stream_error.is_none() {
484 first_stream_error = Some((first_error, input.distance(&before)));
485 }
486
487 ctry!(input.reset(look_ahead_input).committed());
489
490 if input.uncons().is_err() {
492 let (first_error, first_error_distance) = first_stream_error.unwrap();
493
494 ctry!(input.reset(before).committed());
496 *to_consume = first_error_distance;
497
498 return wrap_stream_error(input, first_error);
500 }
501 }
502 };
503 }
504 }
505}
506
507pub fn take_until_range<Input>(r: Input::Range) -> TakeUntilRange<Input>
528where
529 Input: RangeStream,
530{
531 TakeUntilRange(r)
532}
533
534#[derive(Debug, PartialEq)]
535pub enum TakeRange {
536 Found(usize),
538 NotFound(usize),
540}
541
542impl From<Option<usize>> for TakeRange {
543 fn from(opt: Option<usize>) -> TakeRange {
544 match opt {
545 Some(i) => TakeRange::Found(i),
546 None => TakeRange::NotFound(0),
547 }
548 }
549}
550
551pub struct TakeFn<F, Input> {
552 searcher: F,
553 _marker: PhantomData<fn(Input)>,
554}
555
556impl<Input, F, R> Parser<Input> for TakeFn<F, Input>
557where
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]
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
613pub fn take_fn<F, R, Input>(searcher: F) -> TakeFn<F, Input>
622where
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")]
635parser! {
636pub fn length_prefix[Input, P](len: P)(Input) -> Input::Range
653where [
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"))]
670parser! {
671pub fn length_prefix[Input, P](len: P)(Input) -> Input::Range
688where [
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)]
705mod tests {
706
707 use crate::Parser;
708
709 use super::*;
710
711 #[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]
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]
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]
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]
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]
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]
763 fn take_until_range_unicode_2() {
764 let result = take_until_range("⁘⁙/⁘").parse("⚙️🛠️🦀=🏎️⁘⁙⁘⁘⁙/⁘⁘⁙/⁘");
765 assert_eq!(result, Ok(("⚙️🛠️🦀=🏎️⁘⁙⁘", "⁘⁙/⁘⁘⁙/⁘")));
766 }
767}