/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nom-8.0.0/src/bytes/streaming.rs
Line | Count | Source |
1 | | //! Parsers recognizing bytes streams, streaming version |
2 | | |
3 | | use core::marker::PhantomData; |
4 | | |
5 | | use crate::error::ParseError; |
6 | | use crate::internal::{IResult, Parser}; |
7 | | use crate::traits::{Compare, FindSubstring, FindToken, ToUsize}; |
8 | | use crate::Emit; |
9 | | use crate::Input; |
10 | | use crate::OutputM; |
11 | | use crate::Streaming; |
12 | | |
13 | | /// Recognizes a pattern. |
14 | | /// |
15 | | /// The input data will be compared to the tag combinator's argument and will return the part of |
16 | | /// the input that matches the argument. |
17 | | /// # Example |
18 | | /// ```rust |
19 | | /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; |
20 | | /// use nom::bytes::streaming::tag; |
21 | | /// |
22 | | /// fn parser(s: &str) -> IResult<&str, &str> { |
23 | | /// tag("Hello")(s) |
24 | | /// } |
25 | | /// |
26 | | /// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); |
27 | | /// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); |
28 | | /// assert_eq!(parser("S"), Err(Err::Error(Error::new("S", ErrorKind::Tag)))); |
29 | | /// assert_eq!(parser("H"), Err(Err::Incomplete(Needed::new(4)))); |
30 | | /// ``` |
31 | 0 | pub fn tag<T, I, Error: ParseError<I>>(tag: T) -> impl Fn(I) -> IResult<I, I, Error> |
32 | 0 | where |
33 | 0 | I: Input + Compare<T>, |
34 | 0 | T: Input + Clone, |
35 | | { |
36 | 0 | move |i: I| { |
37 | 0 | let mut parser = super::Tag { |
38 | 0 | tag: tag.clone(), |
39 | 0 | e: PhantomData, |
40 | 0 | }; |
41 | | |
42 | 0 | parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
43 | 0 | } |
44 | 0 | } |
45 | | |
46 | | /// Recognizes a case insensitive pattern. |
47 | | /// |
48 | | /// The input data will be compared to the tag combinator's argument and will return the part of |
49 | | /// the input that matches the argument with no regard to case. |
50 | | /// # Example |
51 | | /// ```rust |
52 | | /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; |
53 | | /// use nom::bytes::streaming::tag_no_case; |
54 | | /// |
55 | | /// fn parser(s: &str) -> IResult<&str, &str> { |
56 | | /// tag_no_case("hello")(s) |
57 | | /// } |
58 | | /// |
59 | | /// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); |
60 | | /// assert_eq!(parser("hello, World!"), Ok((", World!", "hello"))); |
61 | | /// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO"))); |
62 | | /// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); |
63 | | /// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(5)))); |
64 | | /// ``` |
65 | 0 | pub fn tag_no_case<T, I, Error: ParseError<I>>(tag: T) -> impl Fn(I) -> IResult<I, I, Error> |
66 | 0 | where |
67 | 0 | I: Input + Compare<T>, |
68 | 0 | T: Input + Clone, |
69 | | { |
70 | 0 | move |i: I| { |
71 | 0 | let mut parser = super::TagNoCase { |
72 | 0 | tag: tag.clone(), |
73 | 0 | e: PhantomData, |
74 | 0 | }; |
75 | | |
76 | 0 | parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
77 | 0 | } |
78 | 0 | } |
79 | | |
80 | | /// Parse till certain characters are met. |
81 | | /// |
82 | | /// The parser will return the longest slice till one of the characters of the combinator's argument are met. |
83 | | /// |
84 | | /// It doesn't consume the matched character. |
85 | | /// |
86 | | /// It will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met. |
87 | | /// # Example |
88 | | /// ```rust |
89 | | /// # use nom::{Err, error::ErrorKind, Needed, IResult}; |
90 | | /// use nom::bytes::streaming::is_not; |
91 | | /// |
92 | | /// fn not_space(s: &str) -> IResult<&str, &str> { |
93 | | /// is_not(" \t\r\n")(s) |
94 | | /// } |
95 | | /// |
96 | | /// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,"))); |
97 | | /// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes"))); |
98 | | /// assert_eq!(not_space("Nospace"), Err(Err::Incomplete(Needed::new(1)))); |
99 | | /// assert_eq!(not_space(""), Err(Err::Incomplete(Needed::new(1)))); |
100 | | /// ``` |
101 | 0 | pub fn is_not<T, I, Error: ParseError<I>>(arr: T) -> impl FnMut(I) -> IResult<I, I, Error> |
102 | 0 | where |
103 | 0 | I: Input, |
104 | 0 | T: FindToken<<I as Input>::Item>, |
105 | | { |
106 | 0 | let mut parser = super::is_not(arr); |
107 | | |
108 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
109 | 0 | } |
110 | | |
111 | | /// Returns the longest slice of the matches the pattern. |
112 | | /// |
113 | | /// The parser will return the longest slice consisting of the characters in provided in the |
114 | | /// combinator's argument. |
115 | | /// |
116 | | /// # Streaming specific |
117 | | /// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met |
118 | | /// or if the pattern reaches the end of the input. |
119 | | /// # Example |
120 | | /// ```rust |
121 | | /// # use nom::{Err, error::ErrorKind, Needed, IResult}; |
122 | | /// use nom::bytes::streaming::is_a; |
123 | | /// |
124 | | /// fn hex(s: &str) -> IResult<&str, &str> { |
125 | | /// is_a("1234567890ABCDEF")(s) |
126 | | /// } |
127 | | /// |
128 | | /// assert_eq!(hex("123 and voila"), Ok((" and voila", "123"))); |
129 | | /// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF"))); |
130 | | /// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE"))); |
131 | | /// assert_eq!(hex("D15EA5E"), Err(Err::Incomplete(Needed::new(1)))); |
132 | | /// assert_eq!(hex(""), Err(Err::Incomplete(Needed::new(1)))); |
133 | | /// ``` |
134 | 0 | pub fn is_a<T, I, Error: ParseError<I>>(arr: T) -> impl FnMut(I) -> IResult<I, I, Error> |
135 | 0 | where |
136 | 0 | I: Input, |
137 | 0 | T: FindToken<<I as Input>::Item>, |
138 | | { |
139 | 0 | let mut parser = super::is_a(arr); |
140 | | |
141 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
142 | 0 | } |
143 | | |
144 | | /// Returns the longest input slice (if any) that matches the predicate. |
145 | | /// |
146 | | /// The parser will return the longest slice that matches the given predicate *(a function that |
147 | | /// takes the input and returns a bool)*. |
148 | | /// |
149 | | /// # Streaming Specific |
150 | | /// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input. |
151 | | /// # Example |
152 | | /// ```rust |
153 | | /// # use nom::{Err, error::ErrorKind, Needed, IResult}; |
154 | | /// use nom::bytes::streaming::take_while; |
155 | | /// use nom::AsChar; |
156 | | /// |
157 | | /// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { |
158 | | /// take_while(AsChar::is_alpha)(s) |
159 | | /// } |
160 | | /// |
161 | | /// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); |
162 | | /// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..]))); |
163 | | /// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); |
164 | | /// assert_eq!(alpha(b""), Err(Err::Incomplete(Needed::new(1)))); |
165 | | /// ``` |
166 | 0 | pub fn take_while<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error> |
167 | 0 | where |
168 | 0 | I: Input, |
169 | 0 | F: Fn(<I as Input>::Item) -> bool, |
170 | | { |
171 | 0 | let mut parser = super::take_while(cond); |
172 | | |
173 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
174 | 0 | } |
175 | | |
176 | | /// Returns the longest (at least 1) input slice that matches the predicate. |
177 | | /// |
178 | | /// The parser will return the longest slice that matches the given predicate *(a function that |
179 | | /// takes the input and returns a bool)*. |
180 | | /// |
181 | | /// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met. |
182 | | /// |
183 | | /// # Streaming Specific |
184 | | /// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` or if the pattern reaches the end of the input. |
185 | | /// |
186 | | /// # Example |
187 | | /// ```rust |
188 | | /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; |
189 | | /// use nom::bytes::streaming::take_while1; |
190 | | /// use nom::AsChar; |
191 | | /// |
192 | | /// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { |
193 | | /// take_while1(AsChar::is_alpha)(s) |
194 | | /// } |
195 | | /// |
196 | | /// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); |
197 | | /// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); |
198 | | /// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1)))); |
199 | | /// ``` |
200 | 0 | pub fn take_while1<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error> |
201 | 0 | where |
202 | 0 | I: Input, |
203 | 0 | F: Fn(<I as Input>::Item) -> bool, |
204 | | { |
205 | 0 | let mut parser = super::take_while1(cond); |
206 | | |
207 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
208 | 0 | } |
209 | | |
210 | | /// Returns the longest (m <= len <= n) input slice that matches the predicate. |
211 | | /// |
212 | | /// The parser will return the longest slice that matches the given predicate *(a function that |
213 | | /// takes the input and returns a bool)*. |
214 | | /// |
215 | | /// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met. |
216 | | /// # Streaming Specific |
217 | | /// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short. |
218 | | /// |
219 | | /// # Example |
220 | | /// ```rust |
221 | | /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; |
222 | | /// use nom::bytes::streaming::take_while_m_n; |
223 | | /// use nom::AsChar; |
224 | | /// |
225 | | /// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { |
226 | | /// take_while_m_n(3, 6, AsChar::is_alpha)(s) |
227 | | /// } |
228 | | /// |
229 | | /// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); |
230 | | /// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..]))); |
231 | | /// assert_eq!(short_alpha(b"latin"), Err(Err::Incomplete(Needed::new(1)))); |
232 | | /// assert_eq!(short_alpha(b"ed"), Err(Err::Incomplete(Needed::new(1)))); |
233 | | /// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN)))); |
234 | | /// ``` |
235 | 0 | pub fn take_while_m_n<F, I, Error: ParseError<I>>( |
236 | 0 | m: usize, |
237 | 0 | n: usize, |
238 | 0 | cond: F, |
239 | 0 | ) -> impl FnMut(I) -> IResult<I, I, Error> |
240 | 0 | where |
241 | 0 | I: Input, |
242 | 0 | F: Fn(<I as Input>::Item) -> bool, |
243 | | { |
244 | 0 | let mut parser = super::take_while_m_n(m, n, cond); |
245 | | |
246 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
247 | 0 | } |
248 | | |
249 | | /// Returns the longest input slice (if any) till a predicate is met. |
250 | | /// |
251 | | /// The parser will return the longest slice till the given predicate *(a function that |
252 | | /// takes the input and returns a bool)*. |
253 | | /// |
254 | | /// # Streaming Specific |
255 | | /// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the |
256 | | /// end of input or if there was not match. |
257 | | /// |
258 | | /// # Example |
259 | | /// ```rust |
260 | | /// # use nom::{Err, error::ErrorKind, Needed, IResult}; |
261 | | /// use nom::bytes::streaming::take_till; |
262 | | /// |
263 | | /// fn till_colon(s: &str) -> IResult<&str, &str> { |
264 | | /// take_till(|c| c == ':')(s) |
265 | | /// } |
266 | | /// |
267 | | /// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); |
268 | | /// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed |
269 | | /// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); |
270 | | /// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); |
271 | | /// ``` |
272 | | #[allow(clippy::redundant_closure)] |
273 | 0 | pub fn take_till<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error> |
274 | 0 | where |
275 | 0 | I: Input, |
276 | 0 | F: Fn(<I as Input>::Item) -> bool, |
277 | | { |
278 | 0 | let mut parser = super::take_till(cond); |
279 | | |
280 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
281 | 0 | } |
282 | | |
283 | | /// Returns the longest (at least 1) input slice till a predicate is met. |
284 | | /// |
285 | | /// The parser will return the longest slice till the given predicate *(a function that |
286 | | /// takes the input and returns a bool)*. |
287 | | /// |
288 | | /// # Streaming Specific |
289 | | /// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the |
290 | | /// end of input or if there was not match. |
291 | | /// # Example |
292 | | /// ```rust |
293 | | /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; |
294 | | /// use nom::bytes::streaming::take_till1; |
295 | | /// |
296 | | /// fn till_colon(s: &str) -> IResult<&str, &str> { |
297 | | /// take_till1(|c| c == ':')(s) |
298 | | /// } |
299 | | /// |
300 | | /// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); |
301 | | /// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1)))); |
302 | | /// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); |
303 | | /// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); |
304 | | /// ``` |
305 | | #[allow(clippy::redundant_closure)] |
306 | 0 | pub fn take_till1<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error> |
307 | 0 | where |
308 | 0 | I: Input, |
309 | 0 | F: Fn(<I as Input>::Item) -> bool, |
310 | | { |
311 | 0 | let mut parser = super::take_till1(cond); |
312 | | |
313 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
314 | 0 | } |
315 | | |
316 | | /// Returns an input slice containing the first N input elements (Input[..N]). |
317 | | /// |
318 | | /// # Streaming Specific |
319 | | /// *Streaming version* if the input has less than N elements, `take` will |
320 | | /// return a `Err::Incomplete(Needed::new(M))` where M is the number of |
321 | | /// additional bytes the parser would need to succeed. |
322 | | /// It is well defined for `&[u8]` as the number of elements is the byte size, |
323 | | /// but for types like `&str`, we cannot know how many bytes correspond for |
324 | | /// the next few chars, so the result will be `Err::Incomplete(Needed::Unknown)` |
325 | | /// |
326 | | /// # Example |
327 | | /// ```rust |
328 | | /// # use nom::{Err, error::ErrorKind, Needed, IResult}; |
329 | | /// use nom::bytes::streaming::take; |
330 | | /// |
331 | | /// fn take6(s: &str) -> IResult<&str, &str> { |
332 | | /// take(6usize)(s) |
333 | | /// } |
334 | | /// |
335 | | /// assert_eq!(take6("1234567"), Ok(("7", "123456"))); |
336 | | /// assert_eq!(take6("things"), Ok(("", "things"))); |
337 | | /// assert_eq!(take6("short"), Err(Err::Incomplete(Needed::Unknown))); |
338 | | /// ``` |
339 | 0 | pub fn take<C, I, Error: ParseError<I>>(count: C) -> impl FnMut(I) -> IResult<I, I, Error> |
340 | 0 | where |
341 | 0 | I: Input, |
342 | 0 | C: ToUsize, |
343 | | { |
344 | 0 | let mut parser = super::take(count); |
345 | | |
346 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
347 | 0 | } |
348 | | |
349 | | /// Returns the input slice up to the first occurrence of the pattern. |
350 | | /// |
351 | | /// It doesn't consume the pattern. |
352 | | /// |
353 | | /// # Streaming Specific |
354 | | /// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't |
355 | | /// contain the pattern or if the input is smaller than the pattern. |
356 | | /// # Example |
357 | | /// ```rust |
358 | | /// # use nom::{Err, error::ErrorKind, Needed, IResult}; |
359 | | /// use nom::bytes::streaming::take_until; |
360 | | /// |
361 | | /// fn until_eof(s: &str) -> IResult<&str, &str> { |
362 | | /// take_until("eof")(s) |
363 | | /// } |
364 | | /// |
365 | | /// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); |
366 | | /// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown))); |
367 | | /// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown))); |
368 | | /// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); |
369 | | /// ``` |
370 | 0 | pub fn take_until<T, I, Error: ParseError<I>>(tag: T) -> impl FnMut(I) -> IResult<I, I, Error> |
371 | 0 | where |
372 | 0 | I: Input + FindSubstring<T>, |
373 | 0 | T: Clone, |
374 | | { |
375 | 0 | let mut parser = super::take_until(tag); |
376 | | |
377 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
378 | 0 | } |
379 | | |
380 | | /// Returns the non empty input slice up to the first occurrence of the pattern. |
381 | | /// |
382 | | /// It doesn't consume the pattern. |
383 | | /// |
384 | | /// # Streaming Specific |
385 | | /// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't |
386 | | /// contain the pattern or if the input is smaller than the pattern. |
387 | | /// # Example |
388 | | /// ```rust |
389 | | /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; |
390 | | /// use nom::bytes::streaming::take_until1; |
391 | | /// |
392 | | /// fn until_eof(s: &str) -> IResult<&str, &str> { |
393 | | /// take_until1("eof")(s) |
394 | | /// } |
395 | | /// |
396 | | /// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); |
397 | | /// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown))); |
398 | | /// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown))); |
399 | | /// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); |
400 | | /// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil)))); |
401 | | /// ``` |
402 | 0 | pub fn take_until1<T, I, Error: ParseError<I>>(tag: T) -> impl FnMut(I) -> IResult<I, I, Error> |
403 | 0 | where |
404 | 0 | I: Input + FindSubstring<T>, |
405 | 0 | T: Clone, |
406 | | { |
407 | 0 | let mut parser = super::take_until1(tag); |
408 | | |
409 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
410 | 0 | } |
411 | | |
412 | | /// Matches a byte string with escaped characters. |
413 | | /// |
414 | | /// * The first argument matches the normal characters (it must not accept the control character) |
415 | | /// * The second argument is the control character (like `\` in most languages) |
416 | | /// * The third argument matches the escaped characters |
417 | | /// # Example |
418 | | /// ``` |
419 | | /// # use nom::{Err, error::ErrorKind, Needed, IResult}; |
420 | | /// # use nom::character::complete::digit1; |
421 | | /// use nom::bytes::streaming::escaped; |
422 | | /// use nom::character::streaming::one_of; |
423 | | /// |
424 | | /// fn esc(s: &str) -> IResult<&str, &str> { |
425 | | /// escaped(digit1, '\\', one_of("\"n\\"))(s) |
426 | | /// } |
427 | | /// |
428 | | /// assert_eq!(esc("123;"), Ok((";", "123"))); |
429 | | /// assert_eq!(esc("12\\\"34;"), Ok((";", "12\\\"34"))); |
430 | | /// ``` |
431 | | /// |
432 | 0 | pub fn escaped<I, Error, F, G>( |
433 | 0 | normal: F, |
434 | 0 | control_char: char, |
435 | 0 | escapable: G, |
436 | 0 | ) -> impl FnMut(I) -> IResult<I, I, Error> |
437 | 0 | where |
438 | 0 | I: Input + Clone + crate::traits::Offset, |
439 | 0 | <I as Input>::Item: crate::traits::AsChar, |
440 | 0 | F: Parser<I, Error = Error>, |
441 | 0 | G: Parser<I, Error = Error>, |
442 | 0 | Error: ParseError<I>, |
443 | | { |
444 | 0 | let mut parser = super::escaped(normal, control_char, escapable); |
445 | | |
446 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
447 | 0 | } |
448 | | |
449 | | /// Matches a byte string with escaped characters. |
450 | | /// |
451 | | /// * The first argument matches the normal characters (it must not match the control character) |
452 | | /// * The second argument is the control character (like `\` in most languages) |
453 | | /// * The third argument matches the escaped characters and transforms them |
454 | | /// |
455 | | /// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character) |
456 | | /// |
457 | | /// ``` |
458 | | /// # use nom::{Err, error::ErrorKind, Needed, IResult}; |
459 | | /// # use std::str::from_utf8; |
460 | | /// use nom::bytes::streaming::{escaped_transform, tag}; |
461 | | /// use nom::character::streaming::alpha1; |
462 | | /// use nom::branch::alt; |
463 | | /// use nom::combinator::value; |
464 | | /// |
465 | | /// fn parser(input: &str) -> IResult<&str, String> { |
466 | | /// escaped_transform( |
467 | | /// alpha1, |
468 | | /// '\\', |
469 | | /// alt(( |
470 | | /// value("\\", tag("\\")), |
471 | | /// value("\"", tag("\"")), |
472 | | /// value("\n", tag("n")), |
473 | | /// )) |
474 | | /// )(input) |
475 | | /// } |
476 | | /// |
477 | | /// assert_eq!(parser("ab\\\"cd\""), Ok(("\"", String::from("ab\"cd")))); |
478 | | /// ``` |
479 | | #[cfg(feature = "alloc")] |
480 | | #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] |
481 | 0 | pub fn escaped_transform<I, Error, F, G, O1, O2, ExtendItem, Output>( |
482 | 0 | normal: F, |
483 | 0 | control_char: char, |
484 | 0 | transform: G, |
485 | 0 | ) -> impl FnMut(I) -> IResult<I, Output, Error> |
486 | 0 | where |
487 | 0 | I: Clone + crate::traits::Offset + Input, |
488 | 0 | I: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, |
489 | 0 | O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, |
490 | 0 | O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, |
491 | 0 | <I as Input>::Item: crate::traits::AsChar, |
492 | 0 | F: Parser<I, Output = O1, Error = Error>, |
493 | 0 | G: Parser<I, Output = O2, Error = Error>, |
494 | 0 | Error: ParseError<I>, |
495 | | { |
496 | 0 | let mut parser = super::escaped_transform(normal, control_char, transform); |
497 | | |
498 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i) |
499 | 0 | } |