cppstreams 1.1.0

C++ streams in rust
Documentation
use std::fmt::Display;
use std::io::{Read, Write};
use std::ops::{Shl, Shr};
use std::str::FromStr;

use crate::istream::Status;
use crate::istream::as_read::AsRead;
use crate::ostream::as_write::AsWrite;
use crate::ostream::ostream_impl;
use crate::{IStream, OStream};

pub struct StringStream {
    data: String,
}

impl Default for StringStream {
    #[inline]
    fn default() -> Self {
        StringStream {
            data: String::new(),
        }
    }
}

impl Display for StringStream {
    #[inline]
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(fmt, "{}", self.data)
    }
}

impl std::fmt::Debug for StringStream {
    #[inline]
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(fmt, "{:?}", self.data)
    }
}

impl From<String> for StringStream {
    #[inline]
    fn from(value: String) -> Self {
        StringStream { data: value }
    }
}

impl Write for StringStream {
    #[inline]
    fn write(&mut self, mut buf: &[u8]) -> std::io::Result<usize> {
        buf.read_to_string(&mut self.data)
    }

    #[inline]
    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

impl Read for StringStream {
    /// Has bad performance
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        if buf.is_empty() {
            return Ok(0);
        }
        let data = self.data.as_bytes();
        match data.len().cmp(&buf.len()) {
            std::cmp::Ordering::Less => {
                let read = data.len();
                buf[..read].copy_from_slice(data);
                self.data.clear();
                Ok(read)
            }
            std::cmp::Ordering::Equal => {
                buf.copy_from_slice(data);
                let read = data.len();
                self.data.clear();
                Ok(read)
            }
            std::cmp::Ordering::Greater => {
                let mut i = buf.len();
                loop {
                    if self.data.is_char_boundary(i) {
                        buf[..i].copy_from_slice(&data[..i]);
                        let char_count = std::str::from_utf8(&data[..i]).unwrap().chars().count();
                        for _ in 0..char_count {
                            self.data.remove(0);
                        }
                        break Ok(i);
                    }
                    i -= 1;
                }
            }
        }
    }
}

impl From<StringStream> for IStream<StringStream> {
    #[inline]
    fn from(value: StringStream) -> Self {
        Self::new(value)
    }
}

impl<T: FromStr> Shr<&mut T> for StringStream {
    type Output = Result<crate::istream::Status, T::Err>;

    #[inline]
    fn shr(self, rhs: &mut T) -> Self::Output {
        Into::<IStream<_>>::into(self) >> rhs
    }
}

impl<T: FromStr> Shr<&mut T> for &mut StringStream {
    type Output = Result<crate::istream::Status, T::Err>;

    #[inline]
    fn shr(self, rhs: &mut T) -> Self::Output {
        // strip ascii whitespace from beginning
        while self
            .data
            .chars()
            .next()
            .is_some_and(|ch| ch.is_ascii_whitespace())
        {
            self.data.remove(0);
        }
        // find first ascii whitespace
        let ws_index = if let Some((i, _ws)) = self
            .data
            .bytes()
            .enumerate()
            .find(|(_, b)| b.is_ascii_whitespace())
        {
            i
        } else {
            self.data.len()
        };

        // parse
        let parsed_result: Result<T, _> = self.data[..ws_index].parse();

        // remove read data from data
        if ws_index >= self.data.len() - 1 {
            // no ws or last is ws
            self.data.clear();
        } else {
            let char_count = self.data[..ws_index].chars().count();
            for _ in 0..char_count {
                self.data.remove(0);
            }
        }

        // write parsed back
        *rhs = parsed_result?;

        Ok(Status::ParseSuccess)
    }
}

impl From<StringStream> for OStream<StringStream> {
    #[inline]
    fn from(value: StringStream) -> Self {
        OStream::new(value)
    }
}

impl<T: Display> Shl<T> for StringStream {
    type Output = OStream<StringStream>;

    #[inline]
    fn shl(self, _rhs: T) -> Self::Output {
        Into::<OStream<_>>::into(self) << _rhs
    }
}

impl<T: Display> Shl<T> for &mut StringStream {
    type Output = Self;

    #[inline]
    fn shl(self, _rhs: T) -> Self::Output {
        ostream_impl(self, _rhs);
        self
    }
}

impl AsWrite for StringStream {
    #[inline]
    fn as_write(&mut self) -> impl Write {
        self
    }
}

impl AsWrite for &mut StringStream {
    #[inline]
    fn as_write(&mut self) -> impl Write {
        self
    }
}

impl AsRead for StringStream {
    #[inline]
    fn as_read(&mut self) -> impl Read {
        self
    }
}

impl AsRead for &mut StringStream {
    #[inline]
    fn as_read(&mut self) -> impl Read {
        self
    }
}