• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Module containing parsers specialized on byte streams.
2 
3 use crate::{
4     error::{self, ParseError, ParseResult::*},
5     parser::{
6         combinator::no_partial,
7         range::{take_fn, TakeRange},
8         repeat::skip_many,
9         token::{satisfy, token, tokens_cmp, Token},
10     },
11     stream::{RangeStream, Stream},
12     Parser,
13 };
14 
15 /// Parses a byte and succeeds if the byte is equal to `c`.
16 ///
17 /// ```
18 /// use combine::Parser;
19 /// use combine::parser::byte::byte;
20 /// assert_eq!(byte(b'!').parse(&b"!"[..]), Ok((b'!', &b""[..])));
21 /// assert!(byte(b'A').parse(&b""[..]).is_err());
22 /// assert!(byte(b'A').parse(&b"!"[..]).is_err());
23 /// ```
byte<Input>(c: u8) -> Token<Input> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,24 pub fn byte<Input>(c: u8) -> Token<Input>
25 where
26     Input: Stream<Token = u8>,
27     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
28 {
29     token(c)
30 }
31 
32 macro_rules! byte_parser {
33     ($name:ident, $ty:ident, $f: ident) => {{
34         satisfy(|c: u8| c.$f())
35             .expected(stringify!($name))
36     }};
37     ($name:ident, $ty:ident, $f: ident $($args:tt)+) => {{
38         satisfy(|c: u8| c.$f $($args)+)
39             .expected(stringify!($name))
40     }};
41 }
42 
43 /// Parses a base-10 digit (0–9).
44 ///
45 /// ```
46 /// use combine::Parser;
47 /// use combine::parser::byte::digit;
48 /// assert_eq!(digit().parse(&b"9"[..]), Ok((b'9', &b""[..])));
49 /// assert!(digit().parse(&b"A"[..]).is_err());
50 /// ```
digit<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,51 pub fn digit<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
52 where
53     Input: Stream<Token = u8>,
54     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
55 {
56     byte_parser!(digit, Digit, is_ascii_digit())
57 }
58 
59 /// Parses a `b' '`, `b'\t'`, `b'\n'` or `'b\'r'`.
60 ///
61 /// ```
62 /// use combine::Parser;
63 /// use combine::parser::byte::space;
64 /// assert_eq!(space().parse(&b" "[..]), Ok((b' ', &b""[..])));
65 /// assert_eq!(space().parse(&b"  "[..]), Ok((b' ', &b" "[..])));
66 /// assert!(space().parse(&b"!"[..]).is_err());
67 /// assert!(space().parse(&b""[..]).is_err());
68 /// ```
space<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,69 pub fn space<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
70 where
71     Input: Stream<Token = u8>,
72     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
73 {
74     byte_parser!(space, Space, is_ascii_whitespace)
75 }
76 
77 /// Skips over [`space`] zero or more times
78 ///
79 /// [`space`]: fn.space.html
80 ///
81 /// ```
82 /// use combine::Parser;
83 /// use combine::parser::byte::spaces;
84 /// assert_eq!(spaces().parse(&b""[..]), Ok(((), &b""[..])));
85 /// assert_eq!(spaces().parse(&b"   "[..]), Ok(((), &b""[..])));
86 /// ```
spaces<Input>() -> impl Parser<Input, Output = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,87 pub fn spaces<Input>() -> impl Parser<Input, Output = ()>
88 where
89     Input: Stream<Token = u8>,
90     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
91 {
92     skip_many(space()).expected("whitespaces")
93 }
94 
95 /// Parses a newline byte (`b'\n'`).
96 ///
97 /// ```
98 /// use combine::Parser;
99 /// use combine::parser::byte::newline;
100 /// assert_eq!(newline().parse(&b"\n"[..]), Ok((b'\n', &b""[..])));
101 /// assert!(newline().parse(&b"\r"[..]).is_err());
102 /// ```
newline<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,103 pub fn newline<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
104 where
105     Input: Stream<Token = u8>,
106     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
107 {
108     satisfy(|ch: u8| ch == b'\n').expected("lf newline")
109 }
110 
111 /// Parses carriage return and newline (`&b"\r\n"`), returning the newline byte.
112 ///
113 /// ```
114 /// use combine::Parser;
115 /// use combine::parser::byte::crlf;
116 /// assert_eq!(crlf().parse(&b"\r\n"[..]), Ok((b'\n', &b""[..])));
117 /// assert!(crlf().parse(&b"\r"[..]).is_err());
118 /// assert!(crlf().parse(&b"\n"[..]).is_err());
119 /// ```
crlf<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,120 pub fn crlf<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
121 where
122     Input: Stream<Token = u8>,
123     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
124 {
125     no_partial(satisfy(|ch: u8| ch == b'\r').with(newline())).expected("crlf newline")
126 }
127 
128 /// Parses a tab byte (`b'\t'`).
129 ///
130 /// ```
131 /// use combine::Parser;
132 /// use combine::parser::byte::tab;
133 /// assert_eq!(tab().parse(&b"\t"[..]), Ok((b'\t', &b""[..])));
134 /// assert!(tab().parse(&b" "[..]).is_err());
135 /// ```
tab<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,136 pub fn tab<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
137 where
138     Input: Stream<Token = u8>,
139     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
140 {
141     satisfy(|ch| ch == b'\t').expected("tab")
142 }
143 
144 /// Parses an uppercase ASCII letter (A–Z).
145 ///
146 /// ```
147 /// use combine::Parser;
148 /// use combine::parser::byte::upper;
149 /// assert_eq!(upper().parse(&b"A"[..]), Ok((b'A', &b""[..])));
150 /// assert!(upper().parse(&b"a"[..]).is_err());
151 /// ```
upper<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,152 pub fn upper<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
153 where
154     Input: Stream<Token = u8>,
155     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
156 {
157     byte_parser!(upper, Upper, is_ascii_uppercase)
158 }
159 
160 /// Parses an lowercase ASCII letter (a–z).
161 ///
162 /// ```
163 /// use combine::Parser;
164 /// use combine::parser::byte::lower;
165 /// assert_eq!(lower().parse(&b"a"[..]), Ok((b'a', &b""[..])));
166 /// assert!(lower().parse(&b"A"[..]).is_err());
167 /// ```
lower<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,168 pub fn lower<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
169 where
170     Input: Stream<Token = u8>,
171     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
172 {
173     byte_parser!(lower, Lower, is_ascii_lowercase)
174 }
175 
176 /// Parses either an ASCII alphabet letter or digit (a–z, A–Z, 0–9).
177 ///
178 /// ```
179 /// use combine::Parser;
180 /// use combine::parser::byte::alpha_num;
181 /// assert_eq!(alpha_num().parse(&b"A"[..]), Ok((b'A', &b""[..])));
182 /// assert_eq!(alpha_num().parse(&b"1"[..]), Ok((b'1', &b""[..])));
183 /// assert!(alpha_num().parse(&b"!"[..]).is_err());
184 /// ```
alpha_num<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,185 pub fn alpha_num<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
186 where
187     Input: Stream<Token = u8>,
188     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
189 {
190     byte_parser!(alpha_num, AlphaNum, is_ascii_alphanumeric)
191 }
192 
193 /// Parses an ASCII alphabet letter (a–z, A–Z).
194 ///
195 /// ```
196 /// use combine::Parser;
197 /// use combine::parser::byte::letter;
198 /// assert_eq!(letter().parse(&b"a"[..]), Ok((b'a', &b""[..])));
199 /// assert_eq!(letter().parse(&b"A"[..]), Ok((b'A', &b""[..])));
200 /// assert!(letter().parse(&b"9"[..]).is_err());
201 /// ```
letter<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,202 pub fn letter<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
203 where
204     Input: Stream<Token = u8>,
205     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
206 {
207     byte_parser!(letter, Letter, is_ascii_alphabetic)
208 }
209 
210 /// Parses an octal digit.
211 ///
212 /// ```
213 /// use combine::Parser;
214 /// use combine::parser::byte::oct_digit;
215 /// assert_eq!(oct_digit().parse(&b"7"[..]), Ok((b'7', &b""[..])));
216 /// assert!(oct_digit().parse(&b"8"[..]).is_err());
217 /// ```
oct_digit<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,218 pub fn oct_digit<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
219 where
220     Input: Stream<Token = u8>,
221     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
222 {
223     satisfy(|ch| (b'0'..=b'7').contains(&ch)).expected("octal digit")
224 }
225 
226 /// Parses an ASCII hexdecimal digit (accepts both uppercase and lowercase).
227 ///
228 /// ```
229 /// use combine::Parser;
230 /// use combine::parser::byte::hex_digit;
231 /// assert_eq!(hex_digit().parse(&b"F"[..]), Ok((b'F', &b""[..])));
232 /// assert!(hex_digit().parse(&b"H"[..]).is_err());
233 /// ```
hex_digit<Input>() -> impl Parser<Input, Output = u8, PartialState = ()> where Input: Stream<Token = u8>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,234 pub fn hex_digit<Input>() -> impl Parser<Input, Output = u8, PartialState = ()>
235 where
236     Input: Stream<Token = u8>,
237     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
238 {
239     byte_parser!(hex_digit, HexDigit, is_ascii_hexdigit())
240 }
241 
242 parser! {
243 /// Parses the bytes `s`.
244 ///
245 /// If you have a stream implementing [`RangeStream`] such as `&[u8]` you can also use the
246 /// [`range`] parser which may be more efficient.
247 ///
248 /// ```
249 /// # extern crate combine;
250 /// # use combine::*;
251 /// # use combine::parser::byte::bytes;
252 /// # fn main() {
253 /// let result = bytes(&b"rust"[..])
254 ///     .parse(&b"rust"[..])
255 ///     .map(|x| x.0);
256 /// assert_eq!(result, Ok(&b"rust"[..]));
257 /// # }
258 /// ```
259 ///
260 /// [`RangeStream`]: super::super::stream::RangeStream
261 /// [`range`]: super::range::range
262 pub fn bytes['a, 'b, Input](s: &'static [u8])(Input) -> &'a [u8]
263 where [
264     Input: Stream<Token = u8, Range = &'b [u8]>,
265     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
266 ]
267 {
268     bytes_cmp(s, |l: u8, r: u8| l == r)
269 }
270 }
271 
272 parser! {
273 /// Parses the bytes `s` using `cmp` to compare each token.
274 ///
275 /// If you have a stream implementing [`RangeStream`] such as `&[u8]` you can also use the
276 /// [`range`] parser which may be more efficient.
277 ///
278 /// ```
279 /// # extern crate combine;
280 /// # use combine::*;
281 /// # use combine::parser::byte::bytes_cmp;
282 /// # use combine::stream::easy::Info;
283 /// # fn main() {
284 /// let result = bytes_cmp(&b"abc"[..], |l, r| l.eq_ignore_ascii_case(&r))
285 ///     .parse(&b"AbC"[..]);
286 /// assert_eq!(result, Ok((&b"abc"[..], &b""[..])));
287 /// # }
288 /// ```
289 ///
290 /// [`RangeStream`]: super::super::stream::RangeStream
291 /// [`range`]: super::range::range
292 pub fn bytes_cmp['a, 'b, C, Input](s: &'static [u8], cmp: C)(Input) -> &'a [u8]
293 where [
294     C: FnMut(u8, u8) -> bool,
295     Input: Stream<Token = u8, Range = &'b [u8]>,
296     Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
297 ]
298 {
299     let s = *s;
300     tokens_cmp(s.iter().cloned(), cmp)
301         .map(move |_| s)
302         .expected(error::Range(s))
303 }
304 }
305 
306 macro_rules! take_until {
307     (
308         $(#[$attr:meta])*
309         $type_name: ident, $func_name: ident, $memchr: ident, $($param: ident),+
310     ) => {
311         parser!{
312             #[derive(Clone)]
313             pub struct $type_name;
314             type PartialState = usize;
315             $(#[$attr])*
316             pub fn $func_name[Input]($($param : u8),*)(Input) -> Input::Range
317                 where [
318                     Input: RangeStream,
319                     Input::Range: AsRef<[u8]> + crate::stream::Range,
320                 ]
321             {
322                 take_fn(move |haystack: Input::Range| {
323                     let haystack = haystack.as_ref();
324                     match ::memchr::$memchr( $(*$param),+ , haystack) {
325                         Some(i) => TakeRange::Found(i),
326                         None => TakeRange::NotFound(haystack.len()),
327                     }
328                 })
329             }
330         }
331     }
332 }
333 
334 take_until! {
335     /// Zero-copy parser which reads a range of 0 or more tokens until `a` is found.
336     ///
337     /// If `a` is not found, the parser will return an error.
338     ///
339     /// ```
340     /// # extern crate combine;
341     /// # use combine::parser::byte::take_until_byte;
342     /// # use combine::*;
343     /// # fn main() {
344     /// let mut parser = take_until_byte(b'\r');
345     /// let result = parser.parse("To: user@example.com\r\n");
346     /// assert_eq!(result, Ok(("To: user@example.com", "\r\n")));
347     /// let result = parser.parse("Hello, world\n");
348     /// assert!(result.is_err());
349     /// # }
350     /// ```
351     TakeUntilByte, take_until_byte, memchr, a
352 }
353 take_until! {
354     /// Zero-copy parser which reads a range of 0 or more tokens until `a` or `b` is found.
355     ///
356     /// If `a` or `b` is not found, the parser will return an error.
357     ///
358     /// ```
359     /// # extern crate combine;
360     /// # use combine::parser::byte::take_until_byte2;
361     /// # use combine::*;
362     /// # fn main() {
363     /// let mut parser = take_until_byte2(b'\r', b'\n');
364     /// let result = parser.parse("To: user@example.com\r\n");
365     /// assert_eq!(result, Ok(("To: user@example.com", "\r\n")));
366     /// let result = parser.parse("Hello, world\n");
367     /// assert_eq!(result, Ok(("Hello, world", "\n")));
368     /// # }
369     /// ```
370     TakeUntilByte2, take_until_byte2, memchr2, a, b
371 }
372 take_until! {
373     /// Zero-copy parser which reads a range of 0 or more tokens until `a`, 'b' or `c` is found.
374     ///
375     /// If `a`, 'b' or `c` is not found, the parser will return an error.
376     ///
377     /// ```
378     /// # extern crate combine;
379     /// # use combine::parser::byte::take_until_byte3;
380     /// # use combine::*;
381     /// # fn main() {
382     /// let mut parser = take_until_byte3(b'\r', b'\n', b' ');
383     /// let result = parser.parse("To: user@example.com\r\n");
384     /// assert_eq!(result, Ok(("To:", " user@example.com\r\n")));
385     /// let result = parser.parse("Helloworld");
386     /// assert!(result.is_err());
387     /// # }
388     /// ```
389     TakeUntilByte3, take_until_byte3, memchr3, a, b, c
390 }
391 
392 parser! {
393 type PartialState = usize;
394 /// Zero-copy parser which reads a range of 0 or more tokens until `needle` is found.
395 ///
396 /// If `a`, 'b' or `c` is not found, the parser will return an error.
397 ///
398 /// Optimized variant of [`take_until_range`](../range/fn.take_until_range.html)
399 ///
400 /// ```
401 /// use combine::*;
402 /// use combine::parser::byte::take_until_bytes;
403 /// assert_eq!(
404 ///     take_until_bytes(&b"\r\n"[..]).easy_parse(&b"abc\r\n"[..]).map(|(x, _)| x),
405 ///     Ok((&b"abc"[..]))
406 /// );
407 /// // Also works on strings as long as `needle` is UTF-8
408 /// assert_eq!(
409 ///     take_until_bytes("\r\n".as_bytes()).easy_parse("abc\r\n").map(|(x, _)| x),
410 ///     Ok(("abc"))
411 /// );
412 /// ```
413 pub fn take_until_bytes['a, Input](needle: &'a [u8])(Input) -> Input::Range
414 where [
415     Input: RangeStream,
416     Input::Range: AsRef<[u8]> + crate::stream::Range,
417 ]
418 {
419     take_fn(move |haystack: Input::Range| {
420         let haystack = haystack.as_ref();
421         match memslice(needle, haystack) {
422             Some(i) => TakeRange::Found(i),
423             None => TakeRange::NotFound(haystack.len().saturating_sub(needle.len() - 1)),
424         }
425     })
426 }
427 
428 }
429 
memslice(needle: &[u8], haystack: &[u8]) -> Option<usize>430 fn memslice(needle: &[u8], haystack: &[u8]) -> Option<usize> {
431     let (&prefix, suffix) = match needle.split_first() {
432         Some(x) => x,
433         None => return Some(0),
434     };
435     for i in memchr::memchr_iter(prefix, haystack) {
436         if haystack[i + 1..].starts_with(suffix) {
437             return Some(i);
438         }
439     }
440     None
441 }
442 
443 /// Parsers for decoding numbers in big-endian or little-endian order.
444 pub mod num {
445 
446     use crate::{error::ResultExt, lib::mem::size_of, parser::function::parser, stream::uncons};
447 
448     use super::*;
449 
450     macro_rules! integer_parser {
451         (
452             $(#[$attr:meta])*
453             pub $type_name: ident,
454             $output_type: ident, $be_name: ident, $le_name: ident, $read_name: ident
455         ) => {
456             $(#[$attr])*
457             pub fn $be_name<'a, Input>() -> impl Parser<Input, Output = $output_type, PartialState = ()>
458             where
459                 Input: Stream<Token = u8>,
460                 Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
461             {
462                 parser(|input: &mut Input| {
463                     let checkpoint = input.checkpoint();
464                     let result = (|input: &mut Input| {
465                         let mut buffer = [0u8; size_of::<$output_type>()];
466                         for elem in &mut buffer[..] {
467                             *elem = ctry!(uncons(input)).0;
468                         }
469                         CommitOk($output_type::from_be_bytes(buffer))
470                     })(input);
471                     if result.is_err() {
472                         input.reset(checkpoint).committed().into_result()?;
473                     }
474                     result.into_result()
475                 })
476             }
477 
478             $(#[$attr])*
479             pub fn $le_name<'a, Input>() -> impl Parser<Input, Output = $output_type, PartialState = ()>
480             where
481                 Input: Stream<Token = u8>,
482                 Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
483             {
484                 parser(|input: &mut Input| {
485                     let checkpoint = input.checkpoint();
486                     let result = (|input: &mut Input| {
487                         let mut buffer = [0u8; size_of::<$output_type>()];
488                         for elem in &mut buffer[..] {
489                             *elem = ctry!(uncons(input)).0;
490                         }
491                         CommitOk($output_type::from_le_bytes(buffer))
492                     })(input);
493                     if result.is_err() {
494                         input.reset(checkpoint).committed().into_result()?;
495                     }
496                     result.into_result()
497                 })
498             }
499         }
500     }
501 
502     integer_parser!(
503         /// Reads a u16 out of the byte stream with the specified endianess
504         ///
505         /// ```
506         /// use combine::Parser;
507         /// use combine::parser::byte::num::le_u16;
508         ///
509         /// assert_eq!(le_u16().parse(&b"\x01\0"[..]), Ok((1, &b""[..])));
510         /// assert!(le_u16().parse(&b"\0"[..]).is_err());
511         /// ```
512         pub U16, u16, be_u16, le_u16, read_u16
513     );
514     integer_parser!(
515         /// Reads a u32 out of the byte stream with the specified endianess
516         ///
517         /// ```
518         /// use combine::Parser;
519         /// use combine::parser::byte::num::le_u32;
520         ///
521         /// assert_eq!(le_u32().parse(&b"\x01\0\0\0"[..]), Ok((1, &b""[..])));
522         /// assert!(le_u32().parse(&b"\x01\0\0"[..]).is_err());
523         /// ```
524         pub U32, u32, be_u32, le_u32, read_u32
525     );
526     integer_parser!(
527         /// Reads a u64 out of the byte stream with the specified endianess
528         ///
529         /// ```
530         /// use combine::Parser;
531         /// use combine::parser::byte::num::le_u64;
532         ///
533         /// assert_eq!(le_u64().parse(&b"\x01\0\0\0\0\0\0\0"[..]), Ok((1, &b""[..])));
534         /// assert!(le_u64().parse(&b"\x01\0\0\0\0\0\0"[..]).is_err());
535         /// ```
536         pub U64, u64, be_u64, le_u64, read_u64
537     );
538 
539     integer_parser!(
540         /// Reads a i16 out of the byte stream with the specified endianess
541         ///
542         /// ```
543         /// use combine::Parser;
544         /// use combine::parser::byte::num::le_i16;
545         ///
546         /// assert_eq!(le_i16().parse(&b"\x01\0"[..]), Ok((1, &b""[..])));
547         /// assert!(le_i16().parse(&b"\x01"[..]).is_err());
548         /// ```
549         pub I16, i16, be_i16, le_i16, read_i16
550     );
551 
552     integer_parser!(
553         /// Reads a i32 out of the byte stream with the specified endianess
554         ///
555         /// ```
556         /// use combine::Parser;
557         /// use combine::parser::byte::num::le_i32;
558         ///
559         /// assert_eq!(le_i32().parse(&b"\x01\0\0\0"[..]), Ok((1, &b""[..])));
560         /// assert!(le_i32().parse(&b"\x01\0\0"[..]).is_err());
561         /// ```
562         pub I32, i32, be_i32, le_i32, read_i32
563     );
564     integer_parser!(
565         /// Reads a i64 out of the byte stream with the specified endianess
566         ///
567         /// ```
568         /// use combine::Parser;
569         /// use combine::parser::byte::num::le_i64;
570         ///
571         /// assert_eq!(le_i64().parse(&b"\x01\0\0\0\0\0\0\0"[..]), Ok((1, &b""[..])));
572         /// assert!(le_i64().parse(&b"\x01\0\0\0\0\0\0"[..]).is_err());
573         /// ```
574         pub I64, i64, be_i64, le_i64, read_i64
575     );
576 
577     integer_parser!(
578         /// Reads a i32 out of the byte stream with the specified endianess
579         ///
580         /// ```
581         /// use combine::Parser;
582         /// use combine::parser::byte::num::le_f32;
583         ///
584         /// let buf = 123.45f32.to_le_bytes();
585         /// assert_eq!(le_f32().parse(&buf[..]), Ok((123.45, &b""[..])));
586         /// assert!(le_f32().parse(&b"\x01\0\0"[..]).is_err());
587         /// ```
588         pub F32, f32, be_f32, le_f32, read_f32
589     );
590     integer_parser!(
591         /// Reads a i64 out of the byte stream with the specified endianess
592         ///
593         /// ```
594         /// use combine::Parser;
595         /// use combine::parser::byte::num::le_f64;
596         ///
597         /// let buf = 123.45f64.to_le_bytes();
598         /// assert_eq!(le_f64().parse(&buf[..]), Ok((123.45, &b""[..])));
599         /// assert!(le_f64().parse(&b"\x01\0\0\0\0\0\0"[..]).is_err());
600         /// ```
601         pub F64, f64, be_f64, le_f64, read_f64
602     );
603 
604     #[cfg(all(feature = "std", test))]
605     mod tests {
606 
607         use crate::stream::{buffered, position, IteratorStream};
608 
609         use super::*;
610 
611         #[test]
no_rangestream()612         fn no_rangestream() {
613             let buf = 123.45f64.to_le_bytes();
614             assert_eq!(
615                 le_f64()
616                     .parse(buffered::Stream::new(
617                         position::Stream::new(IteratorStream::new(buf.iter().cloned())),
618                         1
619                     ))
620                     .map(|(t, _)| t),
621                 Ok(123.45)
622             );
623             assert_eq!(
624                 le_f64()
625                     .parse(buffered::Stream::new(
626                         position::Stream::new(IteratorStream::new(buf.iter().cloned())),
627                         1
628                     ))
629                     .map(|(t, _)| t),
630                 Ok(123.45)
631             );
632             let buf = 123.45f64.to_be_bytes();
633             assert_eq!(
634                 be_f64()
635                     .parse(buffered::Stream::new(
636                         position::Stream::new(IteratorStream::new(buf.iter().cloned())),
637                         1
638                     ))
639                     .map(|(t, _)| t),
640                 Ok(123.45)
641             );
642         }
643     }
644 }
645 
646 #[cfg(all(feature = "std", test))]
647 mod tests {
648 
649     use crate::stream::{buffered, position, read};
650 
651     use super::*;
652 
653     #[test]
memslice_basic()654     fn memslice_basic() {
655         let haystack = b"abc123";
656         assert_eq!(memslice(b"", haystack), Some(0));
657         assert_eq!(memslice(b"a", haystack), Some(0));
658         assert_eq!(memslice(b"ab", haystack), Some(0));
659         assert_eq!(memslice(b"c12", haystack), Some(2));
660 
661         let haystack2 = b"abcab2";
662         assert_eq!(memslice(b"abc", haystack2), Some(0));
663         assert_eq!(memslice(b"ab2", haystack2), Some(3));
664 
665         let haystack3 = b"aaabaaaa";
666         assert_eq!(memslice(b"aaaa", haystack3), Some(4));
667     }
668 
669     #[test]
bytes_read_stream()670     fn bytes_read_stream() {
671         assert!(bytes(b"abc")
672             .parse(buffered::Stream::new(
673                 position::Stream::new(read::Stream::new("abc".as_bytes())),
674                 1
675             ))
676             .is_ok());
677     }
678 }
679