1 use std::collections::HashMap;
2 use std::iter::Iterator;
3 
4 use winnow::ascii::alphanumeric1;
5 use winnow::combinator::iterator;
6 use winnow::combinator::{separated_pair, terminated};
7 use winnow::prelude::*;
8 
main()9 fn main() {
10     let mut data = "abcabcabcabc";
11 
12     fn parser<'s>(i: &mut &'s str) -> PResult<&'s str> {
13         "abc".parse_next(i)
14     }
15 
16     // `from_fn` (available from Rust 1.34) can create an iterator
17     // from a closure
18     let it = std::iter::from_fn(move || {
19         match parser.parse_next(&mut data) {
20             // when successful, a parser returns a tuple of
21             // the remaining input and the output value.
22             // So we replace the captured input data with the
23             // remaining input, to be parsed on the next call
24             Ok(o) => Some(o),
25             _ => None,
26         }
27     });
28 
29     for value in it {
30         println!("parser returned: {}", value);
31     }
32 
33     println!("\n********************\n");
34 
35     let mut data = "abcabcabcabc";
36 
37     // if `from_fn` is not available, it is possible to fold
38     // over an iterator of functions
39     let res = std::iter::repeat(parser)
40         .take(3)
41         .try_fold(Vec::new(), |mut acc, mut parser| {
42             parser.parse_next(&mut data).map(|o| {
43                 acc.push(o);
44                 acc
45             })
46         });
47 
48     // will print "parser iterator returned: Ok(("abc", ["abc", "abc", "abc"]))"
49     println!("\nparser iterator returned: {:?}", res);
50 
51     println!("\n********************\n");
52 
53     let data = "key1:value1,key2:value2,key3:value3,;";
54 
55     // `winnow::combinator::iterator` will return an iterator
56     // producing the parsed values. Compared to the previous
57     // solutions:
58     // - we can work with a normal iterator like `from_fn`
59     // - we can get the remaining input afterwards, like with the `try_fold` trick
60     let mut winnow_it = iterator(
61         data,
62         terminated(separated_pair(alphanumeric1, ":", alphanumeric1), ","),
63     );
64 
65     let res = winnow_it
66         .map(|(k, v)| (k.to_uppercase(), v))
67         .collect::<HashMap<_, _>>();
68 
69     let parser_result: PResult<(_, _), ()> = winnow_it.finish();
70     let (remaining_input, ()) = parser_result.unwrap();
71 
72     // will print "iterator returned {"key1": "value1", "key3": "value3", "key2": "value2"}, remaining input is ';'"
73     println!(
74         "iterator returned {:?}, remaining input is '{}'",
75         res, remaining_input
76     );
77 }
78