File: iterator.rs

package info (click to toggle)
rust-winnow 0.7.13-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,592 kB
  • sloc: makefile: 2
file content (65 lines) | stat: -rw-r--r-- 2,090 bytes parent folder | download | duplicates (27)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::collections::HashMap;
use std::iter::Iterator;

use winnow::ascii::alphanumeric1;
use winnow::combinator::iterator;
use winnow::combinator::{separated_pair, terminated};
use winnow::prelude::*;

fn main() {
    let mut data = "abcabcabcabc";

    fn parser<'s>(i: &mut &'s str) -> ModalResult<&'s str> {
        "abc".parse_next(i)
    }

    // `from_fn` (available from Rust 1.34) can create an iterator
    // from a closure
    let it = std::iter::from_fn(move || parser.parse_next(&mut data).ok());

    for value in it {
        println!("parser returned: {value}");
    }

    println!("\n********************\n");

    let mut data = "abcabcabcabc";

    // if `from_fn` is not available, it is possible to fold
    // over an iterator of functions
    let res = std::iter::repeat(parser)
        .take(3)
        .try_fold(Vec::new(), |mut acc, mut parser| {
            parser.parse_next(&mut data).map(|o| {
                acc.push(o);
                acc
            })
        });

    // will print "parser iterator returned: Ok(("abc", ["abc", "abc", "abc"]))"
    println!("\nparser iterator returned: {res:?}");

    println!("\n********************\n");

    let data = "key1:value1,key2:value2,key3:value3,;";

    // `winnow::combinator::iterator` will return an iterator
    // producing the parsed values. Compared to the previous
    // solutions:
    // - we can work with a normal iterator like `from_fn`
    // - we can get the remaining input afterwards, like with the `try_fold` trick
    let mut winnow_it = iterator(
        data,
        terminated(separated_pair(alphanumeric1, ":", alphanumeric1), ","),
    );

    let res = winnow_it
        .map(|(k, v)| (k.to_uppercase(), v))
        .collect::<HashMap<_, _>>();

    let parser_result: ModalResult<(_, _), ()> = winnow_it.finish();
    let (remaining_input, ()) = parser_result.unwrap();

    // will print "iterator returned {"key1": "value1", "key3": "value3", "key2": "value2"}, remaining input is ';'"
    println!("iterator returned {res:?}, remaining input is '{remaining_input}'");
}