use core::str;
#[cfg(any(feature = "alloc", test))]
use alloc::{string::String, vec::Vec};
mod impls;
mod utils;
#[cfg(test)]
mod test;
#[cfg(any(feature = "std", test))]
pub use impls::to_io;
pub use utils::{buffer::Buffer, copy, counter::Counter, cursor::Cursor, io_fmt::IoFmt};
pub type Result<T> = core::result::Result<T, Error>;
pub type ReadResult = Result<Option<usize>>;
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> ReadResult;
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
while let Some(i) = self.read(buf)? {
buf = &mut buf[i..];
if buf.is_empty() {
break;
}
}
if !buf.is_empty() {
Err(Error::OutOfData)
} else {
Ok(())
}
}
#[cfg(any(feature = "alloc", test))]
fn read_onto_vec(&mut self, buf: &mut Vec<u8>) -> ReadResult {
use core::mem;
if buf.capacity() - buf.len() < 16 {
buf.reserve(16);
}
let uninit = buf.spare_capacity_mut();
uninit.fill(mem::MaybeUninit::new(0));
let target = unsafe { mem::transmute::<&mut [mem::MaybeUninit<u8>], &mut [u8]>(uninit) };
let Some(read) = self.read(target)? else {
return Ok(None);
};
unsafe { buf.set_len(buf.len() + read) };
Ok(Some(read))
}
#[cfg(any(feature = "alloc", test))]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> ReadResult {
let mut read = 0;
while let Some(i) = self.read_onto_vec(buf)? {
read += i;
}
Ok(Some(read))
}
#[cfg(any(feature = "alloc", test))]
fn read_to_string(&mut self, buf: &mut String) -> ReadResult {
let vec = unsafe { buf.as_mut_vec() };
let mut read = 0;
while let Some(i) = self.read_onto_vec(vec)? {
read += i;
}
if let Err(e) = str::from_utf8(vec) {
let _ = vec.drain(e.valid_up_to()..); return Err(Error::Utf8Error(e));
}
Ok(Some(read))
}
}
pub trait Write {
fn write(&mut self, data: &[u8]) -> Result<usize>;
fn flush(&mut self) -> Result<()>;
fn write_all(&mut self, mut data: &[u8]) -> Result<()> {
while !data.is_empty() {
let written = self.write(data)?;
data = &data[written..];
}
Ok(())
}
fn write_args(&mut self, args: crate::fmt::args::Arguments<'_>) -> Result<usize>
where
Self: Sized,
{
let mut writer = IoFmt::new(self);
let _ = args.write(&mut writer);
if let Some(e) = writer.error {
Err(e)
} else {
Ok(writer.written)
}
}
}
pub trait Seek {
fn seek(&mut self, by: isize) -> Result<usize>;
fn seek_to(&mut self, to: usize) -> Result<usize>;
fn seek_from_end(&mut self, by: usize) -> Result<usize>;
fn rewind(&mut self) -> Result<()> {
self.seek_to(0).map(drop)
}
}
#[non_exhaustive]
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Error {
NotFound,
PermissionDenied,
Refused,
Reset,
Unreachable,
Aborted,
Unavailable,
AlreadyExists,
Broken,
InvalidOperation,
InvalidInput,
InvalidData,
TimedOut,
Interrupted,
Unsupported,
OutOfData,
OutOfSpace,
Utf8Error(str::Utf8Error),
Other,
}