/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nom-8.0.0/src/character/complete.rs
Line | Count | Source |
1 | | //! Character specific parsers and combinators, complete input version. |
2 | | //! |
3 | | //! Functions recognizing specific characters. |
4 | | |
5 | | use crate::branch::alt; |
6 | | use crate::combinator::opt; |
7 | | use crate::error::ErrorKind; |
8 | | use crate::error::ParseError; |
9 | | use crate::internal::{Err, IResult}; |
10 | | use crate::traits::{AsChar, FindToken, Input}; |
11 | | use crate::traits::{Compare, CompareResult}; |
12 | | use crate::Complete; |
13 | | use crate::Emit; |
14 | | use crate::OutputM; |
15 | | use crate::Parser; |
16 | | |
17 | | /// Recognizes one character. |
18 | | /// |
19 | | /// *Complete version*: Will return an error if there's not enough input data. |
20 | | /// # Example |
21 | | /// |
22 | | /// ``` |
23 | | /// # use nom::{Err, error::{ErrorKind, Error}, IResult}; |
24 | | /// # use nom::character::complete::char; |
25 | | /// fn parser(i: &str) -> IResult<&str, char> { |
26 | | /// char('a')(i) |
27 | | /// } |
28 | | /// assert_eq!(parser("abc"), Ok(("bc", 'a'))); |
29 | | /// assert_eq!(parser(" abc"), Err(Err::Error(Error::new(" abc", ErrorKind::Char)))); |
30 | | /// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char)))); |
31 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char)))); |
32 | | /// ``` |
33 | 0 | pub fn char<I, Error: ParseError<I>>(c: char) -> impl FnMut(I) -> IResult<I, char, Error> |
34 | 0 | where |
35 | 0 | I: Input, |
36 | 0 | <I as Input>::Item: AsChar, |
37 | | { |
38 | 0 | let mut parser = super::char(c); |
39 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i) Unexecuted instantiation: nom::character::complete::char::<&str, nom::error::Error<&str>>::{closure#0}Unexecuted instantiation: nom::character::complete::char::<_, _>::{closure#0} |
40 | 0 | } Unexecuted instantiation: nom::character::complete::char::<&str, nom::error::Error<&str>> Unexecuted instantiation: nom::character::complete::char::<_, _> |
41 | | |
42 | | /// Recognizes one character and checks that it satisfies a predicate |
43 | | /// |
44 | | /// *Complete version*: Will return an error if there's not enough input data. |
45 | | /// # Example |
46 | | /// |
47 | | /// ``` |
48 | | /// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult}; |
49 | | /// # use nom::character::complete::satisfy; |
50 | | /// fn parser(i: &str) -> IResult<&str, char> { |
51 | | /// satisfy(|c| c == 'a' || c == 'b')(i) |
52 | | /// } |
53 | | /// assert_eq!(parser("abc"), Ok(("bc", 'a'))); |
54 | | /// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy)))); |
55 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Satisfy)))); |
56 | | /// ``` |
57 | 0 | pub fn satisfy<F, I, Error: ParseError<I>>(predicate: F) -> impl FnMut(I) -> IResult<I, char, Error> |
58 | 0 | where |
59 | 0 | I: Input, |
60 | 0 | <I as Input>::Item: AsChar, |
61 | 0 | F: Fn(char) -> bool, |
62 | | { |
63 | 0 | let mut parser = super::satisfy(predicate); |
64 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i) |
65 | 0 | } |
66 | | |
67 | | /// Recognizes one of the provided characters. |
68 | | /// |
69 | | /// *Complete version*: Will return an error if there's not enough input data. |
70 | | /// # Example |
71 | | /// |
72 | | /// ``` |
73 | | /// # use nom::{Err, error::ErrorKind}; |
74 | | /// # use nom::character::complete::one_of; |
75 | | /// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("abc")("b"), Ok(("", 'b'))); |
76 | | /// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf)))); |
77 | | /// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::OneOf)))); |
78 | | /// ``` |
79 | 0 | pub fn one_of<I, T, Error: ParseError<I>>(list: T) -> impl FnMut(I) -> IResult<I, char, Error> |
80 | 0 | where |
81 | 0 | I: Input, |
82 | 0 | <I as Input>::Item: AsChar, |
83 | 0 | T: FindToken<char>, |
84 | | { |
85 | 0 | let mut parser = super::one_of(list); |
86 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i) |
87 | 0 | } |
88 | | |
89 | | /// Recognizes a character that is not in the provided characters. |
90 | | /// |
91 | | /// *Complete version*: Will return an error if there's not enough input data. |
92 | | /// # Example |
93 | | /// |
94 | | /// ``` |
95 | | /// # use nom::{Err, error::ErrorKind}; |
96 | | /// # use nom::character::complete::none_of; |
97 | | /// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("abc")("z"), Ok(("", 'z'))); |
98 | | /// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf)))); |
99 | | /// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::NoneOf)))); |
100 | | /// ``` |
101 | 0 | pub fn none_of<I, T, Error: ParseError<I>>(list: T) -> impl FnMut(I) -> IResult<I, char, Error> |
102 | 0 | where |
103 | 0 | I: Input, |
104 | 0 | <I as Input>::Item: AsChar, |
105 | 0 | T: FindToken<char>, |
106 | | { |
107 | 0 | let mut parser = super::none_of(list); |
108 | 0 | move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i) |
109 | 0 | } |
110 | | |
111 | | /// Recognizes the string "\r\n". |
112 | | /// |
113 | | /// *Complete version*: Will return an error if there's not enough input data. |
114 | | /// # Example |
115 | | /// |
116 | | /// ``` |
117 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult}; |
118 | | /// # use nom::character::complete::crlf; |
119 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
120 | | /// crlf(input) |
121 | | /// } |
122 | | /// |
123 | | /// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n"))); |
124 | | /// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf)))); |
125 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf)))); |
126 | | /// ``` |
127 | 0 | pub fn crlf<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
128 | 0 | where |
129 | 0 | T: Input, |
130 | 0 | T: Compare<&'static str>, |
131 | | { |
132 | 0 | match input.compare("\r\n") { |
133 | 0 | CompareResult::Ok => Ok(input.take_split(2)), |
134 | | _ => { |
135 | 0 | let e: ErrorKind = ErrorKind::CrLf; |
136 | 0 | Err(Err::Error(E::from_error_kind(input, e))) |
137 | | } |
138 | | } |
139 | 0 | } |
140 | | |
141 | | //FIXME: there's still an incomplete |
142 | | /// Recognizes a string of any char except '\r\n' or '\n'. |
143 | | /// |
144 | | /// *Complete version*: Will return an error if there's not enough input data. |
145 | | /// # Example |
146 | | /// |
147 | | /// ``` |
148 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
149 | | /// # use nom::character::complete::not_line_ending; |
150 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
151 | | /// not_line_ending(input) |
152 | | /// } |
153 | | /// |
154 | | /// assert_eq!(parser("ab\r\nc"), Ok(("\r\nc", "ab"))); |
155 | | /// assert_eq!(parser("ab\nc"), Ok(("\nc", "ab"))); |
156 | | /// assert_eq!(parser("abc"), Ok(("", "abc"))); |
157 | | /// assert_eq!(parser(""), Ok(("", ""))); |
158 | | /// assert_eq!(parser("a\rb\nc"), Err(Err::Error(Error { input: "a\rb\nc", code: ErrorKind::Tag }))); |
159 | | /// assert_eq!(parser("a\rbc"), Err(Err::Error(Error { input: "a\rbc", code: ErrorKind::Tag }))); |
160 | | /// ``` |
161 | 0 | pub fn not_line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
162 | 0 | where |
163 | 0 | T: Input, |
164 | 0 | T: Compare<&'static str>, |
165 | 0 | <T as Input>::Item: AsChar, |
166 | | { |
167 | 0 | match input.position(|item| { |
168 | 0 | let c = item.as_char(); |
169 | 0 | c == '\r' || c == '\n' |
170 | 0 | }) { |
171 | 0 | None => Ok(input.take_split(input.input_len())), |
172 | 0 | Some(index) => { |
173 | 0 | let mut it = input.take_from(index).iter_elements(); |
174 | 0 | let nth = it.next().unwrap().as_char(); |
175 | 0 | if nth == '\r' { |
176 | 0 | let sliced = input.take_from(index); |
177 | 0 | let comp = sliced.compare("\r\n"); |
178 | 0 | match comp { |
179 | | //FIXME: calculate the right index |
180 | 0 | CompareResult::Ok => Ok(input.take_split(index)), |
181 | | _ => { |
182 | 0 | let e: ErrorKind = ErrorKind::Tag; |
183 | 0 | Err(Err::Error(E::from_error_kind(input, e))) |
184 | | } |
185 | | } |
186 | | } else { |
187 | 0 | Ok(input.take_split(index)) |
188 | | } |
189 | | } |
190 | | } |
191 | 0 | } |
192 | | |
193 | | /// Recognizes an end of line (both '\n' and '\r\n'). |
194 | | /// |
195 | | /// *Complete version*: Will return an error if there's not enough input data. |
196 | | /// # Example |
197 | | /// |
198 | | /// ``` |
199 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
200 | | /// # use nom::character::complete::line_ending; |
201 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
202 | | /// line_ending(input) |
203 | | /// } |
204 | | /// |
205 | | /// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n"))); |
206 | | /// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf)))); |
207 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf)))); |
208 | | /// ``` |
209 | 0 | pub fn line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
210 | 0 | where |
211 | 0 | T: Input, |
212 | 0 | T: Compare<&'static str>, |
213 | | { |
214 | 0 | match input.compare("\n") { |
215 | 0 | CompareResult::Ok => Ok(input.take_split(1)), |
216 | 0 | CompareResult::Incomplete => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), |
217 | 0 | CompareResult::Error => match input.compare("\r\n") { |
218 | 0 | CompareResult::Ok => Ok(input.take_split(2)), |
219 | 0 | _ => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))), |
220 | | }, |
221 | | } |
222 | 0 | } Unexecuted instantiation: nom::character::complete::line_ending::<&str, nom::error::Error<&str>> Unexecuted instantiation: nom::character::complete::line_ending::<_, _> |
223 | | |
224 | | /// Matches a newline character '\n'. |
225 | | /// |
226 | | /// *Complete version*: Will return an error if there's not enough input data. |
227 | | /// # Example |
228 | | /// |
229 | | /// ``` |
230 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
231 | | /// # use nom::character::complete::newline; |
232 | | /// fn parser(input: &str) -> IResult<&str, char> { |
233 | | /// newline(input) |
234 | | /// } |
235 | | /// |
236 | | /// assert_eq!(parser("\nc"), Ok(("c", '\n'))); |
237 | | /// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char)))); |
238 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char)))); |
239 | | /// ``` |
240 | 0 | pub fn newline<I, Error: ParseError<I>>(input: I) -> IResult<I, char, Error> |
241 | 0 | where |
242 | 0 | I: Input, |
243 | 0 | <I as Input>::Item: AsChar, |
244 | | { |
245 | 0 | char('\n')(input) |
246 | 0 | } |
247 | | |
248 | | /// Matches a tab character '\t'. |
249 | | /// |
250 | | /// *Complete version*: Will return an error if there's not enough input data. |
251 | | /// # Example |
252 | | /// |
253 | | /// ``` |
254 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
255 | | /// # use nom::character::complete::tab; |
256 | | /// fn parser(input: &str) -> IResult<&str, char> { |
257 | | /// tab(input) |
258 | | /// } |
259 | | /// |
260 | | /// assert_eq!(parser("\tc"), Ok(("c", '\t'))); |
261 | | /// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char)))); |
262 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char)))); |
263 | | /// ``` |
264 | 0 | pub fn tab<I, Error: ParseError<I>>(input: I) -> IResult<I, char, Error> |
265 | 0 | where |
266 | 0 | I: Input, |
267 | 0 | <I as Input>::Item: AsChar, |
268 | | { |
269 | 0 | char('\t')(input) |
270 | 0 | } |
271 | | |
272 | | /// Matches one byte as a character. Note that the input type will |
273 | | /// accept a `str`, but not a `&[u8]`, unlike many other nom parsers. |
274 | | /// |
275 | | /// *Complete version*: Will return an error if there's not enough input data. |
276 | | /// # Example |
277 | | /// |
278 | | /// ``` |
279 | | /// # use nom::{character::complete::anychar, Err, error::{Error, ErrorKind}, IResult}; |
280 | | /// fn parser(input: &str) -> IResult<&str, char> { |
281 | | /// anychar(input) |
282 | | /// } |
283 | | /// |
284 | | /// assert_eq!(parser("abc"), Ok(("bc",'a'))); |
285 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Eof)))); |
286 | | /// ``` |
287 | 0 | pub fn anychar<T, E: ParseError<T>>(input: T) -> IResult<T, char, E> |
288 | 0 | where |
289 | 0 | T: Input, |
290 | 0 | <T as Input>::Item: AsChar, |
291 | | { |
292 | 0 | let mut it = input.iter_elements(); |
293 | 0 | match it.next() { |
294 | 0 | None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))), |
295 | 0 | Some(c) => Ok((input.take_from(c.len()), c.as_char())), |
296 | | } |
297 | 0 | } |
298 | | |
299 | | /// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z |
300 | | /// |
301 | | /// *Complete version*: Will return the whole input if no terminating token is found (a non |
302 | | /// alphabetic character). |
303 | | /// # Example |
304 | | /// |
305 | | /// ``` |
306 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
307 | | /// # use nom::character::complete::alpha0; |
308 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
309 | | /// alpha0(input) |
310 | | /// } |
311 | | /// |
312 | | /// assert_eq!(parser("ab1c"), Ok(("1c", "ab"))); |
313 | | /// assert_eq!(parser("1c"), Ok(("1c", ""))); |
314 | | /// assert_eq!(parser(""), Ok(("", ""))); |
315 | | /// ``` |
316 | 0 | pub fn alpha0<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
317 | 0 | where |
318 | 0 | T: Input, |
319 | 0 | <T as Input>::Item: AsChar, |
320 | | { |
321 | 0 | input.split_at_position_complete(|item| !item.is_alpha()) |
322 | 0 | } |
323 | | |
324 | | /// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z |
325 | | /// |
326 | | /// *Complete version*: Will return an error if there's not enough input data, |
327 | | /// or the whole input if no terminating token is found (a non alphabetic character). |
328 | | /// # Example |
329 | | /// |
330 | | /// ``` |
331 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
332 | | /// # use nom::character::complete::alpha1; |
333 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
334 | | /// alpha1(input) |
335 | | /// } |
336 | | /// |
337 | | /// assert_eq!(parser("aB1c"), Ok(("1c", "aB"))); |
338 | | /// assert_eq!(parser("1c"), Err(Err::Error(Error::new("1c", ErrorKind::Alpha)))); |
339 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Alpha)))); |
340 | | /// ``` |
341 | 0 | pub fn alpha1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
342 | 0 | where |
343 | 0 | T: Input, |
344 | 0 | <T as Input>::Item: AsChar, |
345 | | { |
346 | 0 | input.split_at_position1_complete(|item| !item.is_alpha(), ErrorKind::Alpha) |
347 | 0 | } |
348 | | |
349 | | /// Recognizes zero or more ASCII numerical characters: 0-9 |
350 | | /// |
351 | | /// *Complete version*: Will return an error if there's not enough input data, |
352 | | /// or the whole input if no terminating token is found (a non digit character). |
353 | | /// # Example |
354 | | /// |
355 | | /// ``` |
356 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
357 | | /// # use nom::character::complete::digit0; |
358 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
359 | | /// digit0(input) |
360 | | /// } |
361 | | /// |
362 | | /// assert_eq!(parser("21c"), Ok(("c", "21"))); |
363 | | /// assert_eq!(parser("21"), Ok(("", "21"))); |
364 | | /// assert_eq!(parser("a21c"), Ok(("a21c", ""))); |
365 | | /// assert_eq!(parser(""), Ok(("", ""))); |
366 | | /// ``` |
367 | 0 | pub fn digit0<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
368 | 0 | where |
369 | 0 | T: Input, |
370 | 0 | <T as Input>::Item: AsChar, |
371 | | { |
372 | 0 | input.split_at_position_complete(|item| !item.is_dec_digit()) |
373 | 0 | } |
374 | | |
375 | | /// Recognizes one or more ASCII numerical characters: 0-9 |
376 | | /// |
377 | | /// *Complete version*: Will return an error if there's not enough input data, |
378 | | /// or the whole input if no terminating token is found (a non digit character). |
379 | | /// # Example |
380 | | /// |
381 | | /// ``` |
382 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
383 | | /// # use nom::character::complete::digit1; |
384 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
385 | | /// digit1(input) |
386 | | /// } |
387 | | /// |
388 | | /// assert_eq!(parser("21c"), Ok(("c", "21"))); |
389 | | /// assert_eq!(parser("c1"), Err(Err::Error(Error::new("c1", ErrorKind::Digit)))); |
390 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Digit)))); |
391 | | /// ``` |
392 | | /// |
393 | | /// ## Parsing an integer |
394 | | /// You can use `digit1` in combination with [`map_res`] to parse an integer: |
395 | | /// |
396 | | /// ``` |
397 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed, Parser}; |
398 | | /// # use nom::combinator::map_res; |
399 | | /// # use nom::character::complete::digit1; |
400 | | /// fn parser(input: &str) -> IResult<&str, u32> { |
401 | | /// map_res(digit1, str::parse).parse(input) |
402 | | /// } |
403 | | /// |
404 | | /// assert_eq!(parser("416"), Ok(("", 416))); |
405 | | /// assert_eq!(parser("12b"), Ok(("b", 12))); |
406 | | /// assert!(parser("b").is_err()); |
407 | | /// ``` |
408 | | /// |
409 | | /// [`map_res`]: crate::combinator::map_res |
410 | 0 | pub fn digit1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
411 | 0 | where |
412 | 0 | T: Input, |
413 | 0 | <T as Input>::Item: AsChar, |
414 | | { |
415 | 0 | input.split_at_position1_complete(|item| !item.is_dec_digit(), ErrorKind::Digit) Unexecuted instantiation: nom::character::complete::digit1::<&str, nom::error::Error<&str>>::{closure#0}Unexecuted instantiation: nom::character::complete::digit1::<_, _>::{closure#0} |
416 | 0 | } Unexecuted instantiation: nom::character::complete::digit1::<&str, nom::error::Error<&str>> Unexecuted instantiation: nom::character::complete::digit1::<_, _> |
417 | | |
418 | | /// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f |
419 | | /// |
420 | | /// *Complete version*: Will return the whole input if no terminating token is found (a non hexadecimal digit character). |
421 | | /// # Example |
422 | | /// |
423 | | /// ``` |
424 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
425 | | /// # use nom::character::complete::hex_digit0; |
426 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
427 | | /// hex_digit0(input) |
428 | | /// } |
429 | | /// |
430 | | /// assert_eq!(parser("21cZ"), Ok(("Z", "21c"))); |
431 | | /// assert_eq!(parser("Z21c"), Ok(("Z21c", ""))); |
432 | | /// assert_eq!(parser(""), Ok(("", ""))); |
433 | | /// ``` |
434 | 0 | pub fn hex_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
435 | 0 | where |
436 | 0 | T: Input, |
437 | 0 | <T as Input>::Item: AsChar, |
438 | | { |
439 | 0 | input.split_at_position_complete(|item| !item.is_hex_digit()) |
440 | 0 | } |
441 | | /// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f |
442 | | /// |
443 | | /// *Complete version*: Will return an error if there's not enough input data, |
444 | | /// or the whole input if no terminating token is found (a non hexadecimal digit character). |
445 | | /// # Example |
446 | | /// |
447 | | /// ``` |
448 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
449 | | /// # use nom::character::complete::hex_digit1; |
450 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
451 | | /// hex_digit1(input) |
452 | | /// } |
453 | | /// |
454 | | /// assert_eq!(parser("21cZ"), Ok(("Z", "21c"))); |
455 | | /// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::HexDigit)))); |
456 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::HexDigit)))); |
457 | | /// ``` |
458 | 0 | pub fn hex_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
459 | 0 | where |
460 | 0 | T: Input, |
461 | 0 | <T as Input>::Item: AsChar, |
462 | | { |
463 | 0 | input.split_at_position1_complete(|item| !item.is_hex_digit(), ErrorKind::HexDigit) |
464 | 0 | } |
465 | | |
466 | | /// Recognizes zero or more octal characters: 0-7 |
467 | | /// |
468 | | /// *Complete version*: Will return the whole input if no terminating token is found (a non octal |
469 | | /// digit character). |
470 | | /// # Example |
471 | | /// |
472 | | /// ``` |
473 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
474 | | /// # use nom::character::complete::oct_digit0; |
475 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
476 | | /// oct_digit0(input) |
477 | | /// } |
478 | | /// |
479 | | /// assert_eq!(parser("21cZ"), Ok(("cZ", "21"))); |
480 | | /// assert_eq!(parser("Z21c"), Ok(("Z21c", ""))); |
481 | | /// assert_eq!(parser(""), Ok(("", ""))); |
482 | | /// ``` |
483 | 0 | pub fn oct_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
484 | 0 | where |
485 | 0 | T: Input, |
486 | 0 | <T as Input>::Item: AsChar, |
487 | | { |
488 | 0 | input.split_at_position_complete(|item| !item.is_oct_digit()) |
489 | 0 | } |
490 | | |
491 | | /// Recognizes one or more octal characters: 0-7 |
492 | | /// |
493 | | /// *Complete version*: Will return an error if there's not enough input data, |
494 | | /// or the whole input if no terminating token is found (a non octal digit character). |
495 | | /// # Example |
496 | | /// |
497 | | /// ``` |
498 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
499 | | /// # use nom::character::complete::oct_digit1; |
500 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
501 | | /// oct_digit1(input) |
502 | | /// } |
503 | | /// |
504 | | /// assert_eq!(parser("21cZ"), Ok(("cZ", "21"))); |
505 | | /// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::OctDigit)))); |
506 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::OctDigit)))); |
507 | | /// ``` |
508 | 0 | pub fn oct_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
509 | 0 | where |
510 | 0 | T: Input, |
511 | 0 | <T as Input>::Item: AsChar, |
512 | | { |
513 | 0 | input.split_at_position1_complete(|item| !item.is_oct_digit(), ErrorKind::OctDigit) |
514 | 0 | } |
515 | | |
516 | | /// Recognizes zero or more binary characters: 0-1 |
517 | | /// |
518 | | /// *Complete version*: Will return the whole input if no terminating token is found (a non binary |
519 | | /// digit character). |
520 | | /// # Example |
521 | | /// |
522 | | /// ``` |
523 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
524 | | /// # use nom::character::complete::bin_digit0; |
525 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
526 | | /// bin_digit0(input) |
527 | | /// } |
528 | | /// |
529 | | /// assert_eq!(parser("013a"), Ok(("3a", "01"))); |
530 | | /// assert_eq!(parser("a013"), Ok(("a013", ""))); |
531 | | /// assert_eq!(parser(""), Ok(("", ""))); |
532 | | /// ``` |
533 | 0 | pub fn bin_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
534 | 0 | where |
535 | 0 | T: Input, |
536 | 0 | <T as Input>::Item: AsChar, |
537 | | { |
538 | 0 | input.split_at_position_complete(|item| !item.is_bin_digit()) |
539 | 0 | } |
540 | | |
541 | | /// Recognizes one or more binary characters: 0-1 |
542 | | /// |
543 | | /// *Complete version*: Will return an error if there's not enough input data, |
544 | | /// or the whole input if no terminating token is found (a non binary digit character). |
545 | | /// # Example |
546 | | /// |
547 | | /// ``` |
548 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
549 | | /// # use nom::character::complete::bin_digit1; |
550 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
551 | | /// bin_digit1(input) |
552 | | /// } |
553 | | /// |
554 | | /// assert_eq!(parser("013a"), Ok(("3a", "01"))); |
555 | | /// assert_eq!(parser("a013"), Err(Err::Error(Error::new("a013", ErrorKind::BinDigit)))); |
556 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::BinDigit)))); |
557 | | /// ``` |
558 | 0 | pub fn bin_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
559 | 0 | where |
560 | 0 | T: Input, |
561 | 0 | <T as Input>::Item: AsChar, |
562 | | { |
563 | 0 | input.split_at_position1_complete(|item| !item.is_bin_digit(), ErrorKind::BinDigit) |
564 | 0 | } |
565 | | |
566 | | /// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z |
567 | | /// |
568 | | /// *Complete version*: Will return the whole input if no terminating token is found (a non |
569 | | /// alphanumerical character). |
570 | | /// # Example |
571 | | /// |
572 | | /// ``` |
573 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
574 | | /// # use nom::character::complete::alphanumeric0; |
575 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
576 | | /// alphanumeric0(input) |
577 | | /// } |
578 | | /// |
579 | | /// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ"))); |
580 | | /// assert_eq!(parser("&Z21c"), Ok(("&Z21c", ""))); |
581 | | /// assert_eq!(parser(""), Ok(("", ""))); |
582 | | /// ``` |
583 | 0 | pub fn alphanumeric0<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
584 | 0 | where |
585 | 0 | T: Input, |
586 | 0 | <T as Input>::Item: AsChar, |
587 | | { |
588 | 0 | input.split_at_position_complete(|item| !item.is_alphanum()) |
589 | 0 | } |
590 | | |
591 | | /// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z |
592 | | /// |
593 | | /// *Complete version*: Will return an error if there's not enough input data, |
594 | | /// or the whole input if no terminating token is found (a non alphanumerical character). |
595 | | /// # Example |
596 | | /// |
597 | | /// ``` |
598 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
599 | | /// # use nom::character::complete::alphanumeric1; |
600 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
601 | | /// alphanumeric1(input) |
602 | | /// } |
603 | | /// |
604 | | /// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ"))); |
605 | | /// assert_eq!(parser("&H2"), Err(Err::Error(Error::new("&H2", ErrorKind::AlphaNumeric)))); |
606 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::AlphaNumeric)))); |
607 | | /// ``` |
608 | 0 | pub fn alphanumeric1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
609 | 0 | where |
610 | 0 | T: Input, |
611 | 0 | <T as Input>::Item: AsChar, |
612 | | { |
613 | 0 | input.split_at_position1_complete(|item| !item.is_alphanum(), ErrorKind::AlphaNumeric) |
614 | 0 | } |
615 | | |
616 | | /// Recognizes zero or more spaces and tabs. |
617 | | /// |
618 | | /// *Complete version*: Will return the whole input if no terminating token is found (a non space |
619 | | /// character). |
620 | | /// # Example |
621 | | /// |
622 | | /// ``` |
623 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
624 | | /// # use nom::character::complete::space0; |
625 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
626 | | /// space0(input) |
627 | | /// } |
628 | | /// |
629 | | /// assert_eq!(parser(" \t21c"), Ok(("21c", " \t"))); |
630 | | /// assert_eq!(parser("Z21c"), Ok(("Z21c", ""))); |
631 | | /// assert_eq!(parser(""), Ok(("", ""))); |
632 | | /// ``` |
633 | 0 | pub fn space0<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
634 | 0 | where |
635 | 0 | T: Input, |
636 | 0 | <T as Input>::Item: AsChar + Clone, |
637 | | { |
638 | 0 | input.split_at_position_complete(|item| { |
639 | 0 | let c = item.as_char(); |
640 | 0 | !(c == ' ' || c == '\t') |
641 | 0 | }) Unexecuted instantiation: nom::character::complete::space0::<&str, nom::error::Error<&str>>::{closure#0}Unexecuted instantiation: nom::character::complete::space0::<_, _>::{closure#0} |
642 | 0 | } Unexecuted instantiation: nom::character::complete::space0::<&str, nom::error::Error<&str>> Unexecuted instantiation: nom::character::complete::space0::<_, _> |
643 | | |
644 | | /// Recognizes one or more spaces and tabs. |
645 | | /// |
646 | | /// *Complete version*: Will return an error if there's not enough input data, |
647 | | /// or the whole input if no terminating token is found (a non space character). |
648 | | /// # Example |
649 | | /// |
650 | | /// ``` |
651 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
652 | | /// # use nom::character::complete::space1; |
653 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
654 | | /// space1(input) |
655 | | /// } |
656 | | /// |
657 | | /// assert_eq!(parser(" \t21c"), Ok(("21c", " \t"))); |
658 | | /// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::Space)))); |
659 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Space)))); |
660 | | /// ``` |
661 | 0 | pub fn space1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
662 | 0 | where |
663 | 0 | T: Input, |
664 | 0 | <T as Input>::Item: AsChar, |
665 | | { |
666 | 0 | input.split_at_position1_complete( |
667 | 0 | |item| { |
668 | 0 | let c = item.as_char(); |
669 | 0 | !(c == ' ' || c == '\t') |
670 | 0 | }, Unexecuted instantiation: nom::character::complete::space1::<&str, nom::error::Error<&str>>::{closure#0}Unexecuted instantiation: nom::character::complete::space1::<_, _>::{closure#0} |
671 | 0 | ErrorKind::Space, |
672 | | ) |
673 | 0 | } Unexecuted instantiation: nom::character::complete::space1::<&str, nom::error::Error<&str>> Unexecuted instantiation: nom::character::complete::space1::<_, _> |
674 | | |
675 | | /// Recognizes zero or more spaces, tabs, carriage returns and line feeds. |
676 | | /// |
677 | | /// *Complete version*: will return the whole input if no terminating token is found (a non space |
678 | | /// character). |
679 | | /// # Example |
680 | | /// |
681 | | /// ``` |
682 | | /// # use nom::{Err, error::ErrorKind, IResult, Needed}; |
683 | | /// # use nom::character::complete::multispace0; |
684 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
685 | | /// multispace0(input) |
686 | | /// } |
687 | | /// |
688 | | /// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); |
689 | | /// assert_eq!(parser("Z21c"), Ok(("Z21c", ""))); |
690 | | /// assert_eq!(parser(""), Ok(("", ""))); |
691 | | /// ``` |
692 | 0 | pub fn multispace0<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
693 | 0 | where |
694 | 0 | T: Input, |
695 | 0 | <T as Input>::Item: AsChar, |
696 | | { |
697 | 0 | input.split_at_position_complete(|item| { |
698 | 0 | let c = item.as_char(); |
699 | 0 | !(c == ' ' || c == '\t' || c == '\r' || c == '\n') |
700 | 0 | }) Unexecuted instantiation: nom::character::complete::multispace0::<&str, nom::error::Error<&str>>::{closure#0}Unexecuted instantiation: nom::character::complete::multispace0::<_, _>::{closure#0} |
701 | 0 | } Unexecuted instantiation: nom::character::complete::multispace0::<&str, nom::error::Error<&str>> Unexecuted instantiation: nom::character::complete::multispace0::<_, _> |
702 | | |
703 | | /// Recognizes one or more spaces, tabs, carriage returns and line feeds. |
704 | | /// |
705 | | /// *Complete version*: will return an error if there's not enough input data, |
706 | | /// or the whole input if no terminating token is found (a non space character). |
707 | | /// # Example |
708 | | /// |
709 | | /// ``` |
710 | | /// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed}; |
711 | | /// # use nom::character::complete::multispace1; |
712 | | /// fn parser(input: &str) -> IResult<&str, &str> { |
713 | | /// multispace1(input) |
714 | | /// } |
715 | | /// |
716 | | /// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); |
717 | | /// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::MultiSpace)))); |
718 | | /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::MultiSpace)))); |
719 | | /// ``` |
720 | 0 | pub fn multispace1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
721 | 0 | where |
722 | 0 | T: Input, |
723 | 0 | <T as Input>::Item: AsChar, |
724 | | { |
725 | 0 | input.split_at_position1_complete( |
726 | 0 | |item| { |
727 | 0 | let c = item.as_char(); |
728 | 0 | !(c == ' ' || c == '\t' || c == '\r' || c == '\n') |
729 | 0 | }, Unexecuted instantiation: nom::character::complete::multispace1::<&str, nom::error::Error<&str>>::{closure#0}Unexecuted instantiation: nom::character::complete::multispace1::<_, _>::{closure#0} |
730 | 0 | ErrorKind::MultiSpace, |
731 | | ) |
732 | 0 | } Unexecuted instantiation: nom::character::complete::multispace1::<&str, nom::error::Error<&str>> Unexecuted instantiation: nom::character::complete::multispace1::<_, _> |
733 | | |
734 | 0 | pub(crate) fn sign<T, E: ParseError<T>>(input: T) -> IResult<T, bool, E> |
735 | 0 | where |
736 | 0 | T: Clone + Input, |
737 | 0 | T: for<'a> Compare<&'a [u8]>, |
738 | | { |
739 | | use crate::bytes::complete::tag; |
740 | | use crate::combinator::value; |
741 | | |
742 | 0 | let (i, opt_sign) = opt(alt(( |
743 | 0 | value(false, tag(&b"-"[..])), |
744 | 0 | value(true, tag(&b"+"[..])), |
745 | 0 | ))) |
746 | 0 | .parse(input)?; |
747 | 0 | let sign = opt_sign.unwrap_or(true); |
748 | | |
749 | 0 | Ok((i, sign)) |
750 | 0 | } |
751 | | |
752 | | #[doc(hidden)] |
753 | | macro_rules! ints { |
754 | | ($($t:tt)+) => { |
755 | | $( |
756 | | /// will parse a number in text form to a number |
757 | | /// |
758 | | /// *Complete version*: can parse until the end of input. |
759 | 0 | pub fn $t<T, E: ParseError<T>>(input: T) -> IResult<T, $t, E> |
760 | 0 | where |
761 | 0 | T: Input + Clone, |
762 | 0 | <T as Input>::Item: AsChar, |
763 | 0 | T: for <'a> Compare<&'a[u8]>, |
764 | | { |
765 | 0 | let (i, sign) = sign(input.clone())?; |
766 | | |
767 | 0 | if i.input_len() == 0 { |
768 | 0 | return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); |
769 | 0 | } |
770 | | |
771 | 0 | let mut value: $t = 0; |
772 | 0 | if sign { |
773 | 0 | let mut pos = 0; |
774 | 0 | for c in i.iter_elements() { |
775 | 0 | match c.as_char().to_digit(10) { |
776 | | None => { |
777 | 0 | if pos == 0 { |
778 | 0 | return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); |
779 | | } else { |
780 | 0 | return Ok((i.take_from(pos), value)); |
781 | | } |
782 | | }, |
783 | 0 | Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) {Unexecuted instantiation: nom::character::complete::i8::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::i16::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::i32::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::i64::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::i128::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::isize::<_, _>::{closure#0} |
784 | 0 | None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), |
785 | 0 | Some(v) => { |
786 | 0 | pos += c.len(); |
787 | 0 | value = v; |
788 | 0 | }, |
789 | | } |
790 | | } |
791 | | } |
792 | | } else { |
793 | 0 | let mut pos = 0; |
794 | 0 | for c in i.iter_elements() { |
795 | 0 | match c.as_char().to_digit(10) { |
796 | | None => { |
797 | 0 | if pos == 0 { |
798 | 0 | return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))); |
799 | | } else { |
800 | 0 | return Ok((i.take_from(pos), value)); |
801 | | } |
802 | | }, |
803 | 0 | Some(d) => match value.checked_mul(10).and_then(|v| v.checked_sub(d as $t)) {Unexecuted instantiation: nom::character::complete::i8::<_, _>::{closure#1}Unexecuted instantiation: nom::character::complete::i16::<_, _>::{closure#1}Unexecuted instantiation: nom::character::complete::i32::<_, _>::{closure#1}Unexecuted instantiation: nom::character::complete::i64::<_, _>::{closure#1}Unexecuted instantiation: nom::character::complete::i128::<_, _>::{closure#1}Unexecuted instantiation: nom::character::complete::isize::<_, _>::{closure#1} |
804 | 0 | None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))), |
805 | 0 | Some(v) => { |
806 | 0 | pos += c.len(); |
807 | 0 | value = v; |
808 | 0 | }, |
809 | | } |
810 | | } |
811 | | } |
812 | | } |
813 | | |
814 | 0 | Ok((i.take_from(i.input_len()), value)) |
815 | 0 | } Unexecuted instantiation: nom::character::complete::i8::<_, _> Unexecuted instantiation: nom::character::complete::i16::<_, _> Unexecuted instantiation: nom::character::complete::i32::<_, _> Unexecuted instantiation: nom::character::complete::i64::<_, _> Unexecuted instantiation: nom::character::complete::i128::<_, _> Unexecuted instantiation: nom::character::complete::isize::<_, _> |
816 | | )+ |
817 | | } |
818 | | } |
819 | | |
820 | | ints! { i8 i16 i32 i64 i128 isize } |
821 | | |
822 | | #[doc(hidden)] |
823 | | macro_rules! uints { |
824 | | ($($t:tt)+) => { |
825 | | $( |
826 | | /// will parse a number in text form to a number |
827 | | /// |
828 | | /// *Complete version*: can parse until the end of input. |
829 | 0 | pub fn $t<T, E: ParseError<T>>(input: T) -> IResult<T, $t, E> |
830 | 0 | where |
831 | 0 | T: Input , |
832 | 0 | <T as Input>::Item: AsChar, |
833 | | { |
834 | 0 | let i = input; |
835 | | |
836 | 0 | if i.input_len() == 0 { |
837 | 0 | return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))); |
838 | 0 | } |
839 | | |
840 | 0 | let mut value: $t = 0; |
841 | 0 | let mut pos = 0; |
842 | 0 | for c in i.iter_elements() { |
843 | 0 | match c.as_char().to_digit(10) { |
844 | | None => { |
845 | 0 | if pos == 0 { |
846 | 0 | return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))); |
847 | | } else { |
848 | 0 | return Ok((i.take_from(pos), value)); |
849 | | } |
850 | | }, |
851 | 0 | Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) {Unexecuted instantiation: nom::character::complete::u8::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::u16::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::u32::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::u64::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::u128::<_, _>::{closure#0}Unexecuted instantiation: nom::character::complete::usize::<_, _>::{closure#0} |
852 | 0 | None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))), |
853 | 0 | Some(v) => { |
854 | 0 | pos += c.len(); |
855 | 0 | value = v; |
856 | 0 | }, |
857 | | } |
858 | | } |
859 | | } |
860 | | |
861 | 0 | Ok((i.take_from(i.input_len()), value)) |
862 | 0 | } Unexecuted instantiation: nom::character::complete::u8::<_, _> Unexecuted instantiation: nom::character::complete::u16::<_, _> Unexecuted instantiation: nom::character::complete::u32::<_, _> Unexecuted instantiation: nom::character::complete::u64::<_, _> Unexecuted instantiation: nom::character::complete::u128::<_, _> Unexecuted instantiation: nom::character::complete::usize::<_, _> |
863 | | )+ |
864 | | } |
865 | | } |
866 | | |
867 | | uints! { u8 u16 u32 u64 u128 usize } |
868 | | |
869 | | #[cfg(test)] |
870 | | mod tests { |
871 | | use super::*; |
872 | | use crate::internal::Err; |
873 | | use crate::traits::ParseTo; |
874 | | use crate::Parser; |
875 | | use proptest::prelude::*; |
876 | | |
877 | | macro_rules! assert_parse( |
878 | | ($left: expr, $right: expr) => { |
879 | | let res: $crate::IResult<_, _, (_, ErrorKind)> = $left; |
880 | | assert_eq!(res, $right); |
881 | | }; |
882 | | ); |
883 | | |
884 | | #[test] |
885 | | fn character() { |
886 | | let empty: &[u8] = b""; |
887 | | let a: &[u8] = b"abcd"; |
888 | | let b: &[u8] = b"1234"; |
889 | | let c: &[u8] = b"a123"; |
890 | | let d: &[u8] = "azé12".as_bytes(); |
891 | | let e: &[u8] = b" "; |
892 | | let f: &[u8] = b" ;"; |
893 | | //assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::Size(1)))); |
894 | | assert_parse!(alpha1(a), Ok((empty, a))); |
895 | | assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha)))); |
896 | | assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &b"a"[..]))); |
897 | | assert_eq!( |
898 | | alpha1::<_, (_, ErrorKind)>(d), |
899 | | Ok(("é12".as_bytes(), &b"az"[..])) |
900 | | ); |
901 | | assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit)))); |
902 | | assert_eq!(digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); |
903 | | assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit)))); |
904 | | assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit)))); |
905 | | assert_eq!(hex_digit1::<_, (_, ErrorKind)>(a), Ok((empty, a))); |
906 | | assert_eq!(hex_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); |
907 | | assert_eq!(hex_digit1::<_, (_, ErrorKind)>(c), Ok((empty, c))); |
908 | | assert_eq!( |
909 | | hex_digit1::<_, (_, ErrorKind)>(d), |
910 | | Ok(("zé12".as_bytes(), &b"a"[..])) |
911 | | ); |
912 | | assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit)))); |
913 | | assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit)))); |
914 | | assert_eq!(oct_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); |
915 | | assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); |
916 | | assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); |
917 | | assert_eq!(bin_digit1(a), Err(Err::Error((a, ErrorKind::BinDigit)))); |
918 | | assert_eq!( |
919 | | bin_digit1::<_, (_, ErrorKind)>(b), |
920 | | Ok((&b"234"[..], &b"1"[..])) |
921 | | ); |
922 | | assert_eq!(bin_digit1(c), Err(Err::Error((c, ErrorKind::BinDigit)))); |
923 | | assert_eq!(bin_digit1(d), Err(Err::Error((d, ErrorKind::BinDigit)))); |
924 | | assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(a), Ok((empty, a))); |
925 | | //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); |
926 | | assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(c), Ok((empty, c))); |
927 | | assert_eq!( |
928 | | alphanumeric1::<_, (_, ErrorKind)>(d), |
929 | | Ok(("é12".as_bytes(), &b"az"[..])) |
930 | | ); |
931 | | assert_eq!(space1::<_, (_, ErrorKind)>(e), Ok((empty, e))); |
932 | | assert_eq!(space1::<_, (_, ErrorKind)>(f), Ok((&b";"[..], &b" "[..]))); |
933 | | } |
934 | | |
935 | | #[cfg(feature = "alloc")] |
936 | | #[test] |
937 | | fn character_s() { |
938 | | let empty = ""; |
939 | | let a = "abcd"; |
940 | | let b = "1234"; |
941 | | let c = "a123"; |
942 | | let d = "azé12"; |
943 | | let e = " "; |
944 | | assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Ok((empty, a))); |
945 | | assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha)))); |
946 | | assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], "a"))); |
947 | | assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", "az"))); |
948 | | assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit)))); |
949 | | assert_eq!(digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); |
950 | | assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit)))); |
951 | | assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit)))); |
952 | | assert_eq!(hex_digit1::<_, (_, ErrorKind)>(a), Ok((empty, a))); |
953 | | assert_eq!(hex_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); |
954 | | assert_eq!(hex_digit1::<_, (_, ErrorKind)>(c), Ok((empty, c))); |
955 | | assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", "a"))); |
956 | | assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit)))); |
957 | | assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit)))); |
958 | | assert_eq!(oct_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b))); |
959 | | assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit)))); |
960 | | assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit)))); |
961 | | assert_eq!(bin_digit1(a), Err(Err::Error((a, ErrorKind::BinDigit)))); |
962 | | assert_eq!(bin_digit1::<_, (_, ErrorKind)>(b), Ok(("234", "1"))); |
963 | | assert_eq!(bin_digit1(c), Err(Err::Error((c, ErrorKind::BinDigit)))); |
964 | | assert_eq!(bin_digit1(d), Err(Err::Error((d, ErrorKind::BinDigit)))); |
965 | | assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(a), Ok((empty, a))); |
966 | | //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); |
967 | | assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(c), Ok((empty, c))); |
968 | | assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(d), Ok(("é12", "az"))); |
969 | | assert_eq!(space1::<_, (_, ErrorKind)>(e), Ok((empty, e))); |
970 | | } |
971 | | |
972 | | use crate::traits::Offset; |
973 | | #[test] |
974 | | fn offset() { |
975 | | let a = &b"abcd;"[..]; |
976 | | let b = &b"1234;"[..]; |
977 | | let c = &b"a123;"[..]; |
978 | | let d = &b" \t;"[..]; |
979 | | let e = &b" \t\r\n;"[..]; |
980 | | let f = &b"123abcDEF;"[..]; |
981 | | |
982 | | match alpha1::<_, (_, ErrorKind)>(a) { |
983 | | Ok((i, _)) => { |
984 | | assert_eq!(a.offset(i) + i.len(), a.len()); |
985 | | } |
986 | | _ => panic!("wrong return type in offset test for alpha"), |
987 | | } |
988 | | match digit1::<_, (_, ErrorKind)>(b) { |
989 | | Ok((i, _)) => { |
990 | | assert_eq!(b.offset(i) + i.len(), b.len()); |
991 | | } |
992 | | _ => panic!("wrong return type in offset test for digit"), |
993 | | } |
994 | | match alphanumeric1::<_, (_, ErrorKind)>(c) { |
995 | | Ok((i, _)) => { |
996 | | assert_eq!(c.offset(i) + i.len(), c.len()); |
997 | | } |
998 | | _ => panic!("wrong return type in offset test for alphanumeric"), |
999 | | } |
1000 | | match space1::<_, (_, ErrorKind)>(d) { |
1001 | | Ok((i, _)) => { |
1002 | | assert_eq!(d.offset(i) + i.len(), d.len()); |
1003 | | } |
1004 | | _ => panic!("wrong return type in offset test for space"), |
1005 | | } |
1006 | | match multispace1::<_, (_, ErrorKind)>(e) { |
1007 | | Ok((i, _)) => { |
1008 | | assert_eq!(e.offset(i) + i.len(), e.len()); |
1009 | | } |
1010 | | _ => panic!("wrong return type in offset test for multispace"), |
1011 | | } |
1012 | | match hex_digit1::<_, (_, ErrorKind)>(f) { |
1013 | | Ok((i, _)) => { |
1014 | | assert_eq!(f.offset(i) + i.len(), f.len()); |
1015 | | } |
1016 | | _ => panic!("wrong return type in offset test for hex_digit"), |
1017 | | } |
1018 | | match oct_digit1::<_, (_, ErrorKind)>(f) { |
1019 | | Ok((i, _)) => { |
1020 | | assert_eq!(f.offset(i) + i.len(), f.len()); |
1021 | | } |
1022 | | _ => panic!("wrong return type in offset test for oct_digit"), |
1023 | | } |
1024 | | match bin_digit1::<_, (_, ErrorKind)>(f) { |
1025 | | Ok((i, _)) => { |
1026 | | assert_eq!(f.offset(i) + i.len(), f.len()); |
1027 | | } |
1028 | | _ => panic!("wrong return type in offset test for bin_digit"), |
1029 | | } |
1030 | | } |
1031 | | |
1032 | | #[test] |
1033 | | fn is_not_line_ending_bytes() { |
1034 | | let a: &[u8] = b"ab12cd\nefgh"; |
1035 | | assert_eq!( |
1036 | | not_line_ending::<_, (_, ErrorKind)>(a), |
1037 | | Ok((&b"\nefgh"[..], &b"ab12cd"[..])) |
1038 | | ); |
1039 | | |
1040 | | let b: &[u8] = b"ab12cd\nefgh\nijkl"; |
1041 | | assert_eq!( |
1042 | | not_line_ending::<_, (_, ErrorKind)>(b), |
1043 | | Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) |
1044 | | ); |
1045 | | |
1046 | | let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; |
1047 | | assert_eq!( |
1048 | | not_line_ending::<_, (_, ErrorKind)>(c), |
1049 | | Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) |
1050 | | ); |
1051 | | |
1052 | | let d: &[u8] = b"ab12cd"; |
1053 | | assert_eq!(not_line_ending::<_, (_, ErrorKind)>(d), Ok((&[][..], d))); |
1054 | | } |
1055 | | |
1056 | | #[test] |
1057 | | fn is_not_line_ending_str() { |
1058 | | /* |
1059 | | let a: &str = "ab12cd\nefgh"; |
1060 | | assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..]))); |
1061 | | |
1062 | | let b: &str = "ab12cd\nefgh\nijkl"; |
1063 | | assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..]))); |
1064 | | |
1065 | | let c: &str = "ab12cd\r\nefgh\nijkl"; |
1066 | | assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..]))); |
1067 | | |
1068 | | let d = "βèƒôřè\nÂßÇáƒƭèř"; |
1069 | | assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); |
1070 | | |
1071 | | let e = "βèƒôřè\r\nÂßÇáƒƭèř"; |
1072 | | assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); |
1073 | | */ |
1074 | | |
1075 | | let f = "βèƒôřè\rÂßÇáƒƭèř"; |
1076 | | assert_eq!(not_line_ending(f), Err(Err::Error((f, ErrorKind::Tag)))); |
1077 | | |
1078 | | let g2: &str = "ab12cd"; |
1079 | | assert_eq!(not_line_ending::<_, (_, ErrorKind)>(g2), Ok(("", g2))); |
1080 | | } |
1081 | | |
1082 | | #[test] |
1083 | | fn hex_digit_test() { |
1084 | | let i = &b"0123456789abcdefABCDEF;"[..]; |
1085 | | assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); |
1086 | | |
1087 | | let i = &b"g"[..]; |
1088 | | assert_parse!( |
1089 | | hex_digit1(i), |
1090 | | Err(Err::Error(error_position!(i, ErrorKind::HexDigit))) |
1091 | | ); |
1092 | | |
1093 | | let i = &b"G"[..]; |
1094 | | assert_parse!( |
1095 | | hex_digit1(i), |
1096 | | Err(Err::Error(error_position!(i, ErrorKind::HexDigit))) |
1097 | | ); |
1098 | | |
1099 | | assert!(AsChar::is_hex_digit(b'0')); |
1100 | | assert!(AsChar::is_hex_digit(b'9')); |
1101 | | assert!(AsChar::is_hex_digit(b'a')); |
1102 | | assert!(AsChar::is_hex_digit(b'f')); |
1103 | | assert!(AsChar::is_hex_digit(b'A')); |
1104 | | assert!(AsChar::is_hex_digit(b'F')); |
1105 | | assert!(!AsChar::is_hex_digit(b'g')); |
1106 | | assert!(!AsChar::is_hex_digit(b'G')); |
1107 | | assert!(!AsChar::is_hex_digit(b'/')); |
1108 | | assert!(!AsChar::is_hex_digit(b':')); |
1109 | | assert!(!AsChar::is_hex_digit(b'@')); |
1110 | | assert!(!AsChar::is_hex_digit(b'\x60')); |
1111 | | } |
1112 | | |
1113 | | #[test] |
1114 | | fn oct_digit_test() { |
1115 | | let i = &b"01234567;"[..]; |
1116 | | assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); |
1117 | | |
1118 | | let i = &b"8"[..]; |
1119 | | assert_parse!( |
1120 | | oct_digit1(i), |
1121 | | Err(Err::Error(error_position!(i, ErrorKind::OctDigit))) |
1122 | | ); |
1123 | | |
1124 | | assert!(AsChar::is_oct_digit(b'0')); |
1125 | | assert!(AsChar::is_oct_digit(b'7')); |
1126 | | assert!(!AsChar::is_oct_digit(b'8')); |
1127 | | assert!(!AsChar::is_oct_digit(b'9')); |
1128 | | assert!(!AsChar::is_oct_digit(b'a')); |
1129 | | assert!(!AsChar::is_oct_digit(b'A')); |
1130 | | assert!(!AsChar::is_oct_digit(b'/')); |
1131 | | assert!(!AsChar::is_oct_digit(b':')); |
1132 | | assert!(!AsChar::is_oct_digit(b'@')); |
1133 | | assert!(!AsChar::is_oct_digit(b'\x60')); |
1134 | | } |
1135 | | |
1136 | | #[test] |
1137 | | fn bin_digit_test() { |
1138 | | let i = &b"101010;"[..]; |
1139 | | assert_parse!(bin_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); |
1140 | | |
1141 | | let i = &b"2"[..]; |
1142 | | assert_parse!( |
1143 | | bin_digit1(i), |
1144 | | Err(Err::Error(error_position!(i, ErrorKind::BinDigit))) |
1145 | | ); |
1146 | | |
1147 | | assert!(crate::character::is_bin_digit(b'0')); |
1148 | | assert!(crate::character::is_bin_digit(b'1')); |
1149 | | assert!(!crate::character::is_bin_digit(b'8')); |
1150 | | assert!(!crate::character::is_bin_digit(b'9')); |
1151 | | assert!(!crate::character::is_bin_digit(b'a')); |
1152 | | assert!(!crate::character::is_bin_digit(b'A')); |
1153 | | assert!(!crate::character::is_bin_digit(b'/')); |
1154 | | assert!(!crate::character::is_bin_digit(b':')); |
1155 | | assert!(!crate::character::is_bin_digit(b'@')); |
1156 | | assert!(!crate::character::is_bin_digit(b'\x60')); |
1157 | | } |
1158 | | |
1159 | | #[test] |
1160 | | fn full_line_windows() { |
1161 | | use crate::sequence::pair; |
1162 | | fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { |
1163 | | pair(not_line_ending, line_ending).parse(i) |
1164 | | } |
1165 | | let input = b"abc\r\n"; |
1166 | | let output = take_full_line(input); |
1167 | | assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); |
1168 | | } |
1169 | | |
1170 | | #[test] |
1171 | | fn full_line_unix() { |
1172 | | use crate::sequence::pair; |
1173 | | fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { |
1174 | | pair(not_line_ending, line_ending).parse(i) |
1175 | | } |
1176 | | let input = b"abc\n"; |
1177 | | let output = take_full_line(input); |
1178 | | assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); |
1179 | | } |
1180 | | |
1181 | | #[test] |
1182 | | fn check_windows_lineending() { |
1183 | | let input = b"\r\n"; |
1184 | | let output = line_ending(&input[..]); |
1185 | | assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); |
1186 | | } |
1187 | | |
1188 | | #[test] |
1189 | | fn check_unix_lineending() { |
1190 | | let input = b"\n"; |
1191 | | let output = line_ending(&input[..]); |
1192 | | assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); |
1193 | | } |
1194 | | |
1195 | | #[test] |
1196 | | fn cr_lf() { |
1197 | | assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); |
1198 | | assert_parse!( |
1199 | | crlf(&b"\r"[..]), |
1200 | | Err(Err::Error(error_position!(&b"\r"[..], ErrorKind::CrLf))) |
1201 | | ); |
1202 | | assert_parse!( |
1203 | | crlf(&b"\ra"[..]), |
1204 | | Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf))) |
1205 | | ); |
1206 | | |
1207 | | assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); |
1208 | | assert_parse!( |
1209 | | crlf("\r"), |
1210 | | Err(Err::Error(error_position!("\r", ErrorKind::CrLf))) |
1211 | | ); |
1212 | | assert_parse!( |
1213 | | crlf("\ra"), |
1214 | | Err(Err::Error(error_position!("\ra", ErrorKind::CrLf))) |
1215 | | ); |
1216 | | } |
1217 | | |
1218 | | #[test] |
1219 | | fn end_of_line() { |
1220 | | assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); |
1221 | | assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); |
1222 | | assert_parse!( |
1223 | | line_ending(&b"\r"[..]), |
1224 | | Err(Err::Error(error_position!(&b"\r"[..], ErrorKind::CrLf))) |
1225 | | ); |
1226 | | assert_parse!( |
1227 | | line_ending(&b"\ra"[..]), |
1228 | | Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf))) |
1229 | | ); |
1230 | | |
1231 | | assert_parse!(line_ending("\na"), Ok(("a", "\n"))); |
1232 | | assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); |
1233 | | assert_parse!( |
1234 | | line_ending("\r"), |
1235 | | Err(Err::Error(error_position!("\r", ErrorKind::CrLf))) |
1236 | | ); |
1237 | | assert_parse!( |
1238 | | line_ending("\ra"), |
1239 | | Err(Err::Error(error_position!("\ra", ErrorKind::CrLf))) |
1240 | | ); |
1241 | | } |
1242 | | |
1243 | | fn digit_to_i16(input: &str) -> IResult<&str, i16> { |
1244 | | let i = input; |
1245 | | let (i, opt_sign) = opt(alt((char('+'), char('-')))).parse(i)?; |
1246 | | let sign = match opt_sign { |
1247 | | Some('+') => true, |
1248 | | Some('-') => false, |
1249 | | _ => true, |
1250 | | }; |
1251 | | |
1252 | | let (i, s) = match digit1::<_, crate::error::Error<_>>(i) { |
1253 | | Ok((i, s)) => (i, s), |
1254 | | Err(_) => { |
1255 | | return Err(Err::Error(crate::error::Error::from_error_kind( |
1256 | | input, |
1257 | | ErrorKind::Digit, |
1258 | | ))) |
1259 | | } |
1260 | | }; |
1261 | | |
1262 | | match s.parse_to() { |
1263 | | Some(n) => { |
1264 | | if sign { |
1265 | | Ok((i, n)) |
1266 | | } else { |
1267 | | Ok((i, -n)) |
1268 | | } |
1269 | | } |
1270 | | None => Err(Err::Error(crate::error::Error::from_error_kind( |
1271 | | i, |
1272 | | ErrorKind::Digit, |
1273 | | ))), |
1274 | | } |
1275 | | } |
1276 | | |
1277 | | fn digit_to_u32(i: &str) -> IResult<&str, u32> { |
1278 | | let (i, s) = digit1(i)?; |
1279 | | match s.parse_to() { |
1280 | | Some(n) => Ok((i, n)), |
1281 | | None => Err(Err::Error(crate::error::Error::from_error_kind( |
1282 | | i, |
1283 | | ErrorKind::Digit, |
1284 | | ))), |
1285 | | } |
1286 | | } |
1287 | | |
1288 | | proptest! { |
1289 | | #[test] |
1290 | | fn ints(s in "\\PC*") { |
1291 | | let res1 = digit_to_i16(&s); |
1292 | | let res2 = i16(s.as_str()); |
1293 | | assert_eq!(res1, res2); |
1294 | | } |
1295 | | |
1296 | | #[test] |
1297 | | fn uints(s in "\\PC*") { |
1298 | | let res1 = digit_to_u32(&s); |
1299 | | let res2 = u32(s.as_str()); |
1300 | | assert_eq!(res1, res2); |
1301 | | } |
1302 | | } |
1303 | | } |