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