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