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