1#![deny(
73 missing_copy_implementations,
74 missing_debug_implementations,
75 missing_docs,
76 trivial_casts,
77 trivial_numeric_casts,
78 unsafe_code,
79 unused_extern_crates,
80 unused_import_braces,
81 unused_qualifications,
82 unused_results,
83 variant_size_differences,
84 clippy::all,
85 warnings
86)]
87
88use std::fmt::{self, Debug, Display, Formatter};
89use std::io::{self, BufRead, Read};
90use std::str::{self, FromStr};
91
92#[derive(Debug)]
94pub enum Error<E> {
95 Io(io::Error),
97 Utf8(str::Utf8Error),
99 FromStr(E),
101 BufferLimitExceeded,
103}
104
105pub type Result<T, E = Error<<T as FromStr>::Err>> = std::result::Result<T, E>;
108
109impl<E> From<io::Error> for Error<E> {
110 fn from(err: io::Error) -> Self {
111 Error::Io(err)
112 }
113}
114
115impl<E> From<str::Utf8Error> for Error<E> {
116 fn from(err: str::Utf8Error) -> Self {
117 Error::Utf8(err)
118 }
119}
120
121impl<E> Display for Error<E> {
122 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
123 match self {
124 Error::Io(_) => write!(fmt, "I/O Error"),
125 Error::Utf8(_) => write!(fmt, "Data is not valid utf8"),
126 Error::FromStr(_) => write!(fmt, "Could not parse given data type"),
127 Error::BufferLimitExceeded => write!(fmt, "Buffer limit exceeded"),
128 }
129 }
130}
131
132impl<E: Debug> std::error::Error for Error<E> {}
133
134#[derive(Debug)]
139pub struct InputStream<T: BufRead> {
140 reader: T,
141 byte_buffer: Vec<u8>,
142}
143
144#[inline(always)]
145fn is_whitespace(c: u8) -> bool {
146 match c {
147 b' ' | b'\x09'...b'\x0d' => true,
148 _ => false,
149 }
150}
151
152#[inline(always)]
153fn act_while<T, F, G, E>(reader: &mut T, mut condition: F, mut act: G) -> Result<(), Error<E>>
154where
155 T: BufRead,
156 F: FnMut(&&u8) -> bool,
157 G: FnMut(&[u8]) -> Result<(), Error<E>>,
158{
159 loop {
160 let (skipped, done) = match reader.fill_buf() {
161 Ok(buf) => {
162 let skipped = buf.iter().take_while(&mut condition).count();
163 act(&buf[..skipped])?;
164 (skipped, skipped < buf.len() || buf.is_empty())
165 }
166 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
167 Err(e) => return Err(e.into()),
168 };
169
170 reader.consume(skipped);
171 if done {
172 break;
173 }
174 }
175 Ok(())
176}
177
178impl<T: BufRead> InputStream<T> {
179 #[inline(always)]
182 pub fn new(reader: T) -> InputStream<T> {
183 InputStream {
184 reader,
185 byte_buffer: Vec::new(),
186 }
187 }
188
189 pub fn scan<F: FromStr>(&mut self) -> Result<F> {
195 self.inner_scan(None)
196 }
197
198 pub fn scan_with_limit<F: FromStr>(&mut self, limit: usize) -> Result<F> {
205 self.inner_scan(Some(limit))
206 }
207
208 #[inline(always)]
209 fn inner_scan<F: FromStr>(&mut self, limit: Option<usize>) -> Result<F> {
210 let &mut InputStream {
211 ref mut reader,
212 ref mut byte_buffer,
213 } = self;
214 act_while(reader, |&&c| is_whitespace(c), |_| Ok(()))?;
215 byte_buffer.clear();
216 act_while(
217 reader,
218 |&&c| !is_whitespace(c),
219 |slice| {
220 if let Some(limit) = limit {
221 if byte_buffer.len() + slice.len() > limit {
222 return Err(Error::BufferLimitExceeded);
223 }
224 }
225
226 byte_buffer.extend_from_slice(slice);
227 Ok(())
228 },
229 )?;
230
231 let slice = match byte_buffer.split_last() {
232 Some((&b' ', slice)) => slice,
233 _ => byte_buffer.as_slice(),
234 };
235
236 str::from_utf8(slice)?.parse().map_err(Error::FromStr)
237 }
238}
239
240impl<T: BufRead> Read for InputStream<T> {
241 #[inline(always)]
242 fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
243 self.reader.read(buffer)
244 }
245}
246
247impl<T: BufRead> BufRead for InputStream<T> {
248 #[inline(always)]
249 fn fill_buf(&mut self) -> io::Result<&[u8]> {
250 self.reader.fill_buf()
251 }
252
253 #[inline(always)]
254 fn consume(&mut self, amount: usize) {
255 self.reader.consume(amount)
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262 const EPS: f32 = 1e-6;
263
264 #[test]
265 fn simple_strings() {
266 let text = "Howdy neighbour, how are you doing?";
267 let mut stream = InputStream::new(text.as_bytes());
268
269 let first: String = stream.scan().expect("First string");
270 let second: String = stream.scan().expect("Second string");
271 let third: String = stream.scan().expect("Third string");
272 assert_eq!(first, "Howdy");
273 assert_eq!(second, "neighbour,");
274 assert_eq!(third, "how");
275 }
276
277 #[test]
278 fn simple_numbers() {
279 let text = "5 -7 12.5 -2.85";
280 let mut stream = InputStream::new(text.as_bytes());
281 assert_eq!(5, stream.scan().expect("5"));
282 assert_eq!(-7, stream.scan().expect("-7"));
283 assert_eq!(
284 true,
285 (12.5 - stream.scan::<f32>().expect("12.5")).abs() < EPS
286 );
287 assert_eq!(
288 true,
289 (-2.85 - stream.scan::<f32>().expect("-2.85")).abs() < EPS
290 );
291 }
292
293 #[test]
294 fn newlines() {
295 let text = "12\nHello";
296 let mut stream = InputStream::new(text.as_bytes());
297 assert_eq!(12, stream.scan().expect("12"));
298 assert_eq!("Hello", stream.scan::<String>().expect("Hello"));
299 }
300
301 #[test]
302 fn test_non_utf8() {
303 let text: [u8; 1] = [255];
304 let mut stream = InputStream::new(&text[..]);
305 assert_eq!(true, stream.scan::<i32>().is_err());
306 }
307
308 #[test]
309 fn test_not_parsing() {
310 let text = "hello";
311 let mut stream = InputStream::new(text.as_bytes());
312 assert_eq!(true, stream.scan::<i32>().is_err());
313 }
314
315 #[test]
316 fn test_limit_buffer() {
317 let text = "25 150 -250";
318 let mut stream = InputStream::new(text.as_bytes());
319 assert_eq!(25, stream.scan_with_limit(3).expect("25"));
320 assert_eq!(150, stream.scan_with_limit(3).expect("150"));
321 assert!(stream.scan_with_limit::<i32>(3).is_err());
322 }
323}