mod error;
mod stdio;
use core::{fmt::Arguments, marker::PhantomData};
use alloc::{string::{String, ToString}, vec::Vec};
pub use error::IOError as Error;
use heapless::format;
pub(crate) use error::WithPath;
pub type Stdin = stdio::StdInput<0>;
pub type Stdout = stdio::StdOutput<1>;
pub type Stderr = stdio::StdOutput<2>;
pub fn stdin() -> Stdin {
Stdin {
_hidden: PhantomData
}
}
pub fn stdout() -> Stdout {
Stdout {
_hidden: PhantomData
}
}
pub fn stderr() -> Stderr {
Stderr {
_hidden: PhantomData
}
}
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>;
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error> {
let mut read = 0;
let mut loops = 0;
loop {
if loops > 16 {
panic!("IO Timeout");
}
let mut buffer = [0; 0x1000 * 16];
let bytes = self.read(&mut buffer)?;
read += bytes;
buf.extend_from_slice(&buffer[0..bytes]);
if bytes < buffer.len() {
break;
}
loops += 1;
}
Ok(read)
}
fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error> {
self.read_to_end(unsafe { buf.as_mut_vec() })
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error> {
let bytes = self.read(buf)?;
if bytes < buf.len() {
Err(Error::EndOfFile)
} else {
Ok(())
}
}
fn read_array<const N: usize>(&mut self) -> Result<[u8; N], Error> where Self: Sized {
let mut array = [0; N];
self.read_exact(&mut array)?;
Ok(array)
}
}
pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
fn flush(&mut self) -> Result<(), Error>;
fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Error> {
while !buf.is_empty() {
let written = self.write(buf)?;
buf = &buf[written..];
}
Ok(())
}
fn write_fmt(&mut self, args: Arguments<'_>) -> Result<(), Error> {
let string: Result<heapless::String<4096>, _> = format!("{args}");
if let Ok(string) = string {
self.write_all(string.as_bytes())
} else {
self.write_all(args.to_string().as_bytes())
}
}
}
pub trait Seek {
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error>;
fn rewind(&mut self) -> Result<(), Error> {
self.seek(SeekFrom::Start(0)).map(|_| ())
}
fn stream_position(&mut self) -> Result<u64, Error> {
self.seek(SeekFrom::Current(0))
}
fn seek_relative(&mut self, offset: i64) -> Result<(), Error> {
self.seek(SeekFrom::Current(offset)).map(|_| ())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SeekFrom {
Start(u64),
End(i64),
Current(i64),
}