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,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 {
281 let content_length = range("Content-Length: ").with(
282 range::recognize(skip_many1(digit())).and_then(|digits: &str| {
283 // Convert the error from `.parse` into an error combine understands
284 digits
285 .parse::<usize>()
286 .map_err(StreamErrorFor::<Input>::other)
287 }),
288 );
289
290 any_send_partial_state(
291 (
292 skip_many(range("\r\n")),
293 content_length,
294 range("\r\n\r\n").map(|_| ()),
295 )
296 .then_partial(|&mut (_, message_length, _)| {
297 take(message_length).map(|bytes: &str| bytes.to_owned())
298 }),
299 )
300 }
301
302 quickcheck! {
303 fn many1_skip_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
304
305 let input = "123\r\n\
306 456\r\n\
307 1\r\n\
308 5\r\n\
309 666666\r\n";
310
311 let result = run_decoder(input, seq, Basic::default());
312
313 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
314 assert_eq!(
315 result.unwrap(),
316 vec!["123".to_string(), "456".to_string(), "1".to_string(), "5".to_string(), "666666".to_string()]
317 );
318 }
319
320 fn prefix_many_then_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
321 impl_decoder!{ TestParser, String, prefix_many_then_parser() }
322
323 let input = "# 1a\
324 # 4abcd\
325 #0\
326 #3:?a\
327 #10abcdefghij";
328
329 let result = run_decoder(input, seq, TestParser::default());
330
331 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
332 assert_eq!(
333 result.unwrap(),
334 ["a", "abcd", "", ":?a", "abcdefghij"]
335 );
336 }
337
338 fn choice_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
339 impl_decoder!{ TestParser, String, choice_parser() }
340
341 let input = "1\r\n\
342 abcd\r\n\
343 123\r\n\
344 abc\r\n\
345 1232751\r\n";
346
347 let result = run_decoder(input, seq, TestParser::default());
348
349 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
350 assert_eq!(
351 result.unwrap(),
352 ["1", "abcd", "123", "abc", "1232751"]
353 );
354 }
355
356 fn recognize_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
357 impl_decoder!{ TestParser, String,
358 recognize(
359 (skip_many1(digit()), optional((char('.'), skip_many(digit()))))
360 )
361 .skip(range(&"\r\n"[..]))
362 }
363
364 let input = "1.0\r\n\
365 123.123\r\n\
366 17824\r\n\
367 3.14\r\n\
368 1.\r\n\
369 2\r\n";
370
371 let result = run_decoder(input, seq, TestParser::default());
372
373 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
374 assert_eq!(
375 result.unwrap(),
376 ["1.0", "123.123", "17824", "3.14", "1.", "2"]
377 );
378 }
379
380 fn recognize_range_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
381 impl_decoder!{ TestParser, String,
382 recognize_with_value(
383 (skip_many1(digit()), optional((char('.'), skip_many(digit()))))
384 )
385 .map(|(r, _)| String::from(r))
386 .skip(range(&"\r\n"[..]))
387 }
388
389 let input = "1.0\r\n\
390 123.123\r\n\
391 17824\r\n\
392 3.14\r\n\
393 1.\r\n\
394 2\r\n";
395
396 let result = run_decoder(input, seq, TestParser::default());
397
398 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
399 assert_eq!(
400 result.unwrap(),
401 ["1.0", "123.123", "17824", "3.14", "1.", "2"]
402 );
403 }
404
405 fn take_while_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
406 impl_decoder!{ TestParser, String,
407 |counter: Rc<Cell<i32>>|
408 take_while(move |c| { counter.set(counter.get() + 1); c != '\r' })
409 .map(String::from)
410 .skip(range("\r\n")),
411 Rc<Cell<i32>>
412 }
413
414 let input = "1.0\r\n\
415 123.123\r\n\
416 17824\r\n\
417 3.14\r\n\
418 \r\n\
419 2\r\n";
420
421 let counter = Rc::new(Cell::new(0));
422 let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));
423
424 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
425 assert_eq!(
426 result.unwrap(),
427 ["1.0", "123.123", "17824", "3.14", "", "2"]
428 );
429
430 assert_eq!(counter.get(), 26);
431 }
432
433 fn take_while1_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
434 impl_decoder!{ TestParser, String,
435 |count: Rc<Cell<i32>>|
436 take_while1(move |c| { count.set(count.get() + 1); c != '\r' })
437 .map(String::from)
438 .skip(range("\r\n")),
439 Rc<Cell<i32>>
440 }
441
442 let input = "1.0\r\n\
443 123.123\r\n\
444 17824\r\n\
445 3.14\r\n\
446 1.\r\n\
447 2\r\n";
448
449 let counter = Rc::new(Cell::new(0));
450 let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));
451
452 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
453 assert_eq!(
454 result.unwrap(),
455 ["1.0", "123.123", "17824", "3.14", "1.", "2"]
456 );
457
458 assert_eq!(counter.get(), 28);
459 }
460
461 fn take_until(seq: PartialWithErrors<GenWouldBlock>) -> () {
462 impl_decoder!{ TestParser, String,
463 |count: Rc<Cell<i32>>|
464 repeat::take_until(token(',').map(move |_| count.set(count.get() + 1))).skip(token(',')),
465 Rc<Cell<i32>>
466 }
467
468 let input = "123,456,789,";
469
470 let counter = Rc::new(Cell::new(0));
471 let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));
472
473 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
474 assert_eq!(
475 result.unwrap(),
476 ["123", "456", "789"]
477 );
478
479 assert_eq!(counter.get(), 3);
480 }
481
482 fn take_until_committed(seq: PartialWithErrors<GenWouldBlock>) -> () {
483 impl_decoder!{ TestParser, String,
484 |count: Rc<Cell<i32>>| {
485 let end = attempt((token(':').map(move |_| count.set(count.get() + 1)), token(':')));
486 repeat::take_until(end).skip((token(':'), token(':')))
487 },
488 Rc<Cell<i32>>
489 }
490
491 let input = "123::456::789::";
492
493 let counter = Rc::new(Cell::new(0));
494 let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));
495
496 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
497 assert_eq!(
498 result.unwrap(),
499 ["123", "456", "789"]
500 );
501
502 assert_eq!(counter.get(), 3);
503 }
504
505 fn take_until_range_committed(seq: PartialWithErrors<GenWouldBlock>) -> () {
506 impl_decoder!{ TestParser, String,
507 take_until_range("::").map(String::from).skip((token(':'), token(':')))
508 }
509
510 let input = "123::456::789::";
511
512 let result = run_decoder(input, seq, TestParser(Default::default()));
513
514 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
515 assert_eq!(result.unwrap(), ["123", "456", "789"]);
516 }
517
518 fn any_send_partial_state_do_not_forget_state(sizes: Vec<usize>, seq: PartialWithErrors<GenWouldBlock>) -> () {
519 impl_decoder!{ TestParser, usize,
520 any_send_partial_state(content_length().map(|bytes| bytes.len()))
521 }
522
523 let input : String = sizes
524 .iter()
525 .map(|s| {
526 format!(
527 "Content-Length: {}\r\n\r\n{}\r\n",
528 s,
529 ::std::iter::repeat('a').take(*s).collect::<String>()
530 )
531 })
532 .collect();
533
534 let result = run_decoder(input.as_bytes(), seq, TestParser(Default::default()));
535
536 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
537 assert_eq!(result.unwrap(), sizes);
538 }
539
540 fn take_fn_test(sizes: Vec<usize>, seq: PartialWithErrors<GenWouldBlock>) -> () {
541 impl_decoder!{ TestParser, usize,
542 take_fn(|s: &str| s.find("\r\n")).map(|bytes: &str| bytes.parse::<usize>().unwrap()).skip(take(2))
543 }
544
545 let input : String = sizes
546 .iter()
547 .map(|s| {
548 format!(
549 "{}\r\n",
550 s,
551 )
552 })
553 .collect();
554
555 let result = run_decoder(input.as_bytes(), seq, TestParser(Default::default()));
556
557 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
558 assert_eq!(result.unwrap(), sizes);
559 }
560
561 fn take_until_bytes_test(sizes: Vec<usize>, seq: PartialWithErrors<GenWouldBlock>) -> () {
562 impl_decoder!{ TestParser, usize,
563 take_until_bytes("\r\n".as_bytes())
564 .map(|bytes: &str| bytes.parse::<usize>().unwrap())
565 .skip(take(2))
566 }
567
568 let input : String = sizes
569 .iter()
570 .map(|s| {
571 format!(
572 "{}\r\n",
573 s,
574 )
575 })
576 .collect();
577
578 let result = run_decoder(input.as_bytes(), seq, TestParser(Default::default()));
579
580 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
581 assert_eq!(result.unwrap(), sizes);
582 }
583
584 fn num_test(ints: Vec<u16>, seq: PartialWithErrors<GenWouldBlock>) -> () {
585 impl_byte_decoder!{ TestParser, u16,
586 num::be_u16()
587 .skip(take(2))
588 }
589
590 let input: Vec<u8> = ints.iter()
591 .flat_map(|i| {
592 let mut v = Vec::new();
593 v.extend_from_slice(&i.to_be_bytes());
594 v.extend_from_slice(b"\r\n");
595 v
596 })
597 .collect();
598
599 let result = run_decoder(&input, seq, TestParser(Default::default()));
600
601 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
602 assert_eq!(result.unwrap(), ints);
603 }
604
605 fn sep_end_by_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
606 impl_decoder!{ TestParser, Vec<String>,
607 repeat::sep_end_by((digit(), digit(), digit()).map(|(a, b, c)| vec![a, b, c].into_iter().collect()), no_partial(string("::")))
608 .skip(no_partial(string("\r\n")))
609 }
610
611 let input = "123::456::789::\r\n";
612
613 let result = run_decoder(&input, seq, TestParser(Default::default()));
614
615 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
616 assert_eq!(result.unwrap(), vec![vec!["123".to_string(), "456".to_string(), "789".to_string()]]);
617 }
618 }
619
620 #[test]
skip_count_min_max_test()621 fn skip_count_min_max_test() {
622 let seq = vec![PartialOp::Limited(1)];
623 impl_decoder! { TestParser, String,
624 repeat::skip_count_min_max(1, 2, char('_')).skip(char('.')).map(|_| "".to_string())
625 }
626
627 let input = "_.";
628
629 let result = run_decoder(input, seq, TestParser::default());
630
631 assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
632 assert_eq!(result.unwrap(), [""]);
633 }
634
635 const WORDS_IN_README: usize = 773;
636
637 #[test]
decode_std()638 fn decode_std() {
639 quickcheck(
640 (|ops: PartialWithErrors<GenNoErrors>| {
641 let buf = include_bytes!("../README.md");
642
643 let mut read = PartialRead::new(&buf[..], ops);
644 let mut decoder =
645 combine::stream::Decoder::<_, combine::stream::PointerOffset<_>>::new();
646 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
647 assert_eq!(
648 combine::decode!(
649 decoder,
650 read,
651 {
652 let word = many1(satisfy(|b| !is_whitespace(b)));
653 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
654 .map(|words: Vec<Vec<u8>>| words.len())
655 },
656 |input, _| combine::easy::Stream::from(input)
657 )
658 .map_err(From::from)
659 .map_err(
660 |err: combine::easy::Errors<u8, &[u8], combine::stream::PointerOffset<_>>| err
661 .map_position(|p| p.0)
662 ),
663 Ok(WORDS_IN_README),
664 );
665 }) as fn(_) -> _,
666 )
667 }
668
669 #[test]
decode_tokio_02()670 fn decode_tokio_02() {
671 quickcheck(
672 (|ops: PartialWithErrors<GenWouldBlock>| {
673 let buf = include_bytes!("../README.md");
674 let runtime = tokio::runtime::Builder::new_current_thread()
675 .build()
676 .unwrap();
677 runtime.block_on(async {
678 let mut read = PartialAsyncRead::new(&buf[..], ops);
679 let mut decoder =
680 combine::stream::Decoder::<_, combine::stream::PointerOffset<[u8]>>::new();
681 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
682 assert_eq!(
683 combine::decode_tokio_02!(
684 decoder,
685 read,
686 {
687 let word = many1(satisfy(|b| !is_whitespace(b)));
688 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
689 .map(|words: Vec<Vec<u8>>| words.len())
690 },
691 |input, _| combine::easy::Stream::from(input)
692 )
693 .map_err(From::from)
694 .map_err(
695 |err: combine::easy::Errors<u8, &[u8], _>| err.map_range(|r| r.to_owned())
696 )
697 .map_err(|err| err.map_position(|p| p.translate_position(&decoder.buffer()))),
698 Ok(WORDS_IN_README),
699 );
700 })
701 }) as fn(_) -> _,
702 )
703 }
704
705 #[test]
decode_tokio_03()706 fn decode_tokio_03() {
707 quickcheck(
708 (|ops: PartialWithErrors<GenWouldBlock>| {
709 let buf = include_bytes!("../README.md");
710 let runtime = tokio::runtime::Builder::new_current_thread()
711 .build()
712 .unwrap();
713 runtime.block_on(async {
714 let mut read = PartialAsyncRead::new(&buf[..], ops);
715 let mut decoder =
716 combine::stream::Decoder::<_, combine::stream::PointerOffset<[u8]>>::new();
717 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
718 assert_eq!(
719 combine::decode_tokio_03!(
720 decoder,
721 read,
722 {
723 let word = many1(satisfy(|b| !is_whitespace(b)));
724 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
725 .map(|words: Vec<Vec<u8>>| words.len())
726 },
727 |input, _| combine::easy::Stream::from(input)
728 )
729 .map_err(From::from)
730 .map_err(
731 |err: combine::easy::Errors<u8, &[u8], _>| err.map_range(|r| r.to_owned())
732 )
733 .map_err(|err| err.map_position(|p| p.translate_position(&decoder.buffer()))),
734 Ok(WORDS_IN_README),
735 );
736 })
737 }) as fn(_) -> _,
738 )
739 }
740
741 #[test]
decode_tokio()742 fn decode_tokio() {
743 quickcheck(
744 (|ops: PartialWithErrors<GenWouldBlock>| {
745 let buf = include_bytes!("../README.md");
746 let runtime = tokio::runtime::Builder::new_current_thread()
747 .build()
748 .unwrap();
749 runtime.block_on(async {
750 let mut read = PartialAsyncRead::new(&buf[..], ops);
751 let mut decoder =
752 combine::stream::Decoder::<_, combine::stream::PointerOffset<[u8]>>::new();
753 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
754 assert_eq!(
755 combine::decode_tokio!(
756 decoder,
757 read,
758 {
759 let word = many1(satisfy(|b| !is_whitespace(b)));
760 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
761 .map(|words: Vec<Vec<u8>>| words.len())
762 },
763 |input, _| combine::easy::Stream::from(input)
764 )
765 .map_err(From::from)
766 .map_err(
767 |err: combine::easy::Errors<u8, &[u8], _>| err.map_range(|r| r.to_owned())
768 )
769 .map_err(|err| err.map_position(|p| p.translate_position(&decoder.buffer()))),
770 Ok(WORDS_IN_README),
771 );
772 })
773 }) as fn(_) -> _,
774 )
775 }
776
777 #[test]
decode_async_std()778 fn decode_async_std() {
779 quickcheck(
780 (|ops: PartialWithErrors<GenWouldBlock>| {
781 let buf = include_bytes!("../README.md");
782 async_std::task::block_on(async {
783 let mut read = FuturesPartialAsyncRead::new(&buf[..], ops);
784 let mut decoder =
785 combine::stream::Decoder::<_, combine::stream::PointerOffset<[u8]>>::new();
786 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
787 assert_eq!(
788 combine::decode_futures_03!(
789 decoder,
790 read,
791 {
792 let word = many1(satisfy(|b| !is_whitespace(b)));
793 sep_end_by(word, skip_many1(satisfy(is_whitespace)))
794 .map(|words: Vec<Vec<u8>>| words.len())
795 },
796 |input, _| combine::easy::Stream::from(input),
797 )
798 .map_err(From::from)
799 .map_err(|err: combine::easy::Errors<u8, &[u8], _>| err),
800 Ok(WORDS_IN_README),
801 );
802 })
803 }) as fn(_) -> _,
804 )
805 }
806
807 #[tokio::test]
decode_loop()808 async fn decode_loop() {
809 use tokio::fs::File;
810
811 use combine::{
812 decode_tokio, many1, satisfy, skip_many1,
813 stream::{buf_reader::BufReader, Decoder},
814 };
815 let mut read = BufReader::new(File::open("README.md").await.unwrap());
816 let mut decoder = Decoder::new_bufferless();
817 let is_whitespace = |b: u8| b == b' ' || b == b'\r' || b == b'\n';
818
819 let mut count = 0;
820 loop {
821 // async block suppresses a warning about duplicate label
822 if async {
823 decode_tokio!(
824 decoder,
825 read,
826 many1(satisfy(|b| !is_whitespace(b))),
827 |input, _position| combine::easy::Stream::from(input),
828 )
829 .is_err()
830 }
831 .await
832 {
833 break;
834 }
835
836 count += 1;
837
838 {
839 if decode_tokio!(
840 decoder,
841 read,
842 skip_many1(satisfy(is_whitespace)),
843 |input, _position| combine::easy::Stream::from(input),
844 )
845 .is_err()
846 {
847 break;
848 }
849 }
850 }
851 assert_eq!(WORDS_IN_README, count);
852 }
853