1use std::{
57 error::Error,
58 fmt::{self, Display, Formatter},
59 num::{ParseFloatError, ParseIntError},
60 result,
61 str::{Chars, FromStr},
62};
63
64#[derive(Debug, Copy, Clone)]
66pub enum ParseError {
67 EmptyInput,
68 NoMatch,
69}
70
71impl Display for ParseError {
72 fn fmt(&self, f: &mut Formatter) -> result::Result<(), fmt::Error> {
73 let msg = match *self {
74 Self::EmptyInput => "input is empty",
75 Self::NoMatch => "the input does not match",
76 };
77
78 f.write_str(msg)
79 }
80}
81
82impl Error for ParseError {}
83
84pub struct StringReader<'a> {
86 input: Chars<'a>,
87 current: Option<char>,
88}
89
90impl<'a> StringReader<'a> {
91 pub fn new<T>(input: &'a T) -> Self
98 where
99 T: AsRef<str> + ?Sized,
100 {
101 let input = input.as_ref().chars();
102
103 let current = input.clone().next();
106
107 Self { input, current }
108 }
109
110 #[inline]
112 pub fn current_char(&self) -> Option<char> {
113 self.current
114 }
115
116 pub fn read_char(&mut self) -> Result<char, ParseError> {
118 let res = self.input.next().ok_or(ParseError::EmptyInput)?;
119
120 self.current = self.input.clone().next();
122
123 Ok(res)
124 }
125
126 pub fn match_char(&mut self, expected: char) -> Result<(), ParseError> {
134 let c = self.current_char().ok_or(ParseError::EmptyInput)?;
135
136 if c != expected {
137 return Err(ParseError::NoMatch);
138 }
139
140 self.skip_char();
141
142 Ok(())
143 }
144
145 pub fn skip_char(&mut self) {
147 self.input.next();
149
150 self.current = self.input.clone().next();
152 }
153
154 pub fn skip_whitespace(&mut self) {
156 let rest = self.input.as_str().trim_start();
157
158 self.input = rest.chars();
159
160 self.current = self.input.clone().next();
162 }
163
164 pub fn match_str(&mut self, val: &str) -> Result<(), ParseError> {
172 let input = self.input.as_str();
173
174 if input.starts_with(val) {
175 let (_, rest) = input.split_at(val.len());
176
177 self.input = rest.chars();
178
179 self.current = self.input.clone().next();
181
182 Ok(())
183 } else {
184 Err(ParseError::NoMatch)
185 }
186 }
187
188 pub fn read_until<F>(&mut self, cnd: F) -> &'a str
196 where
197 F: FnMut(char) -> bool,
198 {
199 let rest = self.input.as_str();
200
201 let index = rest.find(cnd).unwrap_or_else(|| rest.len());
202
203 self.split_to(index)
204 }
205
206 #[inline]
210 pub fn read_word(&mut self) -> &'a str {
211 self.skip_whitespace();
212 self.read_until(char::is_whitespace)
213 }
214
215 pub fn parse_word<T>(&mut self) -> Result<T, T::Err>
218 where
219 T: FromStr,
220 {
221 let (word, rest) = self.first_word();
222
223 let parsed = word.parse()?;
224
225 self.input = rest.chars();
226
227 self.current = self.input.clone().next();
229
230 Ok(parsed)
231 }
232
233 #[inline]
235 pub fn read_i8(&mut self) -> Result<i8, ParseIntError> {
236 self.parse_word()
237 }
238
239 #[inline]
241 pub fn read_u8(&mut self) -> Result<u8, ParseIntError> {
242 self.parse_word()
243 }
244
245 #[inline]
247 pub fn read_i16(&mut self) -> Result<i16, ParseIntError> {
248 self.parse_word()
249 }
250
251 #[inline]
253 pub fn read_u16(&mut self) -> Result<u16, ParseIntError> {
254 self.parse_word()
255 }
256
257 #[inline]
259 pub fn read_i32(&mut self) -> Result<i32, ParseIntError> {
260 self.parse_word()
261 }
262
263 #[inline]
265 pub fn read_u32(&mut self) -> Result<u32, ParseIntError> {
266 self.parse_word()
267 }
268
269 #[inline]
271 pub fn read_i64(&mut self) -> Result<i64, ParseIntError> {
272 self.parse_word()
273 }
274
275 #[inline]
277 pub fn read_u64(&mut self) -> Result<u64, ParseIntError> {
278 self.parse_word()
279 }
280
281 #[inline]
283 pub fn read_i128(&mut self) -> Result<i128, ParseIntError> {
284 self.parse_word()
285 }
286
287 #[inline]
289 pub fn read_u128(&mut self) -> Result<u128, ParseIntError> {
290 self.parse_word()
291 }
292
293 #[inline]
295 pub fn read_isize(&mut self) -> Result<isize, ParseIntError> {
296 self.parse_word()
297 }
298
299 #[inline]
301 pub fn read_usize(&mut self) -> Result<usize, ParseIntError> {
302 self.parse_word()
303 }
304
305 #[inline]
307 pub fn read_f32(&mut self) -> Result<f32, ParseFloatError> {
308 self.parse_word()
309 }
310
311 #[inline]
313 pub fn read_f64(&mut self) -> Result<f64, ParseFloatError> {
314 self.parse_word()
315 }
316
317 #[inline]
319 pub fn is_empty(&self) -> bool {
320 self.current_char().is_none()
321 }
322
323 #[inline]
325 pub fn as_str(&self) -> &'a str {
326 self.input.as_str()
327 }
328
329 fn first_word(&self) -> (&'a str, &'a str) {
332 let input = self.input.as_str().trim_start();
333
334 let index = input
335 .find(char::is_whitespace)
336 .unwrap_or_else(|| input.len());
337
338 input.split_at(index)
339 }
340
341 fn split_to(&mut self, index: usize) -> &'a str {
345 let rest = self.input.as_str();
346
347 let (word, rest) = rest.split_at(index);
348
349 self.input = rest.chars();
350
351 self.current = self.input.clone().next();
353
354 word
355 }
356}
357
358#[cfg(test)]
359mod tests {
360 use super::StringReader;
361
362 #[test]
363 fn test_reader() {
364 let input = "Hello, World!!! 1234\n\tfoo-bar";
365
366 let mut reader = StringReader::new(input);
367
368 assert!(!reader.is_empty());
369 assert_eq!(reader.current_char(), Some('H'));
370 assert_eq!(reader.as_str(), input);
371
372 let word = reader.read_word();
373
374 assert_eq!(word, "Hello,");
375 assert_eq!(reader.as_str(), " World!!! 1234\n\tfoo-bar");
376
377 reader.skip_whitespace();
378
379 assert_eq!(reader.as_str(), "World!!! 1234\n\tfoo-bar");
380
381 let c = reader.read_char();
382
383 assert_eq!(c.ok(), Some('W'));
384
385 let res = reader.match_char('o');
386
387 assert!(res.is_ok());
388
389 let res = reader.match_char('R');
390
391 assert!(res.is_err());
392
393 let res = reader.match_str("RLD!!!");
394
395 assert!(res.is_err());
396
397 let res = reader.match_str("rld!!!");
398
399 assert!(res.is_ok());
400 assert_eq!(reader.as_str(), " 1234\n\tfoo-bar");
401
402 let n = reader.read_u32();
403
404 assert_eq!(n.ok(), Some(1234));
405 assert_eq!(reader.as_str(), "\n\tfoo-bar");
406
407 let n = reader.read_u32();
408
409 assert!(n.is_err());
410 assert_eq!(reader.as_str(), "\n\tfoo-bar");
411
412 let word = reader.read_word();
413
414 assert_eq!(word, "foo-bar");
415 assert_eq!(reader.as_str(), "");
416 assert!(reader.is_empty());
417
418 let word = reader.read_word();
419
420 assert_eq!(word, "");
421
422 let c = reader.read_char();
423
424 assert!(c.is_err());
425 assert!(reader.is_empty());
426 assert_eq!(reader.as_str(), "");
427 }
428}