cppstreams 1.1.0

C++ streams in rust
Documentation
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 {
                        // ignore whitespace
                        continue;
                    } else {
                        // have already read something
                        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
    }
}