16855e09eSopenharmony_ciuse std::collections::HashMap;
26855e09eSopenharmony_ciuse std::iter::Iterator;
36855e09eSopenharmony_ci
46855e09eSopenharmony_ciuse nom::bytes::complete::tag;
56855e09eSopenharmony_ciuse nom::character::complete::alphanumeric1;
66855e09eSopenharmony_ciuse nom::combinator::iterator;
76855e09eSopenharmony_ciuse nom::sequence::{separated_pair, terminated};
86855e09eSopenharmony_ciuse nom::IResult;
96855e09eSopenharmony_ci
106855e09eSopenharmony_cifn main() {
116855e09eSopenharmony_ci  let mut data = "abcabcabcabc";
126855e09eSopenharmony_ci
136855e09eSopenharmony_ci  fn parser(i: &str) -> IResult<&str, &str> {
146855e09eSopenharmony_ci    tag("abc")(i)
156855e09eSopenharmony_ci  }
166855e09eSopenharmony_ci
176855e09eSopenharmony_ci  // `from_fn` (available from Rust 1.34) can create an iterator
186855e09eSopenharmony_ci  // from a closure
196855e09eSopenharmony_ci  let it = std::iter::from_fn(move || {
206855e09eSopenharmony_ci    match parser(data) {
216855e09eSopenharmony_ci      // when successful, a nom parser returns a tuple of
226855e09eSopenharmony_ci      // the remaining input and the output value.
236855e09eSopenharmony_ci      // So we replace the captured input data with the
246855e09eSopenharmony_ci      // remaining input, to be parsed on the next call
256855e09eSopenharmony_ci      Ok((i, o)) => {
266855e09eSopenharmony_ci        data = i;
276855e09eSopenharmony_ci        Some(o)
286855e09eSopenharmony_ci      }
296855e09eSopenharmony_ci      _ => None,
306855e09eSopenharmony_ci    }
316855e09eSopenharmony_ci  });
326855e09eSopenharmony_ci
336855e09eSopenharmony_ci  for value in it {
346855e09eSopenharmony_ci    println!("parser returned: {}", value);
356855e09eSopenharmony_ci  }
366855e09eSopenharmony_ci
376855e09eSopenharmony_ci  println!("\n********************\n");
386855e09eSopenharmony_ci
396855e09eSopenharmony_ci  let data = "abcabcabcabc";
406855e09eSopenharmony_ci
416855e09eSopenharmony_ci  // if `from_fn` is not available, it is possible to fold
426855e09eSopenharmony_ci  // over an iterator of functions
436855e09eSopenharmony_ci  let res =
446855e09eSopenharmony_ci    std::iter::repeat(parser)
456855e09eSopenharmony_ci      .take(3)
466855e09eSopenharmony_ci      .try_fold((data, Vec::new()), |(data, mut acc), parser| {
476855e09eSopenharmony_ci        parser(data).map(|(i, o)| {
486855e09eSopenharmony_ci          acc.push(o);
496855e09eSopenharmony_ci          (i, acc)
506855e09eSopenharmony_ci        })
516855e09eSopenharmony_ci      });
526855e09eSopenharmony_ci
536855e09eSopenharmony_ci  // will print "parser iterator returned: Ok(("abc", ["abc", "abc", "abc"]))"
546855e09eSopenharmony_ci  println!("\nparser iterator returned: {:?}", res);
556855e09eSopenharmony_ci
566855e09eSopenharmony_ci  println!("\n********************\n");
576855e09eSopenharmony_ci
586855e09eSopenharmony_ci  let data = "key1:value1,key2:value2,key3:value3,;";
596855e09eSopenharmony_ci
606855e09eSopenharmony_ci  // `nom::combinator::iterator` will return an iterator
616855e09eSopenharmony_ci  // producing the parsed values. Compared to the previous
626855e09eSopenharmony_ci  // solutions:
636855e09eSopenharmony_ci  // - we can work with a normal iterator like `from_fn`
646855e09eSopenharmony_ci  // - we can get the remaining input afterwards, like with the `try_fold` trick
656855e09eSopenharmony_ci  let mut nom_it = iterator(
666855e09eSopenharmony_ci    data,
676855e09eSopenharmony_ci    terminated(
686855e09eSopenharmony_ci      separated_pair(alphanumeric1, tag(":"), alphanumeric1),
696855e09eSopenharmony_ci      tag(","),
706855e09eSopenharmony_ci    ),
716855e09eSopenharmony_ci  );
726855e09eSopenharmony_ci
736855e09eSopenharmony_ci  let res = nom_it
746855e09eSopenharmony_ci    .map(|(k, v)| (k.to_uppercase(), v))
756855e09eSopenharmony_ci    .collect::<HashMap<_, _>>();
766855e09eSopenharmony_ci
776855e09eSopenharmony_ci  let parser_result: IResult<_, _> = nom_it.finish();
786855e09eSopenharmony_ci  let (remaining_input, ()) = parser_result.unwrap();
796855e09eSopenharmony_ci
806855e09eSopenharmony_ci  // will print "iterator returned {"key1": "value1", "key3": "value3", "key2": "value2"}, remaining input is ';'"
816855e09eSopenharmony_ci  println!(
826855e09eSopenharmony_ci    "iterator returned {:?}, remaining input is '{}'",
836855e09eSopenharmony_ci    res, remaining_input
846855e09eSopenharmony_ci  );
856855e09eSopenharmony_ci}
86