text_reader/
textreader.rs

1use std::ffi::OsStr;
2use crate::Detector;
3
4#[derive(Debug)]
5pub struct TextReader {
6  len: usize,
7  text: Vec<char>,
8  position: usize,
9  line: usize,
10  cursor: isize,
11}
12
13///
14/// Text character reader.
15///
16/// # Examples
17/// ```
18/// use text_reader::TextReader;
19/// let mut reader = TextReader::new("abc\ndef");
20/// while reader.has_next() {
21///   let ch = reader.next();
22///   println!("{:?}", ch);
23///   if let Some('\n') = ch {
24///     println!("{:?}", reader.this_line());
25///   }
26/// }
27/// println!("{:?}", reader.this_line());
28/// ```
29impl TextReader {
30  pub fn new<S: AsRef<OsStr>>(text: S) -> TextReader {
31    let chars: Vec<char> = text.as_ref().to_str().unwrap().chars().collect();
32    let len = chars.len();
33    TextReader {
34      text: chars,
35      position: 0,
36      line: 1,
37      len,
38      cursor: 0,
39    }
40  }
41
42  ///
43  /// Detect possible strings
44  ///
45  /// # Examples
46  /// ```
47  /// use text_reader::TextReader;
48  /// let mut reader = TextReader::new("abc\ndef");
49  /// let mut detector = reader.detector();
50  ///
51  /// ```
52  pub fn detector(&mut self) -> Detector {
53    Detector::new(self)
54  }
55
56  ///
57  /// Reset to first character
58  ///
59  /// # Examples
60  /// ```
61  /// use text_reader::TextReader;
62  /// let mut reader = TextReader::new("abc\ndef");
63  /// let reader = reader.reset();
64  /// ```
65  pub fn reset(&mut self) -> &mut TextReader {
66    self.line = 1;
67    self.position = 0;
68    self.cursor = 0;
69    self
70  }
71
72  ///
73  /// Peek current character
74  ///
75  /// # Examples
76  /// ```
77  /// use text_reader::TextReader;
78  /// let mut reader = TextReader::new("abc\ndef");
79  /// let ch = reader.peek();
80  /// ```
81  pub fn peek(&self) -> Option<char> {
82    if self.position == 0 {
83      return None;
84    }
85    if self.position - 1 >= self.len {
86      return None;
87    }
88    self.text.get(self.position - 1).cloned()
89  }
90
91  ///
92  /// Next character
93  ///
94  /// # Examples
95  /// ```
96  /// use text_reader::TextReader;
97  /// let mut reader = TextReader::new("abc\ndef");
98  /// let ch = reader.next();
99  /// ```
100  pub fn next(&mut self) -> Option<char> {
101    if !self.has_next() {
102      return None;
103    }
104    let &ch = self.text.get(self.position).unwrap();
105    self.position += 1;
106    self.cursor += 1;
107
108    if ch == '\n' {
109      self.line += 1;
110      self.cursor = 0;
111    }
112
113    Some(ch)
114  }
115
116  ///
117  /// Position of text
118  ///
119  /// # Examples
120  /// ```
121  /// use text_reader::TextReader;
122  /// let mut reader = TextReader::new("abc\ndef");
123  /// let position = reader.position();
124  /// ```
125  ///
126  pub fn position(&self) -> usize {
127    self.position
128  }
129
130  /// Current text line number
131  /// # Examples
132  /// ```
133  /// use text_reader::TextReader;
134  /// let mut reader = TextReader::new("abc\ndef");
135  /// let line = reader.line();
136  /// ```
137  pub fn line(&self) -> usize {
138    self.line
139  }
140
141  /// Current line position
142  /// # Examples
143  /// ```
144  /// use text_reader::TextReader;
145  /// let mut reader = TextReader::new("abc\ndef");
146  /// reader.next();
147  /// reader.next();
148  /// reader.next();
149  /// reader.next();
150  /// let cursor = reader.cursor();
151  /// println!("CURSOR: {}", cursor); // 2
152  /// ```
153  pub fn cursor(&self) -> usize {
154    self.cursor as usize
155  }
156
157  /// Text length
158  /// # Examples
159  /// ```
160  /// use text_reader::TextReader;
161  /// let reader = TextReader::new("abc\ndef");
162  /// let len = reader.len();
163  /// ```
164  pub fn len(&self) -> usize {
165    self.len
166  }
167
168  ///
169  /// Back to previous character
170  ///
171  /// # Examples
172  ///
173  /// ```
174  /// use text_reader::TextReader;
175  /// let mut reader = TextReader::new("abc\ndef");
176  /// reader.back();
177  /// ```
178  ///
179  pub fn back(&mut self) -> &mut TextReader {
180    if self.position == 0 {
181      return self;
182    }
183
184    match self.peek() {
185      None => return self,
186      Some(ch) => {
187        if ch != '\n' {
188          self.position -= 1;
189          self.cursor -= 1;
190          return self;
191        }
192      }
193    }
194
195    self.position -= 1;
196    self.line -= 1;
197
198    let position = self.position;
199    let line = self.line;
200
201    let mut distance = 0;
202    loop {
203      match self.back().peek() {
204        Some('\n') | None => break,
205        _ => distance += 1
206      }
207    }
208
209    self.position = position;
210    self.line = line;
211    self.cursor = distance + 1;
212    self
213  }
214
215  ///
216  /// Current line string
217  ///
218  /// # Examples
219  /// ```
220  /// use text_reader::TextReader;
221  /// let mut reader = TextReader::new("abc\ndef");
222  /// let line_text = reader.this_line();
223  /// ```
224  pub fn this_line(&mut self) -> Option<String> {
225    let position = self.position;
226    let cursor = self.cursor;
227    let line = self.line;
228
229    loop {
230      if self.position == 0 || self.cursor == 0 {
231        break;
232      }
233
234      match self.back().peek() {
235        Some('\n') => break,
236        _ => continue,
237      }
238    }
239
240    let start_position = self.position;
241
242    while self.has_next() {
243      match self.next() {
244        Some('\n') => {
245          self.back();
246          break;
247        }
248        _ => continue
249      }
250    }
251
252    if start_position == self.position {
253      return None;
254    }
255
256    let line_text = self.text.iter().enumerate()
257      .filter(|(ix, _ch)| *ix >= start_position && *ix < self.position)
258      .map(|(_ix, ch)| ch)
259      .into_iter()
260      .collect();
261
262    self.position = position;
263    self.cursor = cursor;
264    self.line = line;
265
266    Some(line_text)
267  }
268
269  ///
270  /// Has next character
271  ///
272  /// # Examples
273  /// ```
274  /// use text_reader::TextReader;
275  /// let mut reader = TextReader::new("abc\ndef");
276  /// while  reader.has_next(){
277  ///    let ch = reader.next();
278  /// }
279  /// ```
280  pub fn has_next(&self) -> bool {
281    self.position < self.len
282  }
283}
284