|
1 |
| -// todo: This is not good at all and very specific to it's use at the moment. |
2 |
| -// Over time this should be improved. |
3 |
| - |
4 |
| -pub struct CharIterator<'a> { |
5 |
| - chars: std::str::Chars<'a>, |
6 |
| - next_char: Option<char>, |
7 |
| -} |
8 |
| - |
9 |
| -impl<'a> CharIterator<'a> { |
10 |
| - pub fn new(chars: std::str::Chars<'a>) -> CharIterator<'a> { |
11 |
| - CharIterator { chars, next_char: None } |
| 1 | +use std::{iter::Peekable, str::Chars}; |
| 2 | + |
| 3 | +pub trait IteratorCharExt: Iterator<Item = char> { |
| 4 | + fn peek(&mut self) -> Option<&char>; |
| 5 | + |
| 6 | + fn check_text(&mut self, text: &str) -> bool { |
| 7 | + let mut text_iter = text.chars(); |
| 8 | + while let Some(text_ch) = text_iter.next() { |
| 9 | + match self.peek() { |
| 10 | + Some(ch) if *ch == text_ch => self.next(), |
| 11 | + _ => return false, |
| 12 | + }; |
| 13 | + } |
| 14 | + true |
12 | 15 | }
|
13 | 16 |
|
14 |
| - pub fn skip_whitespace(&mut self) { |
15 |
| - while let Some(c) = self.peek_next() { |
16 |
| - if !c.is_whitespace() { |
17 |
| - return; |
18 |
| - } else { |
19 |
| - self.move_next(); |
20 |
| - } |
21 |
| - } |
| 17 | + fn skip_whitespace(&mut self) { |
| 18 | + self.skip_while(char::is_whitespace); |
22 | 19 | }
|
23 | 20 |
|
24 |
| - pub fn skip_spaces(&mut self) { |
25 |
| - while let Some(c) = self.peek_next() { |
26 |
| - if c != ' ' { |
27 |
| - return; |
28 |
| - } else { |
29 |
| - self.move_next(); |
30 |
| - } |
31 |
| - } |
| 21 | + fn skip_spaces(&mut self) { |
| 22 | + self.skip_while(|c| c == ' '); |
32 | 23 | }
|
33 | 24 |
|
34 |
| - pub fn skip_all_until_new_line(&mut self) { |
35 |
| - while let Some(c) = self.move_next() { |
36 |
| - if c == '\r' { |
37 |
| - if self.peek_next() == Some('\n') { |
38 |
| - self.move_next(); |
39 |
| - } |
40 |
| - return; |
41 |
| - } else if c == '\n' { |
42 |
| - return; |
43 |
| - } |
44 |
| - } |
| 25 | + fn skip_all_until_new_line(&mut self) { |
| 26 | + self.skip_while(|c| c != '\n'); |
45 | 27 | }
|
46 | 28 |
|
47 |
| - pub fn check_text(&mut self, text: &str) -> bool { |
48 |
| - for c in text.chars() { |
49 |
| - if let Some(comparison_char) = self.peek_next() { |
50 |
| - if comparison_char != c { |
51 |
| - return false; |
52 |
| - } else { |
53 |
| - self.move_next(); |
54 |
| - } |
55 |
| - } else { |
56 |
| - return false; |
| 29 | + fn skip_while<P: Fn(char) -> bool>(&mut self, predicate: P) { |
| 30 | + while let Some(ch) = self.peek() { |
| 31 | + if !predicate(*ch) { |
| 32 | + break; |
57 | 33 | }
|
| 34 | + self.next(); |
58 | 35 | }
|
59 |
| - |
60 |
| - true |
61 |
| - } |
62 |
| - |
63 |
| - pub fn move_next(&mut self) -> Option<char> { |
64 |
| - self.ensure_next_char(); |
65 |
| - let current_char = self.next_char; |
66 |
| - self.next_char = self.chars.next(); |
67 |
| - current_char |
68 |
| - } |
69 |
| - |
70 |
| - pub fn peek_next(&mut self) -> Option<char> { |
71 |
| - self.ensure_next_char(); |
72 |
| - self.next_char |
73 | 36 | }
|
| 37 | +} |
74 | 38 |
|
75 |
| - fn ensure_next_char(&mut self) { |
76 |
| - if self.next_char.is_none() { |
77 |
| - self.next_char = self.chars.next(); |
78 |
| - } |
| 39 | +impl<'a> IteratorCharExt for Peekable<Chars<'a>> { |
| 40 | + fn peek(&mut self) -> Option<&char> { |
| 41 | + self.peek() |
79 | 42 | }
|
80 | 43 | }
|
0 commit comments