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 {
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 {
while self
.data
.chars()
.next()
.is_some_and(|ch| ch.is_ascii_whitespace())
{
self.data.remove(0);
}
let ws_index = if let Some((i, _ws)) = self
.data
.bytes()
.enumerate()
.find(|(_, b)| b.is_ascii_whitespace())
{
i
} else {
self.data.len()
};
let parsed_result: Result<T, _> = self.data[..ws_index].parse();
if ws_index >= self.data.len() - 1 {
self.data.clear();
} else {
let char_count = self.data[..ws_index].chars().count();
for _ in 0..char_count {
self.data.remove(0);
}
}
*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
}
}