use std::io::Read;
use std::ops::Shr;
use std::str::FromStr;
use super::as_read::AsRead;
pub struct IStream<R: Read>(R);
impl<R: Read> IStream<R> {
#[inline]
pub const fn new(reader: R) -> Self {
IStream(reader)
}
#[inline]
pub fn into_innter(self) -> R {
self.0
}
}
impl<R: Read> Read for IStream<R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.0.read(buf)
}
}
#[repr(u8)]
pub enum Status {
IoError,
ParseSuccess,
}
impl Status {
#[inline]
pub const fn success(&self) -> bool {
match self {
Status::ParseSuccess => true,
Status::IoError => false,
}
}
}
impl<R: Read, T: FromStr> Shr<&mut T> for IStream<R> {
type Output = Result<Status, T::Err>;
#[inline]
fn shr(mut self, rhs: &mut T) -> Self::Output {
&mut self >> rhs
}
}
impl<R: Read, T: FromStr> Shr<&mut T> for &mut IStream<R> {
type Output = Result<Status, T::Err>;
#[inline]
fn shr(self, rhs: &mut T) -> Self::Output {
istream_impl(&mut self.0, rhs)
}
}
#[inline]
pub(crate) fn istream_impl<T: FromStr>(
reader: &mut impl Read,
out: &mut T,
) -> Result<Status, T::Err> {
let mut buffer: Vec<u8> = vec![0];
loop {
match reader.read(std::slice::from_mut(buffer.last_mut().expect("has last"))) {
Ok(read) => {
if read == 0 {
buffer.pop();
break;
} else if char::from(*buffer.last().expect("has last")).is_ascii_whitespace() {
if buffer.len() == 1 {
continue;
} else {
buffer.pop();
break;
}
} else {
buffer.push(0);
}
}
Err(_) => return Ok(Status::IoError),
}
}
let string = String::from_utf8_lossy(&buffer);
*out = string.as_ref().parse()?;
Ok(Status::ParseSuccess)
}
impl<R: Read> AsRead for IStream<R> {
#[inline]
fn as_read(&mut self) -> impl Read {
&mut self.0
}
}
impl<R: Read> AsRead for &mut IStream<R> {
#[inline]
fn as_read(&mut self) -> impl Read {
&mut self.0
}
}