1use std::vec::IntoIter;
2use std::iter::Peekable;
3
4pub trait GentleIterator<I: Iterator> {
5 fn take_until<F>(&mut self, predicate: F) -> IntoIter<I::Item>
6 where F: Fn(&I::Item) -> bool;
7}
8
9impl<I: Iterator> GentleIterator<I> for Peekable<I> {
10 fn take_until<F>(&mut self, predicate: F) -> IntoIter<I::Item>
11 where F: Fn(&I::Item) -> bool {
12
13 let mut v: Vec<I::Item> = vec![];
14 while self.peek().map_or(false, &predicate) {
15 v.push(self.next().unwrap());
16 }
17
18 v.into_iter()
19 }
20}
21
22pub fn check<F,I>(iter: &mut Peekable<I>, fun: F) -> bool
23where F: Fn(char) -> bool,
24 I: Iterator<Item = char> {
25 if let Some(&x) = iter.peek() {
26 fun(x)
27 } else {
28 false
29 }
30}
31
32pub fn check_chr<I>(iter: &mut Peekable<I>, chr: char) -> bool
33where I: Iterator<Item = char> {
34 check(iter, |x| x == chr)
35}
36
37pub fn parse_around<I>(iter: &mut Peekable<I>, beg: char, end: char) -> Option<String>
38where I: Iterator<Item = char> {
39 if !check_chr(iter, beg) {
40 return None
41 }
42
43 iter.next(); let value = iter.take_until(|c| *c != end).collect();
45 iter.next(); parse_whitespace(iter);
47
48 Some(value)
49}
50
51pub fn parse_prefixed<I>(iter: &mut Peekable<I>, chr: char) -> Option<String>
52where I: Iterator<Item = char> {
53 if !check_chr(iter, chr) {
54 return None
55 }
56
57 iter.next(); let value = iter.take_until(|c| *c != ' ').collect();
59 parse_whitespace(iter);
60
61 Some(value)
62}
63
64pub fn parse_plain<I>(iter: &mut Peekable<I>) -> Option<String>
65where I: Iterator<Item = char> {
66 if let Some(&_x) = iter.peek() {
67 let value = iter.take_until(|c| *c != ' ').collect();
68 parse_whitespace(iter);
69
70 return Some(value)
71 }
72
73 None
74}
75
76pub fn parse_whitespace<I>(iter: &mut Peekable<I>) -> bool
77where I: Iterator<Item = char> {
78 if check_chr(iter, ' ') || check_chr(iter, '\n') || check_chr(iter, '\t') {
79 iter.next();
80 true
81 } else {
82 false
83 }
84}