winnow/token/mod.rs
1//! Parsers extracting tokens from the stream
2
3#[cfg(all(test, feature = "ascii"))]
4mod tests;
5
6use crate::combinator::trace;
7use crate::combinator::DisplayDebug;
8use crate::error::Needed;
9use crate::error::ParserError;
10use crate::stream::Range;
11use crate::stream::{Compare, CompareResult, ContainsToken, FindSlice, Stream};
12use crate::stream::{StreamIsPartial, ToUsize};
13use crate::Parser;
14use crate::Result;
15use core::result::Result::Ok;
16
17/// Matches one token
18///
19/// *Complete version*: Will return an error if there's not enough input data.
20///
21/// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
22///
23/// # Effective Signature
24///
25/// Assuming you are parsing a `&str` [Stream]:
26/// ```rust
27/// # use winnow::prelude::*;;
28/// pub fn any(input: &mut &str) -> ModalResult<char>
29/// # {
30/// # winnow::token::any.parse_next(input)
31/// # }
32/// ```
33///
34/// # Example
35///
36/// ```rust
37/// # use winnow::{token::any, error::ErrMode, error::ContextError};
38/// # use winnow::prelude::*;
39/// fn parser(input: &mut &str) -> ModalResult<char> {
40/// any.parse_next(input)
41/// }
42///
43/// assert_eq!(parser.parse_peek("abc"), Ok(("bc",'a')));
44/// assert!(parser.parse_peek("").is_err());
45/// ```
46///
47/// ```rust
48/// # use winnow::{token::any, error::ErrMode, error::ContextError, error::Needed};
49/// # use winnow::prelude::*;
50/// # use winnow::Partial;
51/// assert_eq!(any::<_, ErrMode<ContextError>>.parse_peek(Partial::new("abc")), Ok((Partial::new("bc"),'a')));
52/// assert_eq!(any::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
53/// ```
54#[inline(always)]
55#[doc(alias = "token")]
56pub fn any<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Token, Error>
57where
58 Input: StreamIsPartial + Stream,
59 Error: ParserError<Input>,
60{
61 trace("any", move |input: &mut Input| {
62 if <Input as StreamIsPartial>::is_partial_supported() {
63 any_::<_, _, true>(input)
64 } else {
65 any_::<_, _, false>(input)
66 }
67 })
68 .parse_next(input)
69}
70
71fn any_<I, E: ParserError<I>, const PARTIAL: bool>(input: &mut I) -> Result<<I as Stream>::Token, E>
72where
73 I: StreamIsPartial,
74 I: Stream,
75{
76 input.next_token().ok_or_else(|| {
77 if PARTIAL && input.is_partial() {
78 ParserError::incomplete(input, Needed::new(1))
79 } else {
80 ParserError::from_input(input)
81 }
82 })
83}
84
85/// Recognizes a literal
86///
87/// The input data will be compared to the literal combinator's argument and will return the part of
88/// the input that matches the argument
89///
90/// It will return `Err(ErrMode::Backtrack(_))` if the input doesn't match the literal
91///
92/// <div class="warning">
93///
94/// **Note:** [`Parser`] is implemented for strings and byte strings as a convenience (complete
95/// only)
96///
97/// </div>
98///
99/// # Effective Signature
100///
101/// Assuming you are parsing a `&str` [Stream]:
102/// ```rust
103/// # use winnow::prelude::*;;
104/// # use winnow::error::ContextError;
105/// pub fn literal(literal: &str) -> impl Parser<&str, &str, ContextError>
106/// # {
107/// # winnow::token::literal(literal)
108/// # }
109/// ```
110///
111/// # Example
112/// ```rust
113/// # use winnow::prelude::*;
114/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
115/// #
116/// fn parser<'i>(s: &mut &'i str) -> ModalResult<&'i str> {
117/// "Hello".parse_next(s)
118/// }
119///
120/// assert_eq!(parser.parse_peek("Hello, World!"), Ok((", World!", "Hello")));
121/// assert!(parser.parse_peek("Something").is_err());
122/// assert!(parser.parse_peek("").is_err());
123/// ```
124///
125/// ```rust
126/// # use winnow::prelude::*;
127/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
128/// # use winnow::Partial;
129///
130/// fn parser<'i>(s: &mut Partial<&'i str>) -> ModalResult<&'i str> {
131/// "Hello".parse_next(s)
132/// }
133///
134/// assert_eq!(parser.parse_peek(Partial::new("Hello, World!")), Ok((Partial::new(", World!"), "Hello")));
135/// assert!(parser.parse_peek(Partial::new("Something")).is_err());
136/// assert!(parser.parse_peek(Partial::new("S")).is_err());
137/// assert_eq!(parser.parse_peek(Partial::new("H")), Err(ErrMode::Incomplete(Needed::Unknown)));
138/// ```
139///
140/// ```rust
141/// # #[cfg(feature = "ascii")] {
142/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
143/// # use winnow::prelude::*;
144/// use winnow::token::literal;
145/// use winnow::ascii::Caseless;
146///
147/// fn parser<'i>(s: &mut &'i str) -> ModalResult<&'i str> {
148/// literal(Caseless("hello")).parse_next(s)
149/// }
150///
151/// assert_eq!(parser.parse_peek("Hello, World!"), Ok((", World!", "Hello")));
152/// assert_eq!(parser.parse_peek("hello, World!"), Ok((", World!", "hello")));
153/// assert_eq!(parser.parse_peek("HeLlO, World!"), Ok((", World!", "HeLlO")));
154/// assert!(parser.parse_peek("Something").is_err());
155/// assert!(parser.parse_peek("").is_err());
156/// # }
157/// ```
158#[inline(always)]
159#[doc(alias = "tag")]
160#[doc(alias = "bytes")]
161#[doc(alias = "just")]
162pub fn literal<Literal, Input, Error>(
163 literal: Literal,
164) -> impl Parser<Input, <Input as Stream>::Slice, Error>
165where
166 Input: StreamIsPartial + Stream + Compare<Literal>,
167 Literal: Clone + core::fmt::Debug,
168 Error: ParserError<Input>,
169{
170 trace(DisplayDebug(literal.clone()), move |i: &mut Input| {
171 let t = literal.clone();
172 if <Input as StreamIsPartial>::is_partial_supported() {
173 literal_::<_, _, _, true>(i, t)
174 } else {
175 literal_::<_, _, _, false>(i, t)
176 }
177 })
178}
179
180fn literal_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
181 i: &mut I,
182 t: T,
183) -> Result<<I as Stream>::Slice, Error>
184where
185 I: StreamIsPartial,
186 I: Stream + Compare<T>,
187 T: core::fmt::Debug,
188{
189 match i.compare(t) {
190 CompareResult::Ok(len) => Ok(i.next_slice(len)),
191 CompareResult::Incomplete if PARTIAL && i.is_partial() => {
192 Err(ParserError::incomplete(i, Needed::Unknown))
193 }
194 CompareResult::Incomplete | CompareResult::Error => Err(ParserError::from_input(i)),
195 }
196}
197
198/// Recognize a token that matches a [set of tokens][ContainsToken]
199///
200/// <div class="warning">
201///
202/// **Note:** [`Parser`] is implemented as a convenience (complete
203/// only) for
204/// - `u8`
205/// - `char`
206///
207/// </div>
208///
209/// *Complete version*: Will return an error if there's not enough input data.
210///
211/// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
212///
213/// # Effective Signature
214///
215/// Assuming you are parsing a `&str` [Stream]:
216/// ```rust
217/// # use winnow::prelude::*;;
218/// # use winnow::stream::ContainsToken;
219/// # use winnow::error::ContextError;
220/// pub fn one_of<'i>(set: impl ContainsToken<char>) -> impl Parser<&'i str, char, ContextError>
221/// # {
222/// # winnow::token::one_of(set)
223/// # }
224/// ```
225///
226/// # Example
227///
228/// ```rust
229/// # use winnow::prelude::*;
230/// # use winnow::{error::ErrMode, error::ContextError};
231/// # use winnow::token::one_of;
232/// assert_eq!(one_of::<_, _, ContextError>(['a', 'b', 'c']).parse_peek("b"), Ok(("", 'b')));
233/// assert!(one_of::<_, _, ContextError>('a').parse_peek("bc").is_err());
234/// assert!(one_of::<_, _, ContextError>('a').parse_peek("").is_err());
235///
236/// fn parser_fn(i: &mut &str) -> ModalResult<char> {
237/// one_of(|c| c == 'a' || c == 'b').parse_next(i)
238/// }
239/// assert_eq!(parser_fn.parse_peek("abc"), Ok(("bc", 'a')));
240/// assert!(parser_fn.parse_peek("cd").is_err());
241/// assert!(parser_fn.parse_peek("").is_err());
242/// ```
243///
244/// ```rust
245/// # use winnow::prelude::*;
246/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
247/// # use winnow::Partial;
248/// # use winnow::token::one_of;
249/// assert_eq!(one_of::<_, _, ErrMode<ContextError>>(['a', 'b', 'c']).parse_peek(Partial::new("b")), Ok((Partial::new(""), 'b')));
250/// assert!(one_of::<_, _, ErrMode<ContextError>>('a').parse_peek(Partial::new("bc")).is_err());
251/// assert_eq!(one_of::<_, _, ErrMode<ContextError>>('a').parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
252///
253/// fn parser_fn(i: &mut Partial<&str>) -> ModalResult<char> {
254/// one_of(|c| c == 'a' || c == 'b').parse_next(i)
255/// }
256/// assert_eq!(parser_fn.parse_peek(Partial::new("abc")), Ok((Partial::new("bc"), 'a')));
257/// assert!(parser_fn.parse_peek(Partial::new("cd")).is_err());
258/// assert_eq!(parser_fn.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
259/// ```
260#[inline(always)]
261#[doc(alias = "char")]
262#[doc(alias = "token")]
263#[doc(alias = "satisfy")]
264pub fn one_of<Input, Set, Error>(set: Set) -> impl Parser<Input, <Input as Stream>::Token, Error>
265where
266 Input: StreamIsPartial + Stream,
267 <Input as Stream>::Token: Clone,
268 Set: ContainsToken<<Input as Stream>::Token>,
269 Error: ParserError<Input>,
270{
271 trace(
272 "one_of",
273 any.verify(move |t: &<Input as Stream>::Token| set.contains_token(t.clone())),
274 )
275}
276
277/// Recognize a token that does not match a [set of tokens][ContainsToken]
278///
279/// *Complete version*: Will return an error if there's not enough input data.
280///
281/// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
282///
283/// # Effective Signature
284///
285/// Assuming you are parsing a `&str` [Stream]:
286/// ```rust
287/// # use winnow::prelude::*;;
288/// # use winnow::stream::ContainsToken;
289/// # use winnow::error::ContextError;
290/// pub fn none_of<'i>(set: impl ContainsToken<char>) -> impl Parser<&'i str, char, ContextError>
291/// # {
292/// # winnow::token::none_of(set)
293/// # }
294/// ```
295///
296/// # Example
297///
298/// ```rust
299/// # use winnow::{error::ErrMode, error::ContextError};
300/// # use winnow::prelude::*;
301/// # use winnow::token::none_of;
302/// assert_eq!(none_of::<_, _, ContextError>(['a', 'b', 'c']).parse_peek("z"), Ok(("", 'z')));
303/// assert!(none_of::<_, _, ContextError>(['a', 'b']).parse_peek("a").is_err());
304/// assert!(none_of::<_, _, ContextError>('a').parse_peek("").is_err());
305/// ```
306///
307/// ```rust
308/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
309/// # use winnow::prelude::*;
310/// # use winnow::Partial;
311/// # use winnow::token::none_of;
312/// assert_eq!(none_of::<_, _, ErrMode<ContextError>>(['a', 'b', 'c']).parse_peek(Partial::new("z")), Ok((Partial::new(""), 'z')));
313/// assert!(none_of::<_, _, ErrMode<ContextError>>(['a', 'b']).parse_peek(Partial::new("a")).is_err());
314/// assert_eq!(none_of::<_, _, ErrMode<ContextError>>('a').parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
315/// ```
316#[inline(always)]
317pub fn none_of<Input, Set, Error>(set: Set) -> impl Parser<Input, <Input as Stream>::Token, Error>
318where
319 Input: StreamIsPartial + Stream,
320 <Input as Stream>::Token: Clone,
321 Set: ContainsToken<<Input as Stream>::Token>,
322 Error: ParserError<Input>,
323{
324 trace(
325 "none_of",
326 any.verify(move |t: &<Input as Stream>::Token| !set.contains_token(t.clone())),
327 )
328}
329
330/// Recognize the longest (m <= len <= n) input slice that matches a [set of tokens][ContainsToken]
331///
332/// It will return an `ErrMode::Backtrack(_)` if the set of tokens wasn't met or is out
333/// of range (m <= len <= n).
334///
335/// *[Partial version][crate::_topic::partial]* will return a `ErrMode::Incomplete(Needed::new(1))` if a member of the set of tokens reaches the end of the input or is too short.
336///
337/// To take a series of tokens, use [`repeat`][crate::combinator::repeat] to [`Accumulate`][crate::stream::Accumulate] into a `()` and then [`Parser::take`].
338///
339/// # Effective Signature
340///
341/// Assuming you are parsing a `&str` [Stream] with `0..` or `1..` [ranges][Range]:
342/// ```rust
343/// # use std::ops::RangeFrom;
344/// # use winnow::prelude::*;
345/// # use winnow::stream::ContainsToken;
346/// # use winnow::error::ContextError;
347/// pub fn take_while<'i>(occurrences: RangeFrom<usize>, set: impl ContainsToken<char>) -> impl Parser<&'i str, &'i str, ContextError>
348/// # {
349/// # winnow::token::take_while(occurrences, set)
350/// # }
351/// ```
352///
353/// # Example
354///
355/// Zero or more tokens:
356/// ```rust
357/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
358/// # use winnow::prelude::*;
359/// use winnow::token::take_while;
360/// use winnow::stream::AsChar;
361///
362/// fn alpha<'i>(s: &mut &'i [u8]) -> ModalResult<&'i [u8]> {
363/// take_while(0.., AsChar::is_alpha).parse_next(s)
364/// }
365///
366/// assert_eq!(alpha.parse_peek(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
367/// assert_eq!(alpha.parse_peek(b"12345"), Ok((&b"12345"[..], &b""[..])));
368/// assert_eq!(alpha.parse_peek(b"latin"), Ok((&b""[..], &b"latin"[..])));
369/// assert_eq!(alpha.parse_peek(b""), Ok((&b""[..], &b""[..])));
370/// ```
371///
372/// ```rust
373/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
374/// # use winnow::prelude::*;
375/// # use winnow::Partial;
376/// use winnow::token::take_while;
377/// use winnow::stream::AsChar;
378///
379/// fn alpha<'i>(s: &mut Partial<&'i [u8]>) -> ModalResult<&'i [u8]> {
380/// take_while(0.., AsChar::is_alpha).parse_next(s)
381/// }
382///
383/// assert_eq!(alpha.parse_peek(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
384/// assert_eq!(alpha.parse_peek(Partial::new(b"12345")), Ok((Partial::new(&b"12345"[..]), &b""[..])));
385/// assert_eq!(alpha.parse_peek(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
386/// assert_eq!(alpha.parse_peek(Partial::new(b"")), Err(ErrMode::Incomplete(Needed::new(1))));
387/// ```
388///
389/// One or more tokens:
390/// ```rust
391/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
392/// # use winnow::prelude::*;
393/// use winnow::token::take_while;
394/// use winnow::stream::AsChar;
395///
396/// fn alpha<'i>(s: &mut &'i [u8]) -> ModalResult<&'i [u8]> {
397/// take_while(1.., AsChar::is_alpha).parse_next(s)
398/// }
399///
400/// assert_eq!(alpha.parse_peek(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
401/// assert_eq!(alpha.parse_peek(b"latin"), Ok((&b""[..], &b"latin"[..])));
402/// assert!(alpha.parse_peek(b"12345").is_err());
403///
404/// fn hex<'i>(s: &mut &'i str) -> ModalResult<&'i str> {
405/// take_while(1.., ('0'..='9', 'A'..='F')).parse_next(s)
406/// }
407///
408/// assert_eq!(hex.parse_peek("123 and voila"), Ok((" and voila", "123")));
409/// assert_eq!(hex.parse_peek("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
410/// assert_eq!(hex.parse_peek("BADBABEsomething"), Ok(("something", "BADBABE")));
411/// assert_eq!(hex.parse_peek("D15EA5E"), Ok(("", "D15EA5E")));
412/// assert!(hex.parse_peek("").is_err());
413/// ```
414///
415/// ```rust
416/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
417/// # use winnow::prelude::*;
418/// # use winnow::Partial;
419/// use winnow::token::take_while;
420/// use winnow::stream::AsChar;
421///
422/// fn alpha<'i>(s: &mut Partial<&'i [u8]>) -> ModalResult<&'i [u8]> {
423/// take_while(1.., AsChar::is_alpha).parse_next(s)
424/// }
425///
426/// assert_eq!(alpha.parse_peek(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
427/// assert_eq!(alpha.parse_peek(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
428/// assert!(alpha.parse_peek(Partial::new(b"12345")).is_err());
429///
430/// fn hex<'i>(s: &mut Partial<&'i str>) -> ModalResult<&'i str> {
431/// take_while(1.., ('0'..='9', 'A'..='F')).parse_next(s)
432/// }
433///
434/// assert_eq!(hex.parse_peek(Partial::new("123 and voila")), Ok((Partial::new(" and voila"), "123")));
435/// assert_eq!(hex.parse_peek(Partial::new("DEADBEEF and others")), Ok((Partial::new(" and others"), "DEADBEEF")));
436/// assert_eq!(hex.parse_peek(Partial::new("BADBABEsomething")), Ok((Partial::new("something"), "BADBABE")));
437/// assert_eq!(hex.parse_peek(Partial::new("D15EA5E")), Err(ErrMode::Incomplete(Needed::new(1))));
438/// assert_eq!(hex.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
439/// ```
440///
441/// Arbitrary amount of tokens:
442/// ```rust
443/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
444/// # use winnow::prelude::*;
445/// use winnow::token::take_while;
446/// use winnow::stream::AsChar;
447///
448/// fn short_alpha<'i>(s: &mut &'i [u8]) -> ModalResult<&'i [u8]> {
449/// take_while(3..=6, AsChar::is_alpha).parse_next(s)
450/// }
451///
452/// assert_eq!(short_alpha.parse_peek(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
453/// assert_eq!(short_alpha.parse_peek(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
454/// assert_eq!(short_alpha.parse_peek(b"latin"), Ok((&b""[..], &b"latin"[..])));
455/// assert!(short_alpha.parse_peek(b"ed").is_err());
456/// assert!(short_alpha.parse_peek(b"12345").is_err());
457/// ```
458///
459/// ```rust
460/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
461/// # use winnow::prelude::*;
462/// # use winnow::Partial;
463/// use winnow::token::take_while;
464/// use winnow::stream::AsChar;
465///
466/// fn short_alpha<'i>(s: &mut Partial<&'i [u8]>) -> ModalResult<&'i [u8]> {
467/// take_while(3..=6, AsChar::is_alpha).parse_next(s)
468/// }
469///
470/// assert_eq!(short_alpha.parse_peek(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
471/// assert_eq!(short_alpha.parse_peek(Partial::new(b"lengthy")), Ok((Partial::new(&b"y"[..]), &b"length"[..])));
472/// assert_eq!(short_alpha.parse_peek(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
473/// assert_eq!(short_alpha.parse_peek(Partial::new(b"ed")), Err(ErrMode::Incomplete(Needed::new(1))));
474/// assert!(short_alpha.parse_peek(Partial::new(b"12345")).is_err());
475/// ```
476#[inline(always)]
477#[doc(alias = "is_a")]
478#[doc(alias = "take_while0")]
479#[doc(alias = "take_while1")]
480pub fn take_while<Set, Input, Error>(
481 occurrences: impl Into<Range>,
482 set: Set,
483) -> impl Parser<Input, <Input as Stream>::Slice, Error>
484where
485 Input: StreamIsPartial + Stream,
486 Set: ContainsToken<<Input as Stream>::Token>,
487 Error: ParserError<Input>,
488{
489 let Range {
490 start_inclusive,
491 end_inclusive,
492 } = occurrences.into();
493 trace("take_while", move |i: &mut Input| {
494 match (start_inclusive, end_inclusive) {
495 (0, None) => {
496 if <Input as StreamIsPartial>::is_partial_supported() {
497 take_till0::<_, _, _, true>(i, |c| !set.contains_token(c))
498 } else {
499 take_till0::<_, _, _, false>(i, |c| !set.contains_token(c))
500 }
501 }
502 (1, None) => {
503 if <Input as StreamIsPartial>::is_partial_supported() {
504 take_till1::<_, _, _, true>(i, |c| !set.contains_token(c))
505 } else {
506 take_till1::<_, _, _, false>(i, |c| !set.contains_token(c))
507 }
508 }
509 (start, end) => {
510 let end = end.unwrap_or(usize::MAX);
511 if <Input as StreamIsPartial>::is_partial_supported() {
512 take_till_m_n::<_, _, _, true>(i, start, end, |c| !set.contains_token(c))
513 } else {
514 take_till_m_n::<_, _, _, false>(i, start, end, |c| !set.contains_token(c))
515 }
516 }
517 }
518 })
519}
520
521fn take_till0<P, I: StreamIsPartial + Stream, E: ParserError<I>, const PARTIAL: bool>(
522 input: &mut I,
523 predicate: P,
524) -> Result<<I as Stream>::Slice, E>
525where
526 P: Fn(I::Token) -> bool,
527{
528 let offset = match input.offset_for(predicate) {
529 Some(offset) => offset,
530 None if PARTIAL && input.is_partial() => {
531 return Err(ParserError::incomplete(input, Needed::new(1)));
532 }
533 None => input.eof_offset(),
534 };
535 Ok(input.next_slice(offset))
536}
537
538fn take_till1<P, I: StreamIsPartial + Stream, E: ParserError<I>, const PARTIAL: bool>(
539 input: &mut I,
540 predicate: P,
541) -> Result<<I as Stream>::Slice, E>
542where
543 P: Fn(I::Token) -> bool,
544{
545 let offset = match input.offset_for(predicate) {
546 Some(offset) => offset,
547 None if PARTIAL && input.is_partial() => {
548 return Err(ParserError::incomplete(input, Needed::new(1)));
549 }
550 None => input.eof_offset(),
551 };
552 if offset == 0 {
553 Err(ParserError::from_input(input))
554 } else {
555 Ok(input.next_slice(offset))
556 }
557}
558
559fn take_till_m_n<P, I, Error: ParserError<I>, const PARTIAL: bool>(
560 input: &mut I,
561 m: usize,
562 n: usize,
563 predicate: P,
564) -> Result<<I as Stream>::Slice, Error>
565where
566 I: StreamIsPartial,
567 I: Stream,
568 P: Fn(I::Token) -> bool,
569{
570 if n < m {
571 return Err(ParserError::assert(
572 input,
573 "`occurrences` should be ascending, rather than descending",
574 ));
575 }
576
577 let mut final_count = 0;
578 for (processed, (offset, token)) in input.iter_offsets().enumerate() {
579 if predicate(token) {
580 if processed < m {
581 return Err(ParserError::from_input(input));
582 } else {
583 return Ok(input.next_slice(offset));
584 }
585 } else {
586 if processed == n {
587 return Ok(input.next_slice(offset));
588 }
589 final_count = processed + 1;
590 }
591 }
592 if PARTIAL && input.is_partial() {
593 if final_count == n {
594 Ok(input.finish())
595 } else {
596 let needed = if m > input.eof_offset() {
597 m - input.eof_offset()
598 } else {
599 1
600 };
601 Err(ParserError::incomplete(input, Needed::new(needed)))
602 }
603 } else {
604 if m <= final_count {
605 Ok(input.finish())
606 } else {
607 Err(ParserError::from_input(input))
608 }
609 }
610}
611
612/// Recognize the longest input slice (if any) till a member of a [set of tokens][ContainsToken] is found.
613///
614/// It doesn't consume the terminating token from the set.
615///
616/// *[Partial version][crate::_topic::partial]* will return a `ErrMode::Incomplete(Needed::new(1))` if the match reaches the
617/// end of input or if there was not match.
618///
619/// See also
620/// - [`take_until`] for recognizing up-to a [`literal`] (w/ optional simd optimizations)
621/// - [`repeat_till`][crate::combinator::repeat_till] with [`Parser::take`] for taking tokens up to a [`Parser`]
622///
623/// # Effective Signature
624///
625/// Assuming you are parsing a `&str` [Stream] with `0..` or `1..` [ranges][Range]:
626/// ```rust
627/// # use std::ops::RangeFrom;
628/// # use winnow::prelude::*;
629/// # use winnow::stream::ContainsToken;
630/// # use winnow::error::ContextError;
631/// pub fn take_till<'i>(occurrences: RangeFrom<usize>, set: impl ContainsToken<char>) -> impl Parser<&'i str, &'i str, ContextError>
632/// # {
633/// # winnow::token::take_till(occurrences, set)
634/// # }
635/// ```
636///
637/// # Example
638///
639/// ```rust
640/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
641/// # use winnow::prelude::*;
642/// use winnow::token::take_till;
643///
644/// fn till_colon<'i>(s: &mut &'i str) -> ModalResult<&'i str> {
645/// take_till(0.., |c| c == ':').parse_next(s)
646/// }
647///
648/// assert_eq!(till_colon.parse_peek("latin:123"), Ok((":123", "latin")));
649/// assert_eq!(till_colon.parse_peek(":empty matched"), Ok((":empty matched", ""))); //allowed
650/// assert_eq!(till_colon.parse_peek("12345"), Ok(("", "12345")));
651/// assert_eq!(till_colon.parse_peek(""), Ok(("", "")));
652/// ```
653///
654/// ```rust
655/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
656/// # use winnow::prelude::*;
657/// # use winnow::Partial;
658/// use winnow::token::take_till;
659///
660/// fn till_colon<'i>(s: &mut Partial<&'i str>) -> ModalResult<&'i str> {
661/// take_till(0.., |c| c == ':').parse_next(s)
662/// }
663///
664/// assert_eq!(till_colon.parse_peek(Partial::new("latin:123")), Ok((Partial::new(":123"), "latin")));
665/// assert_eq!(till_colon.parse_peek(Partial::new(":empty matched")), Ok((Partial::new(":empty matched"), ""))); //allowed
666/// assert_eq!(till_colon.parse_peek(Partial::new("12345")), Err(ErrMode::Incomplete(Needed::new(1))));
667/// assert_eq!(till_colon.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
668/// ```
669#[inline(always)]
670#[doc(alias = "is_not")]
671pub fn take_till<Set, Input, Error>(
672 occurrences: impl Into<Range>,
673 set: Set,
674) -> impl Parser<Input, <Input as Stream>::Slice, Error>
675where
676 Input: StreamIsPartial + Stream,
677 Set: ContainsToken<<Input as Stream>::Token>,
678 Error: ParserError<Input>,
679{
680 let Range {
681 start_inclusive,
682 end_inclusive,
683 } = occurrences.into();
684 trace("take_till", move |i: &mut Input| {
685 match (start_inclusive, end_inclusive) {
686 (0, None) => {
687 if <Input as StreamIsPartial>::is_partial_supported() {
688 take_till0::<_, _, _, true>(i, |c| set.contains_token(c))
689 } else {
690 take_till0::<_, _, _, false>(i, |c| set.contains_token(c))
691 }
692 }
693 (1, None) => {
694 if <Input as StreamIsPartial>::is_partial_supported() {
695 take_till1::<_, _, _, true>(i, |c| set.contains_token(c))
696 } else {
697 take_till1::<_, _, _, false>(i, |c| set.contains_token(c))
698 }
699 }
700 (start, end) => {
701 let end = end.unwrap_or(usize::MAX);
702 if <Input as StreamIsPartial>::is_partial_supported() {
703 take_till_m_n::<_, _, _, true>(i, start, end, |c| set.contains_token(c))
704 } else {
705 take_till_m_n::<_, _, _, false>(i, start, end, |c| set.contains_token(c))
706 }
707 }
708 }
709 })
710}
711
712/// Recognize an input slice containing the first N input elements (I[..N]).
713///
714/// *Complete version*: It will return `Err(ErrMode::Backtrack(_))` if the input is shorter than the argument.
715///
716/// *[Partial version][crate::_topic::partial]*: if the input has less than N elements, `take` will
717/// return a `ErrMode::Incomplete(Needed::new(M))` where M is the number of
718/// additional bytes the parser would need to succeed.
719/// It is well defined for `&[u8]` as the number of elements is the byte size,
720/// but for types like `&str`, we cannot know how many bytes correspond for
721/// the next few chars, so the result will be `ErrMode::Incomplete(Needed::Unknown)`
722///
723/// # Effective Signature
724///
725/// Assuming you are parsing a `&str` [Stream] with `0..` or `1..` ranges:
726/// ```rust
727/// # use std::ops::RangeFrom;
728/// # use winnow::prelude::*;
729/// # use winnow::stream::ContainsToken;
730/// # use winnow::error::ContextError;
731/// pub fn take<'i>(token_count: usize) -> impl Parser<&'i str, &'i str, ContextError>
732/// # {
733/// # winnow::token::take(token_count)
734/// # }
735/// ```
736///
737/// # Example
738///
739/// ```rust
740/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
741/// # use winnow::prelude::*;
742/// use winnow::token::take;
743///
744/// fn take6<'i>(s: &mut &'i str) -> ModalResult<&'i str> {
745/// take(6usize).parse_next(s)
746/// }
747///
748/// assert_eq!(take6.parse_peek("1234567"), Ok(("7", "123456")));
749/// assert_eq!(take6.parse_peek("things"), Ok(("", "things")));
750/// assert!(take6.parse_peek("short").is_err());
751/// assert!(take6.parse_peek("").is_err());
752/// ```
753///
754/// The units that are taken will depend on the input type. For example, for a
755/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
756/// take that many `u8`'s:
757///
758/// ```rust
759/// # use winnow::prelude::*;
760/// use winnow::error::ContextError;
761/// use winnow::token::take;
762///
763/// assert_eq!(take::<_, _, ContextError>(1usize).parse_peek("💙"), Ok(("", "💙")));
764/// assert_eq!(take::<_, _, ContextError>(1usize).parse_peek("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
765/// ```
766///
767/// ```rust
768/// # use winnow::prelude::*;
769/// # use winnow::error::{ErrMode, ContextError, Needed};
770/// # use winnow::Partial;
771/// use winnow::token::take;
772///
773/// fn take6<'i>(s: &mut Partial<&'i str>) -> ModalResult<&'i str> {
774/// take(6usize).parse_next(s)
775/// }
776///
777/// assert_eq!(take6.parse_peek(Partial::new("1234567")), Ok((Partial::new("7"), "123456")));
778/// assert_eq!(take6.parse_peek(Partial::new("things")), Ok((Partial::new(""), "things")));
779/// // `Unknown` as we don't know the number of bytes that `count` corresponds to
780/// assert_eq!(take6.parse_peek(Partial::new("short")), Err(ErrMode::Incomplete(Needed::Unknown)));
781/// ```
782#[inline(always)]
783pub fn take<UsizeLike, Input, Error>(
784 token_count: UsizeLike,
785) -> impl Parser<Input, <Input as Stream>::Slice, Error>
786where
787 Input: StreamIsPartial + Stream,
788 UsizeLike: ToUsize,
789 Error: ParserError<Input>,
790{
791 let c = token_count.to_usize();
792 trace("take", move |i: &mut Input| {
793 if <Input as StreamIsPartial>::is_partial_supported() {
794 take_::<_, _, true>(i, c)
795 } else {
796 take_::<_, _, false>(i, c)
797 }
798 })
799}
800
801fn take_<I, Error: ParserError<I>, const PARTIAL: bool>(
802 i: &mut I,
803 c: usize,
804) -> Result<<I as Stream>::Slice, Error>
805where
806 I: StreamIsPartial,
807 I: Stream,
808{
809 match i.offset_at(c) {
810 Ok(offset) => Ok(i.next_slice(offset)),
811 Err(e) if PARTIAL && i.is_partial() => Err(ParserError::incomplete(i, e)),
812 Err(_needed) => Err(ParserError::from_input(i)),
813 }
814}
815
816/// Recognize the input slice up to the first occurrence of a [literal].
817///
818/// Feature `simd` will enable the use of [`memchr`](https://docs.rs/memchr/latest/memchr/).
819///
820/// It doesn't consume the literal.
821///
822/// *Complete version*: It will return `Err(ErrMode::Backtrack(_))`
823/// if the literal wasn't met.
824///
825/// *[Partial version][crate::_topic::partial]*: will return a `ErrMode::Incomplete(Needed::new(N))` if the input doesn't
826/// contain the literal or if the input is smaller than the literal.
827///
828/// See also
829/// - [`take_till`] for recognizing up-to a [set of tokens][ContainsToken]
830/// - [`repeat_till`][crate::combinator::repeat_till] with [`Parser::take`] for taking tokens up to a [`Parser`]
831///
832/// # Effective Signature
833///
834/// Assuming you are parsing a `&str` [Stream] with `0..` or `1..` [ranges][Range]:
835/// ```rust
836/// # use std::ops::RangeFrom;
837/// # use winnow::prelude::*;;
838/// # use winnow::error::ContextError;
839/// pub fn take_until(occurrences: RangeFrom<usize>, literal: &str) -> impl Parser<&str, &str, ContextError>
840/// # {
841/// # winnow::token::take_until(occurrences, literal)
842/// # }
843/// ```
844///
845/// # Example
846///
847/// ```rust
848/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
849/// # use winnow::prelude::*;
850/// use winnow::token::take_until;
851///
852/// fn until_eof<'i>(s: &mut &'i str) -> ModalResult<&'i str> {
853/// take_until(0.., "eof").parse_next(s)
854/// }
855///
856/// assert_eq!(until_eof.parse_peek("hello, worldeof"), Ok(("eof", "hello, world")));
857/// assert!(until_eof.parse_peek("hello, world").is_err());
858/// assert!(until_eof.parse_peek("").is_err());
859/// assert_eq!(until_eof.parse_peek("1eof2eof"), Ok(("eof2eof", "1")));
860/// ```
861///
862/// ```rust
863/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
864/// # use winnow::prelude::*;
865/// # use winnow::Partial;
866/// use winnow::token::take_until;
867///
868/// fn until_eof<'i>(s: &mut Partial<&'i str>) -> ModalResult<&'i str> {
869/// take_until(0.., "eof").parse_next(s)
870/// }
871///
872/// assert_eq!(until_eof.parse_peek(Partial::new("hello, worldeof")), Ok((Partial::new("eof"), "hello, world")));
873/// assert_eq!(until_eof.parse_peek(Partial::new("hello, world")), Err(ErrMode::Incomplete(Needed::Unknown)));
874/// assert_eq!(until_eof.parse_peek(Partial::new("hello, worldeo")), Err(ErrMode::Incomplete(Needed::Unknown)));
875/// assert_eq!(until_eof.parse_peek(Partial::new("1eof2eof")), Ok((Partial::new("eof2eof"), "1")));
876/// ```
877///
878/// ```rust
879/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
880/// # use winnow::prelude::*;
881/// use winnow::token::take_until;
882///
883/// fn until_eof<'i>(s: &mut &'i str) -> ModalResult<&'i str> {
884/// take_until(1.., "eof").parse_next(s)
885/// }
886///
887/// assert_eq!(until_eof.parse_peek("hello, worldeof"), Ok(("eof", "hello, world")));
888/// assert!(until_eof.parse_peek("hello, world").is_err());
889/// assert!(until_eof.parse_peek("").is_err());
890/// assert_eq!(until_eof.parse_peek("1eof2eof"), Ok(("eof2eof", "1")));
891/// assert!(until_eof.parse_peek("eof").is_err());
892/// ```
893///
894/// ```rust
895/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
896/// # use winnow::prelude::*;
897/// # use winnow::Partial;
898/// use winnow::token::take_until;
899///
900/// fn until_eof<'i>(s: &mut Partial<&'i str>) -> ModalResult<&'i str> {
901/// take_until(1.., "eof").parse_next(s)
902/// }
903///
904/// assert_eq!(until_eof.parse_peek(Partial::new("hello, worldeof")), Ok((Partial::new("eof"), "hello, world")));
905/// assert_eq!(until_eof.parse_peek(Partial::new("hello, world")), Err(ErrMode::Incomplete(Needed::Unknown)));
906/// assert_eq!(until_eof.parse_peek(Partial::new("hello, worldeo")), Err(ErrMode::Incomplete(Needed::Unknown)));
907/// assert_eq!(until_eof.parse_peek(Partial::new("1eof2eof")), Ok((Partial::new("eof2eof"), "1")));
908/// assert!(until_eof.parse_peek(Partial::new("eof")).is_err());
909/// ```
910#[inline(always)]
911pub fn take_until<Literal, Input, Error>(
912 occurrences: impl Into<Range>,
913 literal: Literal,
914) -> impl Parser<Input, <Input as Stream>::Slice, Error>
915where
916 Input: StreamIsPartial + Stream + FindSlice<Literal>,
917 Literal: Clone,
918 Error: ParserError<Input>,
919{
920 let Range {
921 start_inclusive,
922 end_inclusive,
923 } = occurrences.into();
924 trace("take_until", move |i: &mut Input| {
925 match (start_inclusive, end_inclusive) {
926 (0, None) => {
927 if <Input as StreamIsPartial>::is_partial_supported() {
928 take_until0_::<_, _, _, true>(i, literal.clone())
929 } else {
930 take_until0_::<_, _, _, false>(i, literal.clone())
931 }
932 }
933 (1, None) => {
934 if <Input as StreamIsPartial>::is_partial_supported() {
935 take_until1_::<_, _, _, true>(i, literal.clone())
936 } else {
937 take_until1_::<_, _, _, false>(i, literal.clone())
938 }
939 }
940 (start, end) => {
941 let end = end.unwrap_or(usize::MAX);
942 if <Input as StreamIsPartial>::is_partial_supported() {
943 take_until_m_n_::<_, _, _, true>(i, start, end, literal.clone())
944 } else {
945 take_until_m_n_::<_, _, _, false>(i, start, end, literal.clone())
946 }
947 }
948 }
949 })
950}
951
952fn take_until0_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
953 i: &mut I,
954 t: T,
955) -> Result<<I as Stream>::Slice, Error>
956where
957 I: StreamIsPartial,
958 I: Stream + FindSlice<T>,
959{
960 match i.find_slice(t) {
961 Some(range) => Ok(i.next_slice(range.start)),
962 None if PARTIAL && i.is_partial() => Err(ParserError::incomplete(i, Needed::Unknown)),
963 None => Err(ParserError::from_input(i)),
964 }
965}
966
967fn take_until1_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
968 i: &mut I,
969 t: T,
970) -> Result<<I as Stream>::Slice, Error>
971where
972 I: StreamIsPartial,
973 I: Stream + FindSlice<T>,
974{
975 match i.find_slice(t) {
976 None if PARTIAL && i.is_partial() => Err(ParserError::incomplete(i, Needed::Unknown)),
977 None => Err(ParserError::from_input(i)),
978 Some(range) => {
979 if range.start == 0 {
980 Err(ParserError::from_input(i))
981 } else {
982 Ok(i.next_slice(range.start))
983 }
984 }
985 }
986}
987
988fn take_until_m_n_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
989 i: &mut I,
990 start: usize,
991 end: usize,
992 t: T,
993) -> Result<<I as Stream>::Slice, Error>
994where
995 I: StreamIsPartial,
996 I: Stream + FindSlice<T>,
997{
998 if end < start {
999 return Err(ParserError::assert(
1000 i,
1001 "`occurrences` should be ascending, rather than descending",
1002 ));
1003 }
1004
1005 match i.find_slice(t) {
1006 Some(range) => {
1007 let start_offset = i.offset_at(start);
1008 let end_offset = i.offset_at(end).unwrap_or_else(|_err| i.eof_offset());
1009 if start_offset.map(|s| range.start < s).unwrap_or(true) {
1010 if PARTIAL && i.is_partial() {
1011 return Err(ParserError::incomplete(i, Needed::Unknown));
1012 } else {
1013 return Err(ParserError::from_input(i));
1014 }
1015 }
1016 if end_offset < range.start {
1017 return Err(ParserError::from_input(i));
1018 }
1019 Ok(i.next_slice(range.start))
1020 }
1021 None if PARTIAL && i.is_partial() => Err(ParserError::incomplete(i, Needed::Unknown)),
1022 None => Err(ParserError::from_input(i)),
1023 }
1024}
1025
1026/// Return the remaining input.
1027///
1028/// # Effective Signature
1029///
1030/// Assuming you are parsing a `&str` [Stream]:
1031/// ```rust
1032/// # use winnow::prelude::*;;
1033/// pub fn rest<'i>(input: &mut &'i str) -> ModalResult<&'i str>
1034/// # {
1035/// # winnow::token::rest.parse_next(input)
1036/// # }
1037/// ```
1038///
1039/// # Example
1040///
1041/// ```rust
1042/// # use winnow::prelude::*;
1043/// # use winnow::error::ContextError;
1044/// use winnow::token::rest;
1045/// assert_eq!(rest::<_,ContextError>.parse_peek("abc"), Ok(("", "abc")));
1046/// assert_eq!(rest::<_,ContextError>.parse_peek(""), Ok(("", "")));
1047/// ```
1048#[inline]
1049pub fn rest<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error>
1050where
1051 Input: Stream,
1052 Error: ParserError<Input>,
1053{
1054 trace("rest", move |input: &mut Input| Ok(input.finish())).parse_next(input)
1055}
1056
1057/// Return the length of the remaining input.
1058///
1059/// <div class="warning">
1060///
1061/// Note: this does not advance the [`Stream`]
1062///
1063/// </div>
1064///
1065/// # Effective Signature
1066///
1067/// Assuming you are parsing a `&str` [Stream]:
1068/// ```rust
1069/// # use winnow::prelude::*;;
1070/// pub fn rest_len(input: &mut &str) -> ModalResult<usize>
1071/// # {
1072/// # winnow::token::rest_len.parse_next(input)
1073/// # }
1074/// ```
1075///
1076/// # Example
1077///
1078/// ```rust
1079/// # use winnow::prelude::*;
1080/// # use winnow::error::ContextError;
1081/// use winnow::token::rest_len;
1082/// assert_eq!(rest_len::<_,ContextError>.parse_peek("abc"), Ok(("abc", 3)));
1083/// assert_eq!(rest_len::<_,ContextError>.parse_peek(""), Ok(("", 0)));
1084/// ```
1085#[inline]
1086pub fn rest_len<Input, Error>(input: &mut Input) -> Result<usize, Error>
1087where
1088 Input: Stream,
1089 Error: ParserError<Input>,
1090{
1091 trace("rest_len", move |input: &mut Input| {
1092 let len = input.eof_offset();
1093 Ok(len)
1094 })
1095 .parse_next(input)
1096}