1use crate::span::{Location, Result, Span};
13
14pub trait InputStream {
16 type CharType;
18
19 fn next_char_loc(&mut self) -> Result<(Option<Self::CharType>, Location)>;
25
26 fn unread(&mut self, last: (Option<Self::CharType>, Location));
29
30 fn span(&self) -> &Span;
32
33 fn set_line_col(&mut self, line: u32, col: u32);
43
44 fn next_char(&mut self) -> Result<Option<Self::CharType>> {
50 self.next_char_loc().map(|(c, _)| c)
51 }
52
53 fn next_char_span(&mut self) -> Result<(Option<Self::CharType>, Span)> {
59 self.next_char_loc().map(|(c, _)| (c, self.span().clone()))
60 }
61
62 fn next_span(&mut self) -> Result<&Span> {
67 self.next_char_loc()?;
68 Ok(self.span())
69 }
70
71 fn peek(&mut self) -> Result<Option<Self::CharType>>
75 where
76 Self::CharType: Clone,
77 {
78 let (c, loc) = self.next_char_loc()?;
79 self.unread((c.clone(), loc));
80 Ok(c)
81 }
82
83 fn peek_with_span(&mut self) -> Result<(Option<Self::CharType>, Span)>
88 where
89 Self::CharType: Clone,
90 {
91 let (c, loc) = self.next_char_loc()?;
92 let span = self.span().clone();
93 self.unread((c.clone(), loc));
94 Ok((c, span))
95 }
96
97 fn skip_until<F>(&mut self, mut f: F) -> Result<()>
99 where
100 Self::CharType: Clone,
101 F: FnMut(Self::CharType) -> bool,
102 {
103 while self.peek()?.map_or(false, |c| !f(c)) {
104 self.next_char()?;
105 }
106 Ok(())
107 }
108
109 fn collect_until<F>(&mut self, mut f: F) -> Result<Vec<Self::CharType>>
112 where
113 Self::CharType: Clone,
114 F: FnMut(&Self::CharType) -> bool,
115 {
116 let mut v = Vec::new();
117 while let Some(c) = self.peek()? {
118 if f(&c) {
119 break;
120 }
121 v.push(c);
122 self.next_char()?;
123 }
124 Ok(v)
125 }
126
127 fn collect_with_span_until<F>(&mut self, mut f: F) -> Result<(Vec<Self::CharType>, Span)>
132 where
133 Self::CharType: Clone,
134 F: FnMut(&Self::CharType) -> bool,
135 {
136 let mut v = Vec::new();
137 let mut span = match self.peek_with_span()? {
138 (Some(c), span) if !f(&c) => span,
139 (_, span) => return Ok((v, span)),
140 };
141 while let Some(c) = self.peek()? {
142 if f(&c) {
143 break;
144 }
145 v.push(c);
146 span.update_end(self.next_span()?);
147 }
148 Ok((v, span))
149 }
150}
151
152#[cfg(test)]
153mod test {
154 use super::*;
155 use crate::reader::Reader;
156
157 #[test]
158 fn next_char_or_span() {
159 let mut reader = Reader::from("123 abc");
160 assert_eq!(reader.next_char(), Ok(Some('1')));
161 assert_eq!(reader.next_char(), Ok(Some('2')));
162 let (c, span) = reader.next_char_span().unwrap();
163 assert_eq!(c, Some('3'));
164 assert_eq!(format!("{span}"), "1:3-1:3");
165 let (c, span) = reader.next_char_span().unwrap();
166 assert_eq!(c, Some(' '));
167 assert_eq!(format!("{span}"), "1:4-1:4");
168 assert_eq!(format!("{}", reader.next_span().unwrap()), "1:5-1:5");
169 assert_eq!(format!("{}", reader.next_span().unwrap()), "1:6-1:6");
170 assert_eq!(reader.next_char(), Ok(Some('c')));
171 assert_eq!(reader.next_char(), Ok(None));
172 assert_eq!(reader.next_char(), Ok(None));
173 }
174
175 #[test]
176 fn skip_until() {
177 let mut reader = Reader::from("123 abc");
178 assert_eq!(reader.skip_until(|c| c.is_whitespace()), Ok(()));
179 assert_eq!(reader.next_char(), Ok(Some(' ')));
180 assert_eq!(reader.next_char(), Ok(Some(' ')));
181 assert_eq!(reader.next_char(), Ok(Some('a')));
182 assert_eq!(reader.next_char(), Ok(Some('b')));
183 assert_eq!(reader.next_char(), Ok(Some('c')));
184 assert_eq!(reader.next_char(), Ok(None));
185 assert_eq!(reader.next_char(), Ok(None));
186 }
187
188 #[test]
189 fn collect_until() {
190 let mut reader = Reader::from("123 abc");
191 assert_eq!(reader.collect_until(|c| *c == '1'), Ok(vec![]));
192 assert_eq!(
193 reader.collect_with_span_until(|c| *c == '1').unwrap().0,
194 vec![]
195 );
196 assert_eq!(
197 reader.collect_until(|c| c.is_whitespace()),
198 Ok("123".chars().collect())
199 );
200 assert_eq!(reader.next_char(), Ok(Some(' ')));
201 let (s, span) = reader.collect_with_span_until(|_| false).unwrap();
202 assert_eq!(s, "abc".chars().collect::<Vec<_>>());
203 assert_eq!(format!("{span}"), "1:5-1:7");
204 assert_eq!(reader.next_char(), Ok(None));
205 assert_eq!(reader.next_char(), Ok(None));
206 }
207}