1 //! parsers recognizing bytes streams, streaming version
2
3 use crate::error::ErrorKind;
4 use crate::error::ParseError;
5 use crate::internal::{Err, IResult, Needed};
6 use crate::lib::std::ops::RangeFrom;
7 use crate::lib::std::result::Result::*;
8 use crate::traits::{Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, Slice, ToUsize};
9
10 /// Recognizes a pattern
11 ///
12 /// The input data will be compared to the tag combinator's argument and will return the part of
13 /// the input that matches the argument
14 /// # Example
15 /// ```rust
16 /// # #[macro_use] extern crate nom;
17 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
18 /// use nom::bytes::streaming::tag;
19 ///
20 /// fn parser(s: &str) -> IResult<&str, &str> {
21 /// tag("Hello")(s)
22 /// }
23 ///
24 /// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
25 /// assert_eq!(parser("Something"), Err(Err::Error(("Something", ErrorKind::Tag))));
26 /// assert_eq!(parser(""), Err(Err::Incomplete(Needed::Size(5))));
27 /// ```
tag<'a, T: 'a, Input: 'a, Error: ParseError<Input>>(tag: T) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTake + Compare<T>, T: InputLength + Clone,28 pub fn tag<'a, T: 'a, Input: 'a, Error: ParseError<Input>>(tag: T) -> impl Fn(Input) -> IResult<Input, Input, Error>
29 where
30 Input: InputTake + Compare<T>,
31 T: InputLength + Clone,
32 {
33 move |i: Input| {
34 let tag_len = tag.input_len();
35 let t = tag.clone();
36
37 let res: IResult<_, _, Error> = match i.compare(t) {
38 CompareResult::Ok => Ok(i.take_split(tag_len)),
39 CompareResult::Incomplete => Err(Err::Incomplete(Needed::Size(tag_len))),
40 CompareResult::Error => {
41 let e: ErrorKind = ErrorKind::Tag;
42 Err(Err::Error(Error::from_error_kind(i, e)))
43 }
44 };
45 res
46 }
47 }
48
49 /// Recognizes a case insensitive pattern
50 ///
51 /// The input data will be compared to the tag combinator's argument and will return the part of
52 /// the input that matches the argument with no regard to case
53 /// # Example
54 /// ```rust
55 /// # #[macro_use] extern crate nom;
56 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
57 /// use nom::bytes::streaming::tag_no_case;
58 ///
59 /// fn parser(s: &str) -> IResult<&str, &str> {
60 /// tag_no_case("hello")(s)
61 /// }
62 ///
63 /// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
64 /// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
65 /// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
66 /// assert_eq!(parser("Something"), Err(Err::Error(("Something", ErrorKind::Tag))));
67 /// assert_eq!(parser(""), Err(Err::Incomplete(Needed::Size(5))));
68 /// ```
tag_no_case<T, Input, Error: ParseError<Input>>(tag: T) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTake + Compare<T>, T: InputLength + Clone,69 pub fn tag_no_case<T, Input, Error: ParseError<Input>>(tag: T) -> impl Fn(Input) -> IResult<Input, Input, Error>
70 where
71 Input: InputTake + Compare<T>,
72 T: InputLength + Clone,
73 {
74 move |i: Input| {
75 let tag_len = tag.input_len();
76 let t = tag.clone();
77
78 let res: IResult<_, _, Error> = match (i).compare_no_case(t) {
79 CompareResult::Ok => Ok(i.take_split(tag_len)),
80 CompareResult::Incomplete => Err(Err::Incomplete(Needed::Size(tag_len))),
81 CompareResult::Error => {
82 let e: ErrorKind = ErrorKind::Tag;
83 Err(Err::Error(Error::from_error_kind(i, e)))
84 }
85 };
86 res
87 }
88 }
89
90 /// Parse till certain characters are met
91 ///
92 /// The parser will return the longest slice till one of the characters of the combinator's argument are met.
93 ///
94 /// It doesn't consume the matched character,
95 ///
96 /// It will return a `Err::Incomplete(Needed::Size(1))` if the pattern wasn't met
97 /// # Example
98 /// ```rust
99 /// # #[macro_use] extern crate nom;
100 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
101 /// use nom::bytes::streaming::is_not;
102 ///
103 /// fn not_space(s: &str) -> IResult<&str, &str> {
104 /// is_not(" \t\r\n")(s)
105 /// }
106 ///
107 /// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
108 /// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
109 /// assert_eq!(not_space("Nospace"), Err(Err::Incomplete(Needed::Size(1))));
110 /// assert_eq!(not_space(""), Err(Err::Incomplete(Needed::Size(1))));
111 /// ```
is_not<T, Input, Error: ParseError<Input>>(arr: T) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTakeAtPosition, T: InputLength + FindToken<<Input as InputTakeAtPosition>::Item>,112 pub fn is_not<T, Input, Error: ParseError<Input>>(arr: T) -> impl Fn(Input) -> IResult<Input, Input, Error>
113 where
114 Input: InputTakeAtPosition,
115 T: InputLength + FindToken<<Input as InputTakeAtPosition>::Item>,
116 {
117 move |i: Input| {
118 let e: ErrorKind = ErrorKind::IsNot;
119 i.split_at_position1(|c| arr.find_token(c), e)
120 }
121 }
122
123 /// Returns the longest slice of the matches the pattern
124 ///
125 /// The parser will return the longest slice consisting of the characters in provided in the
126 /// combinator's argument
127 ///
128 /// # Streaming specific
129 /// *Streaming version* will return a `Err::Incomplete(Needed::Size(1))` if the pattern wasn't met
130 /// or if the pattern reaches the end of the input
131 /// # Example
132 /// ```rust
133 /// # #[macro_use] extern crate nom;
134 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
135 /// use nom::bytes::streaming::is_a;
136 ///
137 /// fn hex(s: &str) -> IResult<&str, &str> {
138 /// is_a("1234567890ABCDEF")(s)
139 /// }
140 ///
141 /// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
142 /// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
143 /// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
144 /// assert_eq!(hex("D15EA5E"), Err(Err::Incomplete(Needed::Size(1))));
145 /// assert_eq!(hex(""), Err(Err::Incomplete(Needed::Size(1))));
146 /// ```
is_a<T, Input, Error: ParseError<Input>>(arr: T) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTakeAtPosition, T: InputLength + FindToken<<Input as InputTakeAtPosition>::Item>,147 pub fn is_a<T, Input, Error: ParseError<Input>>(arr: T) -> impl Fn(Input) -> IResult<Input, Input, Error>
148 where
149 Input: InputTakeAtPosition,
150 T: InputLength + FindToken<<Input as InputTakeAtPosition>::Item>,
151 {
152 move |i: Input| {
153 let e: ErrorKind = ErrorKind::IsA;
154 i.split_at_position1(|c| !arr.find_token(c), e)
155 }
156 }
157
158 /// Returns the longest input slice (if any) that matches the predicate
159 ///
160 /// The parser will return the longest slice that matches the given predicate *(a function that
161 /// takes the input and returns a bool)*
162 ///
163 /// # Streaming Specific
164 /// *Streaming version* will return a `Err::Incomplete(Needed::Size(1))` if the pattern reaches the end of the input
165 /// # Example
166 /// ```rust
167 /// # #[macro_use] extern crate nom;
168 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
169 /// use nom::bytes::streaming::take_while;
170 /// use nom::character::is_alphabetic;
171 ///
172 /// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
173 /// take_while(is_alphabetic)(s)
174 /// }
175 ///
176 /// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
177 /// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
178 /// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::Size(1))));
179 /// assert_eq!(alpha(b""), Err(Err::Incomplete(Needed::Size(1))));
180 /// ```
take_while<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTakeAtPosition, F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,181 pub fn take_while<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error>
182 where
183 Input: InputTakeAtPosition,
184 F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
185 {
186 move |i: Input| i.split_at_position(|c| !cond(c))
187 }
188
189 /// Returns the longest (atleast 1) input slice that matches the predicate
190 ///
191 /// The parser will return the longest slice that matches the given predicate *(a function that
192 /// takes the input and returns a bool)*
193 ///
194 /// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met
195 ///
196 /// # Streaming Specific
197 /// *Streaming version* will return a `Err::Incomplete(Needed::Size(1))` or if the pattern reaches the end of the input.
198 ///
199 /// # Example
200 /// ```rust
201 /// # #[macro_use] extern crate nom;
202 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
203 /// use nom::bytes::streaming::take_while1;
204 /// use nom::character::is_alphabetic;
205 ///
206 /// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
207 /// take_while1(is_alphabetic)(s)
208 /// }
209 ///
210 /// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
211 /// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::Size(1))));
212 /// assert_eq!(alpha(b"12345"), Err(Err::Error((&b"12345"[..], ErrorKind::TakeWhile1))));
213 /// ```
take_while1<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTakeAtPosition, F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,214 pub fn take_while1<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error>
215 where
216 Input: InputTakeAtPosition,
217 F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
218 {
219 move |i: Input| {
220 let e: ErrorKind = ErrorKind::TakeWhile1;
221 i.split_at_position1(|c| !cond(c), e)
222 }
223 }
224
225 /// Returns the longest (m <= len <= n) input slice that matches the predicate
226 ///
227 /// The parser will return the longest slice that matches the given predicate *(a function that
228 /// takes the input and returns a bool)*
229 ///
230 /// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met
231 /// # Streaming Specific
232 /// *Streaming version* will return a `Err::Incomplete(Needed::Size(1))` if the pattern reaches the end of the input or is too short.
233 ///
234 /// # Example
235 /// ```rust
236 /// # #[macro_use] extern crate nom;
237 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
238 /// use nom::bytes::streaming::take_while_m_n;
239 /// use nom::character::is_alphabetic;
240 ///
241 /// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
242 /// take_while_m_n(3, 6, is_alphabetic)(s)
243 /// }
244 ///
245 /// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
246 /// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
247 /// assert_eq!(short_alpha(b"latin"), Err(Err::Incomplete(Needed::Size(1))));
248 /// assert_eq!(short_alpha(b"ed"), Err(Err::Incomplete(Needed::Size(1))));
249 /// assert_eq!(short_alpha(b"12345"), Err(Err::Error((&b"12345"[..], ErrorKind::TakeWhileMN))));
250 /// ```
take_while_m_n<F, Input, Error: ParseError<Input>>(m: usize, n: usize, cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>, F: Fn(<Input as InputIter>::Item) -> bool,251 pub fn take_while_m_n<F, Input, Error: ParseError<Input>>(m: usize, n: usize, cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error>
252 where
253 Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>,
254 F: Fn(<Input as InputIter>::Item) -> bool,
255 {
256 move |i: Input| {
257 let input = i;
258
259 match input.position(|c| !cond(c)) {
260 Some(idx) => {
261 if idx >= m {
262 if idx <= n {
263 let res: IResult<_, _, Error> = if let Some(index) = input.slice_index(idx) {
264 Ok(input.take_split(index))
265 } else {
266 Err(Err::Error(Error::from_error_kind(input, ErrorKind::TakeWhileMN)))
267 };
268 res
269 } else {
270 let res: IResult<_, _, Error> = if let Some(index) = input.slice_index(n) {
271 Ok(input.take_split(index))
272 } else {
273 Err(Err::Error(Error::from_error_kind(input, ErrorKind::TakeWhileMN)))
274 };
275 res
276 }
277 } else {
278 let e = ErrorKind::TakeWhileMN;
279 Err(Err::Error(Error::from_error_kind(input, e)))
280 }
281 }
282 None => {
283 let len = input.input_len();
284 if len >= n {
285 match input.slice_index(n) {
286 Some(index) => Ok(input.take_split(index)),
287 None => Err(Err::Error(Error::from_error_kind(input, ErrorKind::TakeWhileMN)))
288 }
289 } else {
290 let needed = if m > len { m - len } else { 1 };
291 Err(Err::Incomplete(Needed::Size(needed)))
292 }
293 }
294 }
295 }
296 }
297
298 /// Returns the longest input slice (if any) till a predicate is met
299 ///
300 /// The parser will return the longest slice till the given predicate *(a function that
301 /// takes the input and returns a bool)*
302 ///
303 /// # Streaming Specific
304 /// *Streaming version* will return a `Err::Incomplete(Needed::Size(1))` if the match reaches the
305 /// end of input or if there was not match
306 ///
307 /// # Example
308 /// ```rust
309 /// # #[macro_use] extern crate nom;
310 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
311 /// use nom::bytes::streaming::take_till;
312 ///
313 /// fn till_colon(s: &str) -> IResult<&str, &str> {
314 /// take_till(|c| c == ':')(s)
315 /// }
316 ///
317 /// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
318 /// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
319 /// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::Size(1))));
320 /// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::Size(1))));
321 /// ```
take_till<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTakeAtPosition, F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,322 pub fn take_till<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error>
323 where
324 Input: InputTakeAtPosition,
325 F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
326 {
327 move |i: Input| i.split_at_position(|c| cond(c))
328 }
329
330 /// Returns the longest (atleast 1) input slice till a predicate is met
331 ///
332 /// The parser will return the longest slice till the given predicate *(a function that
333 /// takes the input and returns a bool)*
334 ///
335 /// # Streaming Specific
336 /// *Streaming version* will return a `Err::Incomplete(Needed::Size(1))` if the match reaches the
337 /// end of input or if there was not match
338 /// # Example
339 /// ```rust
340 /// # #[macro_use] extern crate nom;
341 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
342 /// use nom::bytes::streaming::take_till1;
343 ///
344 /// fn till_colon(s: &str) -> IResult<&str, &str> {
345 /// take_till1(|c| c == ':')(s)
346 /// }
347 ///
348 /// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
349 /// assert_eq!(till_colon(":empty matched"), Err(Err::Error((":empty matched", ErrorKind::TakeTill1))));
350 /// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::Size(1))));
351 /// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::Size(1))));
352 /// ```
take_till1<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTakeAtPosition, F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,353 pub fn take_till1<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error>
354 where
355 Input: InputTakeAtPosition,
356 F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
357 {
358 move |i: Input| {
359 let e: ErrorKind = ErrorKind::TakeTill1;
360 i.split_at_position1(|c| cond(c), e)
361 }
362 }
363
364 /// Returns an input slice containing the first N input elements (Input[..N])
365 ///
366 /// # Streaming Specific
367 /// *Streaming version* will return a `Err::Incomplete(Needed::Size(N))` where N is the
368 /// argument if the input is less than the length provided
369 /// # Example
370 /// ```rust
371 /// # #[macro_use] extern crate nom;
372 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
373 /// use nom::bytes::streaming::take;
374 ///
375 /// fn take6(s: &str) -> IResult<&str, &str> {
376 /// take(6usize)(s)
377 /// }
378 ///
379 /// assert_eq!(take6("1234567"), Ok(("7", "123456")));
380 /// assert_eq!(take6("things"), Ok(("", "things")));
381 /// assert_eq!(take6("short"), Err(Err::Incomplete(Needed::Size(6)))); //N doesn't change
382 /// assert_eq!(take6(""), Err(Err::Incomplete(Needed::Size(6))));
383 /// ```
take<C, Input, Error: ParseError<Input>>(count: C) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputIter + InputTake, C: ToUsize,384 pub fn take<C, Input, Error: ParseError<Input>>(count: C) -> impl Fn(Input) -> IResult<Input, Input, Error>
385 where
386 Input: InputIter + InputTake,
387 C: ToUsize,
388 {
389 let c = count.to_usize();
390 move |i: Input| match i.slice_index(c) {
391 None => Err(Err::Incomplete(Needed::Size(c))),
392 Some(index) => Ok(i.take_split(index)),
393 }
394 }
395
396 /// Returns the longest input slice till it matches the pattern.
397 ///
398 /// It doesn't consume the pattern
399 ///
400 /// # Streaming Specific
401 /// *Streaming version* will return a `Err::Incomplete(Needed::Size(N))` if the input doesn't
402 /// contain the pattern or if the input is smaller than the pattern
403 /// # Example
404 /// ```rust
405 /// # #[macro_use] extern crate nom;
406 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
407 /// use nom::bytes::streaming::take_until;
408 ///
409 /// fn until_eof(s: &str) -> IResult<&str, &str> {
410 /// take_until("eof")(s)
411 /// }
412 ///
413 /// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
414 /// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Size(3))));
415 /// assert_eq!(until_eof(""), Err(Err::Incomplete(Needed::Size(3))));
416 /// ```
take_until<T, Input, Error: ParseError<Input>>(tag: T) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: InputTake + FindSubstring<T>, T: InputLength + Clone,417 pub fn take_until<T, Input, Error: ParseError<Input>>(tag: T) -> impl Fn(Input) -> IResult<Input, Input, Error>
418 where
419 Input: InputTake + FindSubstring<T>,
420 T: InputLength + Clone,
421 {
422 move |i: Input| {
423 let len = tag.input_len();
424 let t = tag.clone();
425
426 let res: IResult<_, _, Error> = match i.find_substring(t) {
427 None => Err(Err::Incomplete(Needed::Size(len))),
428 Some(index) => Ok(i.take_split(index)),
429 };
430 res
431 }
432 }
433
434 /// Matches a byte string with escaped characters.
435 ///
436 /// * The first argument matches the normal characters (it must not accept the control character),
437 /// * the second argument is the control character (like `\` in most languages),
438 /// * the third argument matches the escaped characters
439 ///
440 /// # Example
441 /// ```
442 /// # #[macro_use] extern crate nom;
443 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
444 /// # use nom::character::complete::digit1;
445 /// use nom::bytes::streaming::escaped;
446 /// use nom::character::streaming::one_of;
447 ///
448 /// fn esc(s: &str) -> IResult<&str, &str> {
449 /// escaped(digit1, '\\', one_of("\"n\\"))(s)
450 /// }
451 ///
452 /// assert_eq!(esc("123;"), Ok((";", "123")));
453 /// assert_eq!(esc("12\\\"34;"), Ok((";", "12\\\"34")));
454 /// ```
455 ///
escaped<Input, Error, F, G, O1, O2>(normal: F, control_char: char, escapable: G) -> impl Fn(Input) -> IResult<Input, Input, Error> where Input: Clone + crate::traits::Offset + InputLength + InputTake + InputTakeAtPosition + Slice<RangeFrom<usize>> + InputIter, <Input as InputIter>::Item: crate::traits::AsChar, F: Fn(Input) -> IResult<Input, O1, Error>, G: Fn(Input) -> IResult<Input, O2, Error>, Error: ParseError<Input>,456 pub fn escaped<Input, Error, F, G, O1, O2>(normal: F, control_char: char, escapable: G) -> impl Fn(Input) -> IResult<Input, Input, Error>
457 where
458 Input: Clone + crate::traits::Offset + InputLength + InputTake + InputTakeAtPosition + Slice<RangeFrom<usize>> + InputIter,
459 <Input as InputIter>::Item: crate::traits::AsChar,
460 F: Fn(Input) -> IResult<Input, O1, Error>,
461 G: Fn(Input) -> IResult<Input, O2, Error>,
462 Error: ParseError<Input>,
463 {
464 use crate::traits::AsChar;
465
466 move |input: Input| {
467 let mut i = input.clone();
468
469 while i.input_len() > 0 {
470 match normal(i.clone()) {
471 Ok((i2, _)) => {
472 if i2.input_len() == 0 {
473 return Err(Err::Incomplete(Needed::Unknown));
474 } else {
475 i = i2;
476 }
477 }
478 Err(Err::Error(_)) => {
479 // unwrap() should be safe here since index < $i.input_len()
480 if i.iter_elements().next().unwrap().as_char() == control_char {
481 let next = control_char.len_utf8();
482 if next >= i.input_len() {
483 return Err(Err::Incomplete(Needed::Size(1)));
484 } else {
485 match escapable(i.slice(next..)) {
486 Ok((i2, _)) => {
487 if i2.input_len() == 0 {
488 return Err(Err::Incomplete(Needed::Unknown));
489 } else {
490 i = i2;
491 }
492 }
493 Err(e) => return Err(e),
494 }
495 }
496 } else {
497 let index = input.offset(&i);
498 return Ok(input.take_split(index));
499 }
500 }
501 Err(e) => {
502 return Err(e);
503 }
504 }
505 }
506
507 Err(Err::Incomplete(Needed::Unknown))
508 }
509 }
510
511 #[doc(hidden)]
escapedc<Input, Error, F, G, O1, O2>(i: Input, normal: F, control_char: char, escapable: G) -> IResult<Input, Input, Error> where Input: Clone + crate::traits::Offset + InputLength + InputTake + InputTakeAtPosition + Slice<RangeFrom<usize>> + InputIter, <Input as InputIter>::Item: crate::traits::AsChar, F: Fn(Input) -> IResult<Input, O1, Error>, G: Fn(Input) -> IResult<Input, O2, Error>, Error: ParseError<Input>,512 pub fn escapedc<Input, Error, F, G, O1, O2>(i: Input, normal: F, control_char: char, escapable: G) -> IResult<Input, Input, Error>
513 where
514 Input: Clone + crate::traits::Offset + InputLength + InputTake + InputTakeAtPosition + Slice<RangeFrom<usize>> + InputIter,
515 <Input as InputIter>::Item: crate::traits::AsChar,
516 F: Fn(Input) -> IResult<Input, O1, Error>,
517 G: Fn(Input) -> IResult<Input, O2, Error>,
518 Error: ParseError<Input>,
519 {
520 escaped(normal, control_char, escapable)(i)
521 }
522
523 /// Matches a byte string with escaped characters.
524 ///
525 /// * The first argument matches the normal characters (it must not match the control character),
526 /// * the second argument is the control character (like `\` in most languages),
527 /// * the third argument matches the escaped characters and transforms them.
528 ///
529 /// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character)
530 ///
531 /// ```
532 /// # #[macro_use] extern crate nom;
533 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
534 /// # use std::str::from_utf8;
535 /// use nom::bytes::streaming::escaped_transform;
536 /// use nom::character::streaming::alpha1;
537 ///
538 /// fn parser(input: &str) -> IResult<&str, String> {
539 /// escaped_transform(
540 /// alpha1,
541 /// '\\',
542 /// |i:&str| alt!(i,
543 /// tag!("\\") => { |_| "\\" }
544 /// | tag!("\"") => { |_| "\"" }
545 /// | tag!("n") => { |_| "\n" }
546 /// )
547 /// )(input)
548 /// }
549 ///
550 /// assert_eq!(parser("ab\\\"cd\""), Ok(("\"", String::from("ab\"cd"))));
551 /// ```
552 #[cfg(feature = "alloc")]
escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>( normal: F, control_char: char, transform: G, ) -> impl Fn(Input) -> IResult<Input, Output, Error> where Input: Clone + crate::traits::Offset + InputLength + InputTake + InputTakeAtPosition + Slice<RangeFrom<usize>> + InputIter, Input: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, Output: core::iter::Extend<<Input as crate::traits::ExtendInto>::Item>, Output: core::iter::Extend<<O1 as crate::traits::ExtendInto>::Item>, Output: core::iter::Extend<<O2 as crate::traits::ExtendInto>::Item>, <Input as InputIter>::Item: crate::traits::AsChar, F: Fn(Input) -> IResult<Input, O1, Error>, G: Fn(Input) -> IResult<Input, O2, Error>, Error: ParseError<Input>,553 pub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>(
554 normal: F,
555 control_char: char,
556 transform: G,
557 ) -> impl Fn(Input) -> IResult<Input, Output, Error>
558 where
559 Input: Clone + crate::traits::Offset + InputLength + InputTake + InputTakeAtPosition + Slice<RangeFrom<usize>> + InputIter,
560 Input: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
561 O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
562 O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
563 Output: core::iter::Extend<<Input as crate::traits::ExtendInto>::Item>,
564 Output: core::iter::Extend<<O1 as crate::traits::ExtendInto>::Item>,
565 Output: core::iter::Extend<<O2 as crate::traits::ExtendInto>::Item>,
566 <Input as InputIter>::Item: crate::traits::AsChar,
567 F: Fn(Input) -> IResult<Input, O1, Error>,
568 G: Fn(Input) -> IResult<Input, O2, Error>,
569 Error: ParseError<Input>,
570 {
571 use crate::traits::AsChar;
572
573 move |input: Input| {
574 let mut index = 0;
575 let mut res = input.new_builder();
576
577 let i = input.clone();
578
579 while index < i.input_len() {
580 let remainder = i.slice(index..);
581 match normal(remainder.clone()) {
582 Ok((i2, o)) => {
583 o.extend_into(&mut res);
584 if i2.input_len() == 0 {
585 return Err(Err::Incomplete(Needed::Unknown));
586 } else {
587 index = input.offset(&i2);
588 }
589 }
590 Err(Err::Error(_)) => {
591 // unwrap() should be safe here since index < $i.input_len()
592 if remainder.iter_elements().next().unwrap().as_char() == control_char {
593 let next = index + control_char.len_utf8();
594 let input_len = input.input_len();
595
596 if next >= input_len {
597 return Err(Err::Incomplete(Needed::Unknown));
598 } else {
599 match transform(i.slice(next..)) {
600 Ok((i2, o)) => {
601 o.extend_into(&mut res);
602 if i2.input_len() == 0 {
603 return Err(Err::Incomplete(Needed::Unknown));
604 } else {
605 index = input.offset(&i2);
606 }
607 }
608 Err(e) => return Err(e),
609 }
610 }
611 } else {
612 return Ok((remainder, res));
613 }
614 }
615 Err(e) => return Err(e),
616 }
617 }
618 Err(Err::Incomplete(Needed::Unknown))
619 }
620 }
621
622 #[doc(hidden)]
623 #[cfg(feature = "alloc")]
escaped_transformc<Input, Error, F, G, O1, O2, ExtendItem, Output>( i: Input, normal: F, control_char: char, transform: G, ) -> IResult<Input, Output, Error> where Input: Clone + crate::traits::Offset + InputLength + InputTake + InputTakeAtPosition + Slice<RangeFrom<usize>> + InputIter, Input: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, Output: core::iter::Extend<<Input as crate::traits::ExtendInto>::Item>, Output: core::iter::Extend<<O1 as crate::traits::ExtendInto>::Item>, Output: core::iter::Extend<<O2 as crate::traits::ExtendInto>::Item>, <Input as InputIter>::Item: crate::traits::AsChar, F: Fn(Input) -> IResult<Input, O1, Error>, G: Fn(Input) -> IResult<Input, O2, Error>, Error: ParseError<Input>,624 pub fn escaped_transformc<Input, Error, F, G, O1, O2, ExtendItem, Output>(
625 i: Input,
626 normal: F,
627 control_char: char,
628 transform: G,
629 ) -> IResult<Input, Output, Error>
630 where
631 Input: Clone + crate::traits::Offset + InputLength + InputTake + InputTakeAtPosition + Slice<RangeFrom<usize>> + InputIter,
632 Input: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
633 O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
634 O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
635 Output: core::iter::Extend<<Input as crate::traits::ExtendInto>::Item>,
636 Output: core::iter::Extend<<O1 as crate::traits::ExtendInto>::Item>,
637 Output: core::iter::Extend<<O2 as crate::traits::ExtendInto>::Item>,
638 <Input as InputIter>::Item: crate::traits::AsChar,
639 F: Fn(Input) -> IResult<Input, O1, Error>,
640 G: Fn(Input) -> IResult<Input, O2, Error>,
641 Error: ParseError<Input>,
642 {
643 escaped_transform(normal, control_char, transform)(i)
644
645 }
646