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