/rust/registry/src/github.com-1ecc6299db9ec823/nom-5.1.2/src/character/streaming.rs
Line | Count | Source |
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 | | /// ``` |
28 | 2.75M | pub fn char<I, Error: ParseError<I>>(c: char) -> impl Fn(I) -> IResult<I, char, Error> |
29 | 2.75M | where |
30 | 2.75M | I: Slice<RangeFrom<usize>> + InputIter, |
31 | 2.75M | <I as InputIter>::Item: AsChar, |
32 | 2.75M | { |
33 | 2.75M | move |i: I| match (i).iter_elements().next().map(|t| { |
34 | 2.75M | let b = t.as_char() == c; |
35 | 2.75M | (&c, b) |
36 | 2.75M | }) { |
37 | 912 | None => Err(Err::Incomplete(Needed::Size(1))), |
38 | | Some((_, false)) => { |
39 | 191k | Err(Err::Error(Error::from_char(i, c))) |
40 | | } |
41 | 2.56M | Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())), |
42 | 2.75M | } |
43 | 2.75M | } |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
116 | 3.18M | pub fn crlf<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> |
117 | 3.18M | where |
118 | 3.18M | T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>, |
119 | 3.18M | T: InputIter, |
120 | 3.18M | T: Compare<&'static str>, |
121 | 3.18M | { |
122 | 3.18M | match input.compare("\r\n") { |
123 | | //FIXME: is this the right index? |
124 | 2.35M | CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))), |
125 | 1.07k | CompareResult::Incomplete => Err(Err::Incomplete(Needed::Size(2))), |
126 | | CompareResult::Error => { |
127 | 826k | let e: ErrorKind = ErrorKind::CrLf; |
128 | 826k | Err(Err::Error(E::from_error_kind(input, e))) |
129 | | } |
130 | | } |
131 | 3.18M | } |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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 | | /// ``` |
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] |
662 | | fn anychar_str() { |
663 | | use super::anychar; |
664 | | assert_eq!(anychar::<_, (&str, ErrorKind)>("Ә"), Ok(("", 'Ә'))); |
665 | | } |
666 | | |
667 | | #[test] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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 | | } |