#![deny(
missing_copy_implementations,
missing_debug_implementations,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results,
variant_size_differences,
clippy::all,
warnings
)]
use std::fmt::{self, Debug, Display, Formatter};
use std::io::{self, BufRead, Read};
use std::str::{self, FromStr};
#[derive(Debug)]
pub enum Error<E> {
Io(io::Error),
Utf8(str::Utf8Error),
FromStr(E),
BufferLimitExceeded,
}
pub type Result<T, E = Error<<T as FromStr>::Err>> = std::result::Result<T, E>;
impl<E> From<io::Error> for Error<E> {
fn from(err: io::Error) -> Self {
Error::Io(err)
}
}
impl<E> From<str::Utf8Error> for Error<E> {
fn from(err: str::Utf8Error) -> Self {
Error::Utf8(err)
}
}
impl<E> Display for Error<E> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
match self {
Error::Io(_) => write!(fmt, "I/O Error"),
Error::Utf8(_) => write!(fmt, "Data is not valid utf8"),
Error::FromStr(_) => write!(fmt, "Could not parse given data type"),
Error::BufferLimitExceeded => write!(fmt, "Buffer limit exceeded"),
}
}
}
impl<E: Debug> std::error::Error for Error<E> {}
#[derive(Debug)]
pub struct InputStream<T: BufRead> {
reader: T,
byte_buffer: Vec<u8>,
}
#[inline(always)]
fn is_whitespace(c: u8) -> bool {
match c {
b' ' | b'\x09'...b'\x0d' => true,
_ => false,
}
}
#[inline(always)]
fn act_while<T, F, G, E>(reader: &mut T, mut condition: F, mut act: G) -> Result<(), Error<E>>
where
T: BufRead,
F: FnMut(&&u8) -> bool,
G: FnMut(&[u8]) -> Result<(), Error<E>>,
{
loop {
let (skipped, done) = match reader.fill_buf() {
Ok(buf) => {
let skipped = buf.iter().take_while(&mut condition).count();
act(&buf[..skipped])?;
(skipped, skipped < buf.len() || buf.is_empty())
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => return Err(e.into()),
};
reader.consume(skipped);
if done {
break;
}
}
Ok(())
}
impl<T: BufRead> InputStream<T> {
#[inline(always)]
pub fn new(reader: T) -> InputStream<T> {
InputStream {
reader,
byte_buffer: Vec::new(),
}
}
pub fn scan<F: FromStr>(&mut self) -> Result<F> {
self.inner_scan(None)
}
pub fn scan_with_limit<F: FromStr>(&mut self, limit: usize) -> Result<F> {
self.inner_scan(Some(limit))
}
#[inline(always)]
fn inner_scan<F: FromStr>(&mut self, limit: Option<usize>) -> Result<F> {
let &mut InputStream {
ref mut reader,
ref mut byte_buffer,
} = self;
act_while(reader, |&&c| is_whitespace(c), |_| Ok(()))?;
byte_buffer.clear();
act_while(
reader,
|&&c| !is_whitespace(c),
|slice| {
if let Some(limit) = limit {
if byte_buffer.len() + slice.len() > limit {
return Err(Error::BufferLimitExceeded);
}
}
byte_buffer.extend_from_slice(slice);
Ok(())
},
)?;
let slice = match byte_buffer.split_last() {
Some((&b' ', slice)) => slice,
_ => byte_buffer.as_slice(),
};
str::from_utf8(slice)?.parse().map_err(Error::FromStr)
}
}
impl<T: BufRead> Read for InputStream<T> {
#[inline(always)]
fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
self.reader.read(buffer)
}
}
impl<T: BufRead> BufRead for InputStream<T> {
#[inline(always)]
fn fill_buf(&mut self) -> io::Result<&[u8]> {
self.reader.fill_buf()
}
#[inline(always)]
fn consume(&mut self, amount: usize) {
self.reader.consume(amount)
}
}
#[cfg(test)]
mod tests {
use super::*;
const EPS: f32 = 1e-6;
#[test]
fn simple_strings() {
let text = "Howdy neighbour, how are you doing?";
let mut stream = InputStream::new(text.as_bytes());
let first: String = stream.scan().expect("First string");
let second: String = stream.scan().expect("Second string");
let third: String = stream.scan().expect("Third string");
assert_eq!(first, "Howdy");
assert_eq!(second, "neighbour,");
assert_eq!(third, "how");
}
#[test]
fn simple_numbers() {
let text = "5 -7 12.5 -2.85";
let mut stream = InputStream::new(text.as_bytes());
assert_eq!(5, stream.scan().expect("5"));
assert_eq!(-7, stream.scan().expect("-7"));
assert_eq!(
true,
(12.5 - stream.scan::<f32>().expect("12.5")).abs() < EPS
);
assert_eq!(
true,
(-2.85 - stream.scan::<f32>().expect("-2.85")).abs() < EPS
);
}
#[test]
fn newlines() {
let text = "12\nHello";
let mut stream = InputStream::new(text.as_bytes());
assert_eq!(12, stream.scan().expect("12"));
assert_eq!("Hello", stream.scan::<String>().expect("Hello"));
}
#[test]
fn test_non_utf8() {
let text: [u8; 1] = [255];
let mut stream = InputStream::new(&text[..]);
assert_eq!(true, stream.scan::<i32>().is_err());
}
#[test]
fn test_not_parsing() {
let text = "hello";
let mut stream = InputStream::new(text.as_bytes());
assert_eq!(true, stream.scan::<i32>().is_err());
}
#[test]
fn test_limit_buffer() {
let text = "25 150 -250";
let mut stream = InputStream::new(text.as_bytes());
assert_eq!(25, stream.scan_with_limit(3).expect("25"));
assert_eq!(150, stream.scan_with_limit(3).expect("150"));
assert!(stream.scan_with_limit::<i32>(3).is_err());
}
}