Function winnow::token::take_while

source ·
pub fn take_while<T, I, Error: ParserError<I>>(
    range: impl Into<Range>,
    list: T,
) -> impl Parser<I, <I as Stream>::Slice, Error>
Expand description

Recognize the longest (m <= len <= n) input slice that matches the pattern

It will return an ErrMode::Backtrack(InputError::new(_, ErrorKind::Slice)) if the pattern wasn’t met or is out of range (m <= len <= n).

Partial version will return a ErrMode::Incomplete(Needed::new(1)) if the pattern reaches the end of the input or is too short.

To recognize a series of tokens, use repeat to Accumulate into a () and then Parser::recognize.

§Example

Zero or more tokens:

use winnow::token::take_while;
use winnow::stream::AsChar;

fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
  take_while(0.., AsChar::is_alpha).parse_peek(s)
}

assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
assert_eq!(alpha(b""), Ok((&b""[..], &b""[..])));
use winnow::token::take_while;
use winnow::stream::AsChar;

fn alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
  take_while(0.., AsChar::is_alpha).parse_peek(s)
}

assert_eq!(alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
assert_eq!(alpha(Partial::new(b"12345")), Ok((Partial::new(&b"12345"[..]), &b""[..])));
assert_eq!(alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
assert_eq!(alpha(Partial::new(b"")), Err(ErrMode::Incomplete(Needed::new(1))));

One or more tokens:

use winnow::token::take_while;
use winnow::stream::AsChar;

fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
  take_while(1.., AsChar::is_alpha).parse_peek(s)
}

assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
assert_eq!(alpha(b"12345"), Err(ErrMode::Backtrack(InputError::new(&b"12345"[..], ErrorKind::Slice))));

fn hex(s: &str) -> IResult<&str, &str> {
  take_while(1.., ('0'..='9', 'A'..='F')).parse_peek(s)
}

assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E")));
assert_eq!(hex(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice))));
use winnow::token::take_while;
use winnow::stream::AsChar;

fn alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
  take_while(1.., AsChar::is_alpha).parse_peek(s)
}

assert_eq!(alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
assert_eq!(alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
assert_eq!(alpha(Partial::new(b"12345")), Err(ErrMode::Backtrack(InputError::new(Partial::new(&b"12345"[..]), ErrorKind::Slice))));

fn hex(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
  take_while(1.., ('0'..='9', 'A'..='F')).parse_peek(s)
}

assert_eq!(hex(Partial::new("123 and voila")), Ok((Partial::new(" and voila"), "123")));
assert_eq!(hex(Partial::new("DEADBEEF and others")), Ok((Partial::new(" and others"), "DEADBEEF")));
assert_eq!(hex(Partial::new("BADBABEsomething")), Ok((Partial::new("something"), "BADBABE")));
assert_eq!(hex(Partial::new("D15EA5E")), Err(ErrMode::Incomplete(Needed::new(1))));
assert_eq!(hex(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));

Arbitrary amount of tokens:

use winnow::token::take_while;
use winnow::stream::AsChar;

fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
  take_while(3..=6, AsChar::is_alpha).parse_peek(s)
}

assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
assert_eq!(short_alpha(b"ed"), Err(ErrMode::Backtrack(InputError::new(&b"ed"[..], ErrorKind::Slice))));
assert_eq!(short_alpha(b"12345"), Err(ErrMode::Backtrack(InputError::new(&b"12345"[..], ErrorKind::Slice))));
use winnow::token::take_while;
use winnow::stream::AsChar;

fn short_alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
  take_while(3..=6, AsChar::is_alpha).parse_peek(s)
}

assert_eq!(short_alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
assert_eq!(short_alpha(Partial::new(b"lengthy")), Ok((Partial::new(&b"y"[..]), &b"length"[..])));
assert_eq!(short_alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
assert_eq!(short_alpha(Partial::new(b"ed")), Err(ErrMode::Incomplete(Needed::new(1))));
assert_eq!(short_alpha(Partial::new(b"12345")), Err(ErrMode::Backtrack(InputError::new(Partial::new(&b"12345"[..]), ErrorKind::Slice))));