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