1 #![allow(renamed_and_removed_lints)]
2
3 use std::{
4 cell::Cell,
5 io::{self, Cursor},
6 rc::Rc,
7 str,
8 };
9
10 use {
11 bytes::{Buf, BytesMut},
12 combine::{
13 any, count_min_max,
14 error::{ParseError, StreamError},
15 many1, parser,
16 parser::{
17 byte::{num, take_until_bytes},
18 char::{char, digit, letter, string},
19 choice::optional,
20 combinator::{
21 any_partial_state, any_send_partial_state, attempt, from_str, no_partial,
22 recognize, AnyPartialState, AnySendPartialState,
23 },
24 range::{
25 self, range, recognize_with_value, take, take_fn, take_until_range, take_while,
26 take_while1,
27 },
28 repeat,
29 },
30 satisfy, sep_end_by, skip_many, skip_many1,
31 stream::{easy, RangeStream, StreamErrorFor},
32 token, Parser,
33 },
34 futures::prelude::*,
35 futures_03_dep as futures,
36 partial_io::PartialRead,
37 quick_error::quick_error,
38 quickcheck::quickcheck,
39 tokio_dep as tokio,
40 tokio_util::codec::{Decoder, FramedRead},
41 };
42
43 // Workaround partial_io not working with tokio-0.2
44 mod support;
45 use support::*;
46
47 quick_error! {
48 #[derive(Debug)]
49 enum Error {
50 Io(err: io::Error) {
51 display("{}", err)
52 from()
53 }
54 Parse(err: easy::Errors<char, String, usize>) {
55 display("{}", err)
56 from()
57 }
58 Utf8(err: std::str::Utf8Error) {
59 display("{}", err)
60 from()
61 }
62 Message(err: String) {
63 display("{}", err)
64 from()
65 }
66 }
67 }
68
69 macro_rules! mk_parser {
70 ($parser:expr, $self_:expr,()) => {
71 $parser
72 };
73 ($parser:expr, $self_:expr,($custom_state:ty)) => {
74 $parser($self_.1.clone())
75 };
76 }
77 macro_rules! impl_decoder {
78 ($typ: ident, $token: ty, $parser: expr, $custom_state: ty) => {
79 #[derive(Default)]
80 struct $typ(AnyPartialState, $custom_state);
81 impl_decoder!{$typ, $token, $parser; ($custom_state)}
82 };
83 ($typ: ident, $token: ty, $parser: expr) => {
84 #[derive(Default)]
85 struct $typ(AnyPartialState);
86 impl_decoder!{$typ, $token, $parser; ()}
87 };
88 ($typ: ident, $token: ty, $parser: expr; ( $($custom_state: tt)* )) => {
89 impl Decoder for $typ {
90 type Item = $token;
91 type Error = Error;
92
93 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
94 (&mut &mut *self).decode(src)
95 }
96 fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
97 (&mut &mut *self).decode_eof(src)
98 }
99 }
100
101 impl<'a> Decoder for &'a mut $typ {
102 type Item = $token;
103 type Error = Error;
104
105 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
106 self.decode_stream(src, false)
107 }
108 fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
109 self.decode_stream(src, true)
110 }
111 }
112
113 impl<'a> $typ {
114 fn decode_stream(&mut self, src: &mut BytesMut, eof: bool) -> Result<Option<$token>, Error> {
115 let (opt, removed_len) = {
116 let str_src = str::from_utf8(&src[..])?;
117 println!("Decoding `{}`", str_src);
118 combine::stream::decode_tokio(
119 any_partial_state(mk_parser!($parser, self, ($($custom_state)*))),
120 &mut easy::Stream(combine::stream::MaybePartialStream(str_src, !eof)),
121 &mut self.0,
122 ).map_err(|err| {
123 // Since err contains references into `src` we must remove these before
124 // returning the error and before we call `advance` to remove the input we
125 // just committed
126 let err = err.map_range(|r| r.to_string())
127 .map_position(|p| p.translate_position(&str_src[..]));
128 format!("{}\nIn input: `{}`", err, str_src)
129 })?
130 };
131
132 src.advance(removed_len);
133 match opt {
134 None => println!("Need more input!"),
135 Some(_) => (),
136 }
137 Ok(opt)
138 }
139 }
140 }
141 }
142
143 macro_rules! impl_byte_decoder {
144 ($typ: ident, $token: ty, $parser: expr, $custom_state: ty) => {
145 #[derive(Default)]
146 struct $typ(AnyPartialState, $custom_state);
147 impl_byte_decoder!{$typ, $token, $parser; ($custom_state)}
148 };
149 ($typ: ident, $token: ty, $parser: expr) => {
150 #[derive(Default)]
151 struct $typ(AnyPartialState);
152 impl_byte_decoder!{$typ, $token, $parser; ()}
153 };
154 ($typ: ident, $token: ty, $parser: expr; ( $($custom_state: tt)* )) => {
155 impl Decoder for $typ {
156 type Item = $token;
157 type Error = Error;
158
159 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
160 (&mut &mut *self).decode(src)
161 }
162 }
163
164 impl<'a> Decoder for &'a mut $typ {
165 type Item = $token;
166 type Error = Error;
167
168 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
169 let (opt, removed_len) = {
170 let str_src = &src[..];
171 println!("Decoding `{:?}`", str_src);
172 combine::stream::decode(
173 any_partial_state(mk_parser!($parser, self, ($($custom_state)*))),
174 &mut easy::Stream(combine::stream::PartialStream(str_src)),
175 &mut self.0,
176 ).map_err(|err| {
177 // Since err contains references into `src` we must remove these before
178 // returning the error and before we call `advance` to remove the input we
179 // just committed
180 let err = err.map_range(|r| format!("{:?}", r))
181 .map_position(|p| p.translate_position(&str_src[..]));
182 format!("{}\nIn input: `{:?}`", err, str_src)
183 })?
184 };
185
186 src.advance(removed_len);
187 match opt {
188 None => println!("Need more input!"),
189 Some(_) => (),
190 }
191 Ok(opt)
192 }
193 }
194 }
195 }
196
197 use partial_io::{GenNoErrors, GenWouldBlock, PartialOp, PartialWithErrors};
198
run_decoder<B, D, S>(input: &B, seq: S, decoder: D) -> Result<Vec<D::Item>, D::Error> where D: Decoder<Error = Error>, D::Item: ::std::fmt::Debug, S: IntoIterator<Item = PartialOp> + 'static, S::IntoIter: Send, B: ?Sized + AsRef<[u8]>,199 fn run_decoder<B, D, S>(input: &B, seq: S, decoder: D) -> Result<Vec<D::Item>, D::Error>
200 where
201 D: Decoder<Error = Error>,
202 D::Item: ::std::fmt::Debug,
203 S: IntoIterator<Item = PartialOp> + 'static,
204 S::IntoIter: Send,
205 B: ?Sized + AsRef<[u8]>,
206 {
207 let ref mut reader = Cursor::new(input.as_ref());
208 let partial_reader = PartialAsyncRead::new(reader, seq);
209
210 tokio_02_dep::runtime::Builder::new()
211 .basic_scheduler()
212 .build()
213 .unwrap()
214 .block_on(
215 FramedRead::new(partial_reader, decoder)
216 .map_ok(|x| {
217 println!("Decoded `{:?}`", x);
218 x
219 })
220 .try_collect(),
221 )
222 }
223
224 parser! {
225 type PartialState = AnyPartialState;
226 fn basic_parser['a, Input]()(Input) -> String
227 where [ Input: RangeStream<Token = char, Range = &'a str> ]
228 {
229 any_partial_state(
230 many1(digit()).skip(range(&"\r\n"[..])),
231 )
232 }
233 }
234
235 impl_decoder! { Basic, String, basic_parser() }
236
237 #[test]
many1_skip_no_errors()238 fn many1_skip_no_errors() {
239 let input = "123\r\n\
240 456\r\n";
241
242 let result = run_decoder(input, vec![], Basic::default());
243
244 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
245 assert_eq!(result.unwrap(), vec!["123".to_string(), "456".to_string()]);
246 }
247
248 parser! {
249 type PartialState = AnyPartialState;
250 fn prefix_many_then_parser['a, Input]()(Input) -> String
251 where [ Input: RangeStream<Token = char, Range = &'a str> ]
252 {
253 let integer = from_str(many1::<String, _, _>(digit()));
254 any_partial_state((char('#'), skip_many(char(' ')), integer)
255 .then_partial(|t| {
256 let c = t.2;
257 count_min_max(c, c, any())
258 })
259 )
260 }
261 }
262
263 parser! {
264 type PartialState = AnyPartialState;
265 fn choice_parser['a, Input]()(Input) -> String
266 where [ Input: RangeStream<Token = char, Range = &'a str> ]
267 {
268 any_partial_state(
269 many1(digit())
270 .or(many1(letter()))
271 .skip(range(&"\r\n"[..]))
272 )
273 }
274 }
275
content_length<'a, Input>( ) -> impl Parser<Input, Output = String, PartialState = AnySendPartialState> + 'a where Input: RangeStream<Token = char, Range = &'a str> + 'a, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,276 fn content_length<'a, Input>(
277 ) -> impl Parser<Input, Output = String, PartialState = AnySendPartialState> + 'a
278 where
279 Input: RangeStream<Token = char, Range = &'a str> + 'a,
280 // Necessary due to rust-lang/rust#24159
281 Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
282 {
283 let content_length = range("Content-Length: ").with(
284 range::recognize(skip_many1(digit())).and_then(|digits: &str| {
285 // Convert the error from `.parse` into an error combine understands
286 digits
287 .parse::<usize>()
288 .map_err(StreamErrorFor::<Input>::other)
289 }),
290 );
291
292 any_send_partial_state(
293 (
294 skip_many(range("\r\n")),
295 content_length,
296 range("\r\n\r\n").map(|_| ()),
297 )
298 .then_partial(|&mut (_, message_length, _)| {
299 take(message_length).map(|bytes: &str| bytes.to_owned())
300 }),
301 )
302 }
303
304 quickcheck! {
305 fn many1_skip_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
306
307 let input = "123\r\n\
308 456\r\n\
309 1\r\n\
310 5\r\n\
311 666666\r\n";
312
313 let result = run_decoder(input, seq, Basic::default());
314
315 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
316 assert_eq!(
317 result.unwrap(),
318 vec!["123".to_string(), "456".to_string(), "1".to_string(), "5".to_string(), "666666".to_string()]
319 );
320 }
321
322 fn prefix_many_then_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
323 impl_decoder!{ TestParser, String, prefix_many_then_parser() }
324
325 let input = "# 1a\
326 # 4abcd\
327 #0\
328 #3:?a\
329 #10abcdefghij";
330
331 let result = run_decoder(input, seq, TestParser::default());
332
333 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
334 assert_eq!(
335 result.unwrap(),
336 ["a", "abcd", "", ":?a", "abcdefghij"]
337 );
338 }
339
340 fn choice_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
341 impl_decoder!{ TestParser, String, choice_parser() }
342
343 let input = "1\r\n\
344 abcd\r\n\
345 123\r\n\
346 abc\r\n\
347 1232751\r\n";
348
349 let result = run_decoder(input, seq, TestParser::default());
350
351 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
352 assert_eq!(
353 result.unwrap(),
354 ["1", "abcd", "123", "abc", "1232751"]
355 );
356 }
357
358 fn recognize_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
359 impl_decoder!{ TestParser, String,
360 recognize(
361 (skip_many1(digit()), optional((char('.'), skip_many(digit()))))
362 )
363 .skip(range(&"\r\n"[..]))
364 }
365
366 let input = "1.0\r\n\
367 123.123\r\n\
368 17824\r\n\
369 3.14\r\n\
370 1.\r\n\
371 2\r\n";
372
373 let result = run_decoder(input, seq, TestParser::default());
374
375 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
376 assert_eq!(
377 result.unwrap(),
378 ["1.0", "123.123", "17824", "3.14", "1.", "2"]
379 );
380 }
381
382 fn recognize_range_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
383 impl_decoder!{ TestParser, String,
384 recognize_with_value(
385 (skip_many1(digit()), optional((char('.'), skip_many(digit()))))
386 )
387 .map(|(r, _)| String::from(r))
388 .skip(range(&"\r\n"[..]))
389 }
390
391 let input = "1.0\r\n\
392 123.123\r\n\
393 17824\r\n\
394 3.14\r\n\
395 1.\r\n\
396 2\r\n";
397
398 let result = run_decoder(input, seq, TestParser::default());
399
400 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
401 assert_eq!(
402 result.unwrap(),
403 ["1.0", "123.123", "17824", "3.14", "1.", "2"]
404 );
405 }
406
407 fn take_while_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
408 impl_decoder!{ TestParser, String,
409 |counter: Rc<Cell<i32>>|
410 take_while(move |c| { counter.set(counter.get() + 1); c != '\r' })
411 .map(String::from)
412 .skip(range("\r\n")),
413 Rc<Cell<i32>>
414 }
415
416 let input = "1.0\r\n\
417 123.123\r\n\
418 17824\r\n\
419 3.14\r\n\
420 \r\n\
421 2\r\n";
422
423 let counter = Rc::new(Cell::new(0));
424 let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));
425
426 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
427 assert_eq!(
428 result.unwrap(),
429 ["1.0", "123.123", "17824", "3.14", "", "2"]
430 );
431
432 assert_eq!(counter.get(), 26);
433 }
434
435 fn take_while1_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
436 impl_decoder!{ TestParser, String,
437 |count: Rc<Cell<i32>>|
438 take_while1(move |c| { count.set(count.get() + 1); c != '\r' })
439 .map(String::from)
440 .skip(range("\r\n")),
441 Rc<Cell<i32>>
442 }
443
444 let input = "1.0\r\n\
445 123.123\r\n\
446 17824\r\n\
447 3.14\r\n\
448 1.\r\n\
449 2\r\n";
450
451 let counter = Rc::new(Cell::new(0));
452 let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));
453
454 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
455 assert_eq!(
456 result.unwrap(),
457 ["1.0", "123.123", "17824", "3.14", "1.", "2"]
458 );
459
460 assert_eq!(counter.get(), 28);
461 }
462
463 fn take_until(seq: PartialWithErrors<GenWouldBlock>) -> () {
464 impl_decoder!{ TestParser, String,
465 |count: Rc<Cell<i32>>|
466 repeat::take_until(token(',').map(move |_| count.set(count.get() + 1))).skip(token(',')),
467 Rc<Cell<i32>>
468 }
469
470 let input = "123,456,789,";
471
472 let counter = Rc::new(Cell::new(0));
473 let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));
474
475 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
476 assert_eq!(
477 result.unwrap(),
478 ["123", "456", "789"]
479 );
480
481 assert_eq!(counter.get(), 3);
482 }
483
484 fn take_until_committed(seq: PartialWithErrors<GenWouldBlock>) -> () {
485 impl_decoder!{ TestParser, String,
486 |count: Rc<Cell<i32>>| {
487 let end = attempt((token(':').map(move |_| count.set(count.get() + 1)), token(':')));
488 repeat::take_until(end).skip((token(':'), token(':')))
489 },
490 Rc<Cell<i32>>
491 }
492
493 let input = "123::456::789::";
494
495 let counter = Rc::new(Cell::new(0));
496 let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));
497
498 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
499 assert_eq!(
500 result.unwrap(),
501 ["123", "456", "789"]
502 );
503
504 assert_eq!(counter.get(), 3);
505 }
506
507 fn take_until_range_committed(seq: PartialWithErrors<GenWouldBlock>) -> () {
508 impl_decoder!{ TestParser, String,
509 take_until_range("::").map(String::from).skip((token(':'), token(':')))
510 }
511
512 let input = "123::456::789::";
513
514 let result = run_decoder(input, seq, TestParser(Default::default()));
515
516 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
517 assert_eq!(result.unwrap(), ["123", "456", "789"]);
518 }
519
520 fn any_send_partial_state_do_not_forget_state(sizes: Vec<usize>, seq: PartialWithErrors<GenWouldBlock>) -> () {
521 impl_decoder!{ TestParser, usize,
522 any_send_partial_state(content_length().map(|bytes| bytes.len()))
523 }
524
525 let input : String = sizes
526 .iter()
527 .map(|s| {
528 format!(
529 "Content-Length: {}\r\n\r\n{}\r\n",
530 s,
531 ::std::iter::repeat('a').take(*s).collect::<String>()
532 )
533 })
534 .collect();
535
536 let result = run_decoder(input.as_bytes(), seq, TestParser(Default::default()));
537
538 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
539 assert_eq!(result.unwrap(), sizes);
540 }
541
542 fn take_fn_test(sizes: Vec<usize>, seq: PartialWithErrors<GenWouldBlock>) -> () {
543 impl_decoder!{ TestParser, usize,
544 take_fn(|s: &str| s.find("\r\n")).map(|bytes: &str| bytes.parse::<usize>().unwrap()).skip(take(2))
545 }
546
547 let input : String = sizes
548 .iter()
549 .map(|s| {
550 format!(
551 "{}\r\n",
552 s,
553 )
554 })
555 .collect();
556
557 let result = run_decoder(input.as_bytes(), seq, TestParser(Default::default()));
558
559 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
560 assert_eq!(result.unwrap(), sizes);
561 }
562
563 fn take_until_bytes_test(sizes: Vec<usize>, seq: PartialWithErrors<GenWouldBlock>) -> () {
564 impl_decoder!{ TestParser, usize,
565 take_until_bytes("\r\n".as_bytes())
566 .map(|bytes: &str| bytes.parse::<usize>().unwrap())
567 .skip(take(2))
568 }
569
570 let input : String = sizes
571 .iter()
572 .map(|s| {
573 format!(
574 "{}\r\n",
575 s,
576 )
577 })
578 .collect();
579
580 let result = run_decoder(input.as_bytes(), seq, TestParser(Default::default()));
581
582 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
583 assert_eq!(result.unwrap(), sizes);
584 }
585
586 fn num_test(ints: Vec<u16>, seq: PartialWithErrors<GenWouldBlock>) -> () {
587 impl_byte_decoder!{ TestParser, u16,
588 num::be_u16()
589 .skip(take(2))
590 }
591
592 let input: Vec<u8> = ints.iter()
593 .flat_map(|i| {
594 let mut v = Vec::new();
595 v.extend_from_slice(&i.to_be_bytes());
596 v.extend_from_slice(b"\r\n");
597 v
598 })
599 .collect();
600
601 let result = run_decoder(&input, seq, TestParser(Default::default()));
602
603 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
604 assert_eq!(result.unwrap(), ints);
605 }
606
607 fn sep_end_by_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
608 impl_decoder!{ TestParser, Vec<String>,
609 repeat::sep_end_by((digit(), digit(), digit()).map(|(a, b, c)| vec![a, b, c].into_iter().collect()), no_partial(string("::")))
610 .skip(no_partial(string("\r\n")))
611 }
612
613 let input = "123::456::789::\r\n";
614
615 let result = run_decoder(&input, seq, TestParser(Default::default()));
616
617 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
618 assert_eq!(result.unwrap(), vec![vec!["123".to_string(), "456".to_string(), "789".to_string()]]);
619 }
620 }
621
622 #[test]
skip_count_min_max_test()623 fn skip_count_min_max_test() {
624 let seq = vec![PartialOp::Limited(1)];
625 impl_decoder! { TestParser, String,
626 repeat::skip_count_min_max(1, 2, char('_')).skip(char('.')).map(|_| "".to_string())
627 }
628
629 let input = "_.";
630
631 let result = run_decoder(input, seq, TestParser::default());
632
633 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
634 assert_eq!(result.unwrap(), [""]);
635 }
636
637 const WORDS_IN_README: usize = 824;
638
639 #[test]
decode_std()640 fn decode_std() {
641 quickcheck(
642 (|ops: PartialWithErrors<GenNoErrors>| {
643 let buf = include_bytes!("../README.md");
644
645 let mut read = PartialRead::new(&buf[..], ops);
646 let mut decoder =
647 combine::stream::Decoder::<_, combine::stream::PointerOffset<_>>::new();
648 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
649 assert_eq!(
650 combine::decode!(
651 decoder,
652 read,
653 {
654 let word = many1(satisfy(|b| !is_whitespace(b)));
655 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
656 .map(|words: Vec<Vec<u8>>| words.len())
657 },
658 |input, _| combine::easy::Stream::from(input)
659 )
660 .map_err(From::from)
661 .map_err(
662 |err: combine::easy::Errors<u8, &[u8], combine::stream::PointerOffset<_>>| err
663 .map_position(|p| p.0)
664 ),
665 Ok(WORDS_IN_README),
666 );
667 }) as fn(_) -> _,
668 )
669 }
670
671 #[test]
decode_tokio_02()672 fn decode_tokio_02() {
673 quickcheck(
674 (|ops: PartialWithErrors<GenWouldBlock>| {
675 let buf = include_bytes!("../README.md");
676 let runtime = tokio::runtime::Builder::new_current_thread()
677 .build()
678 .unwrap();
679 runtime.block_on(async {
680 let mut read = PartialAsyncRead::new(&buf[..], ops);
681 let mut decoder =
682 combine::stream::Decoder::<_, combine::stream::PointerOffset<[u8]>>::new();
683 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
684 assert_eq!(
685 combine::decode_tokio_02!(
686 decoder,
687 read,
688 {
689 let word = many1(satisfy(|b| !is_whitespace(b)));
690 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
691 .map(|words: Vec<Vec<u8>>| words.len())
692 },
693 |input, _| combine::easy::Stream::from(input)
694 )
695 .map_err(From::from)
696 .map_err(
697 |err: combine::easy::Errors<u8, &[u8], _>| err.map_range(|r| r.to_owned())
698 )
699 .map_err(|err| err.map_position(|p| p.translate_position(&decoder.buffer()))),
700 Ok(WORDS_IN_README),
701 );
702 })
703 }) as fn(_) -> _,
704 )
705 }
706
707 #[test]
decode_tokio_03()708 fn decode_tokio_03() {
709 quickcheck(
710 (|ops: PartialWithErrors<GenWouldBlock>| {
711 let buf = include_bytes!("../README.md");
712 let runtime = tokio::runtime::Builder::new_current_thread()
713 .build()
714 .unwrap();
715 runtime.block_on(async {
716 let mut read = PartialAsyncRead::new(&buf[..], ops);
717 let mut decoder =
718 combine::stream::Decoder::<_, combine::stream::PointerOffset<[u8]>>::new();
719 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
720 assert_eq!(
721 combine::decode_tokio_03!(
722 decoder,
723 read,
724 {
725 let word = many1(satisfy(|b| !is_whitespace(b)));
726 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
727 .map(|words: Vec<Vec<u8>>| words.len())
728 },
729 |input, _| combine::easy::Stream::from(input)
730 )
731 .map_err(From::from)
732 .map_err(
733 |err: combine::easy::Errors<u8, &[u8], _>| err.map_range(|r| r.to_owned())
734 )
735 .map_err(|err| err.map_position(|p| p.translate_position(&decoder.buffer()))),
736 Ok(WORDS_IN_README),
737 );
738 })
739 }) as fn(_) -> _,
740 )
741 }
742
743 #[test]
decode_tokio()744 fn decode_tokio() {
745 quickcheck(
746 (|ops: PartialWithErrors<GenWouldBlock>| {
747 let buf = include_bytes!("../README.md");
748 let runtime = tokio::runtime::Builder::new_current_thread()
749 .build()
750 .unwrap();
751 runtime.block_on(async {
752 let mut read = PartialAsyncRead::new(&buf[..], ops);
753 let mut decoder =
754 combine::stream::Decoder::<_, combine::stream::PointerOffset<[u8]>>::new();
755 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
756 assert_eq!(
757 combine::decode_tokio!(
758 decoder,
759 read,
760 {
761 let word = many1(satisfy(|b| !is_whitespace(b)));
762 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
763 .map(|words: Vec<Vec<u8>>| words.len())
764 },
765 |input, _| combine::easy::Stream::from(input)
766 )
767 .map_err(From::from)
768 .map_err(
769 |err: combine::easy::Errors<u8, &[u8], _>| err.map_range(|r| r.to_owned())
770 )
771 .map_err(|err| err.map_position(|p| p.translate_position(&decoder.buffer()))),
772 Ok(WORDS_IN_README),
773 );
774 })
775 }) as fn(_) -> _,
776 )
777 }
778
779 #[test]
decode_async_std()780 fn decode_async_std() {
781 quickcheck(
782 (|ops: PartialWithErrors<GenWouldBlock>| {
783 let buf = include_bytes!("../README.md");
784 async_std::task::block_on(async {
785 let mut read = FuturesPartialAsyncRead::new(&buf[..], ops);
786 let mut decoder =
787 combine::stream::Decoder::<_, combine::stream::PointerOffset<[u8]>>::new();
788 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
789 assert_eq!(
790 combine::decode_futures_03!(
791 decoder,
792 read,
793 {
794 let word = many1(satisfy(|b| !is_whitespace(b)));
795 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
796 .map(|words: Vec<Vec<u8>>| words.len())
797 },
798 |input, _| combine::easy::Stream::from(input),
799 )
800 .map_err(From::from)
801 .map_err(|err: combine::easy::Errors<u8, &[u8], _>| err),
802 Ok(WORDS_IN_README),
803 );
804 })
805 }) as fn(_) -> _,
806 )
807 }
808
809 #[tokio::test]
decode_loop()810 async fn decode_loop() {
811 use tokio::fs::File;
812
813 use combine::{
814 decode_tokio, many1, satisfy, skip_many1,
815 stream::{buf_reader::BufReader, Decoder},
816 };
817 let mut read = BufReader::new(File::open("README.md").await.unwrap());
818 let mut decoder = Decoder::new_bufferless();
819 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
820
821 let mut count = 0;
822 loop {
823 // async block suppresses a warning about duplicate label
824 if async {
825 decode_tokio!(
826 decoder,
827 read,
828 many1(satisfy(|b| !is_whitespace(b))),
829 |input, _position| combine::easy::Stream::from(input),
830 )
831 .is_err()
832 }
833 .await
834 {
835 break;
836 }
837
838 count += 1;
839
840 {
841 if decode_tokio!(
842 decoder,
843 read,
844 skip_many1(satisfy(is_whitespace)),
845 |input, _position| combine::easy::Stream::from(input),
846 )
847 .is_err()
848 {
849 break;
850 }
851 }
852 }
853 assert_eq!(824, count);
854 }
855