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