chord_parser/
utils.rs

1/// Provides a way to effectively read an object piece by piece.
2pub trait Reader<T>: Iterator {
3    /// Length of the object being read
4    fn len(&self) -> usize;
5    /// Current index position of the reader
6    fn pos(&self) -> usize;
7    /// Reads back several pieces
8    fn rollback(&mut self, amount: usize) -> Result<(), ()>;
9
10    /// Whether the reader has reached the end of the object
11    fn is_end(&self) -> bool {
12        self.len() == 0 || self.len() <= self.pos()
13    }
14
15    /// Reads several pieces and encapsulates into one object
16    fn try_read(&mut self, amount: usize) -> Option<T>;
17}
18
19/// Reads a string character by character.
20pub struct TextReader {
21    pos: usize,
22    text: Vec<char>,
23}
24
25impl Iterator for TextReader {
26    type Item = char;
27
28    /// Reads the next character from the current position
29    fn next(&mut self) -> Option<Self::Item> {
30        let current = self.text.get(self.pos).copied();
31        
32        self.pos += 1;
33
34        current
35    }
36}
37
38impl Reader<String> for TextReader {
39    fn len(&self) -> usize {
40        self.text.len()
41    }
42
43    fn pos(&self) -> usize {
44        self.pos
45    }
46
47    fn rollback(&mut self, amount: usize) -> Result<(), ()> {
48        if self.pos < amount {
49            return Err(());
50        }
51
52        self.pos -= amount;
53
54        Ok(())
55    }
56
57    fn try_read(&mut self, amount: usize) -> Option<String> {
58        let mut s = String::with_capacity(amount);
59
60        let mut left = amount;
61        while left > 0 {
62            if self.is_end() {
63                self.pos -= amount - left;
64                
65                return None;
66            }
67
68            let ch = self.next().unwrap();
69            s.push(ch);
70
71            left -= 1;
72        }
73
74        Some(s)
75    }
76}
77
78impl TextReader {
79    /// Creates an empty reader with empty contents. Isn't particularly useful.
80    pub fn new() -> Self {
81        TextReader { pos: 0, text: vec![] }
82    }
83
84    /// Creates a new reader from the passed text.
85    /// 
86    /// The provided string is copied, and not used since.
87    pub fn from_text(s: &str) -> Self {
88        TextReader { pos: 0, text: s.chars().collect() }
89    }
90
91    /// Reads until a character is encountered.
92    /// 
93    /// If no character was found, everything that has been read by the method is rollbacked.
94    pub fn read_until_char(&mut self, ch: char) -> Option<String> {
95        let mut s = String::new();
96
97        while self.is_end() == false {
98            let read_ch = self.next().unwrap();
99            s.push(read_ch);
100
101            if read_ch == ch {
102                return Some(s);
103            }
104        }
105
106        self.rollback(s.len()).unwrap();
107        None
108    }
109}