1use std::iter::Peekable;
2use std::str::Chars;
3
4pub struct BufferedInput<'a> {
5 buffer: String,
6 chars: Peekable<Chars<'a>>,
7}
8
9impl<'a> BufferedInput<'a> {
10 pub(crate) fn new(input: &'a str) -> BufferedInput<'a> {
12 BufferedInput {
13 buffer: String::new(),
14 chars: input.chars().peekable(),
15 }
16 }
17
18 pub fn take_buffer(&mut self) -> String {
20 let buffer = self.buffer.clone();
21 self.buffer.clear();
22 buffer
23 }
24
25 #[inline(always)]
27 pub fn peek(&mut self) -> Option<char> {
28 self.chars.peek().map(|&c| c)
29 }
30
31 #[inline(always)]
33 pub fn skip(&mut self) -> Option<char> {
34 self.chars.next()
35 }
36
37 pub fn skip_if<P: Fn(&char) -> bool>(&mut self, predicate: P) -> Option<char> {
39 if let Some(c) = self.peek() {
40 if predicate(&c) {
41 self.skip();
42 return Some(c);
43 }
44 }
45 None
46 }
47
48 pub fn skip_while<P: Fn(&char) -> bool>(&mut self, predicate: P) {
50 while let Some(_) = self.skip_if(&predicate) {}
51 }
52
53 pub fn accept(&mut self) -> Option<char> {
55 if let Some(c) = self.chars.next() {
56 self.buffer.push(c);
57 Some(c)
58 } else {
59 None
60 }
61 }
62
63 pub fn accept_if<P: Fn(&char) -> bool>(&mut self, predicate: P) -> Option<char> {
65 if let Some(c) = self.peek() {
66 if predicate(&c) {
67 self.accept().unwrap();
68 return Some(c)
69 }
70 }
71 None
72 }
73
74 pub fn accept_while<P: Fn(&char) -> bool>(&mut self, predicate: P) {
76 while let Some(_) = self.accept_if(&predicate) {}
77 }
78
79 pub fn accept_or<P: Fn(&char) -> bool, T>(&mut self, predicate: P, ok: T, default: T) -> T {
89 if let Some(_) = self.accept_if(predicate) {
90 ok
91 } else {
92 default
93 }
94 }
95
96 #[inline]
98 pub fn skip_whitespace(&mut self) {
99 self.skip_while(char::is_ascii_whitespace);
100 }
101}