#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(missing_docs)]
#![doc = include_str!("../README.md")]
use core::fmt;
#[cfg(feature = "alloc")]
extern crate alloc;
mod impls;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SeekFrom {
Start(u64),
End(i64),
Current(i64),
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<SeekFrom> for std::io::SeekFrom {
fn from(pos: SeekFrom) -> Self {
match pos {
SeekFrom::Start(n) => std::io::SeekFrom::Start(n),
SeekFrom::End(n) => std::io::SeekFrom::End(n),
SeekFrom::Current(n) => std::io::SeekFrom::Current(n),
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<std::io::SeekFrom> for SeekFrom {
fn from(pos: std::io::SeekFrom) -> SeekFrom {
match pos {
std::io::SeekFrom::Start(n) => SeekFrom::Start(n),
std::io::SeekFrom::End(n) => SeekFrom::End(n),
std::io::SeekFrom::Current(n) => SeekFrom::Current(n),
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum ErrorKind {
Other,
NotFound,
PermissionDenied,
ConnectionRefused,
ConnectionReset,
ConnectionAborted,
NotConnected,
AddrInUse,
AddrNotAvailable,
BrokenPipe,
AlreadyExists,
InvalidInput,
InvalidData,
TimedOut,
Interrupted,
Unsupported,
OutOfMemory,
WriteZero,
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<ErrorKind> for std::io::ErrorKind {
fn from(value: ErrorKind) -> Self {
match value {
ErrorKind::NotFound => std::io::ErrorKind::NotFound,
ErrorKind::PermissionDenied => std::io::ErrorKind::PermissionDenied,
ErrorKind::ConnectionRefused => std::io::ErrorKind::ConnectionRefused,
ErrorKind::ConnectionReset => std::io::ErrorKind::ConnectionReset,
ErrorKind::ConnectionAborted => std::io::ErrorKind::ConnectionAborted,
ErrorKind::NotConnected => std::io::ErrorKind::NotConnected,
ErrorKind::AddrInUse => std::io::ErrorKind::AddrInUse,
ErrorKind::AddrNotAvailable => std::io::ErrorKind::AddrNotAvailable,
ErrorKind::BrokenPipe => std::io::ErrorKind::BrokenPipe,
ErrorKind::AlreadyExists => std::io::ErrorKind::AlreadyExists,
ErrorKind::InvalidInput => std::io::ErrorKind::InvalidInput,
ErrorKind::InvalidData => std::io::ErrorKind::InvalidData,
ErrorKind::TimedOut => std::io::ErrorKind::TimedOut,
ErrorKind::Interrupted => std::io::ErrorKind::Interrupted,
ErrorKind::Unsupported => std::io::ErrorKind::Unsupported,
ErrorKind::OutOfMemory => std::io::ErrorKind::OutOfMemory,
ErrorKind::WriteZero => std::io::ErrorKind::WriteZero,
_ => std::io::ErrorKind::Other,
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<std::io::ErrorKind> for ErrorKind {
fn from(value: std::io::ErrorKind) -> Self {
match value {
std::io::ErrorKind::NotFound => ErrorKind::NotFound,
std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
std::io::ErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
std::io::ErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
std::io::ErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
std::io::ErrorKind::NotConnected => ErrorKind::NotConnected,
std::io::ErrorKind::AddrInUse => ErrorKind::AddrInUse,
std::io::ErrorKind::AddrNotAvailable => ErrorKind::AddrNotAvailable,
std::io::ErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
std::io::ErrorKind::AlreadyExists => ErrorKind::AlreadyExists,
std::io::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
std::io::ErrorKind::InvalidData => ErrorKind::InvalidData,
std::io::ErrorKind::TimedOut => ErrorKind::TimedOut,
std::io::ErrorKind::Interrupted => ErrorKind::Interrupted,
std::io::ErrorKind::Unsupported => ErrorKind::Unsupported,
std::io::ErrorKind::OutOfMemory => ErrorKind::OutOfMemory,
std::io::ErrorKind::WriteZero => ErrorKind::WriteZero,
_ => ErrorKind::Other,
}
}
}
pub trait Error: core::error::Error {
fn kind(&self) -> ErrorKind;
}
impl Error for core::convert::Infallible {
fn kind(&self) -> ErrorKind {
match *self {}
}
}
impl Error for ErrorKind {
fn kind(&self) -> ErrorKind {
*self
}
}
impl core::error::Error for ErrorKind {}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Error for std::io::Error {
fn kind(&self) -> ErrorKind {
self.kind().into()
}
}
pub trait ErrorType {
type Error: Error;
}
impl<T: ?Sized + ErrorType> ErrorType for &mut T {
type Error = T::Error;
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ReadExactError<E> {
UnexpectedEof,
Other(E),
}
impl<E> From<E> for ReadExactError<E> {
fn from(err: E) -> Self {
Self::Other(err)
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<ReadExactError<std::io::Error>> for std::io::Error {
fn from(err: ReadExactError<std::io::Error>) -> Self {
match err {
ReadExactError::UnexpectedEof => std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"UnexpectedEof".to_owned(),
),
ReadExactError::Other(e) => std::io::Error::new(e.kind(), format!("{e:?}")),
}
}
}
impl<E: fmt::Debug> fmt::Display for ReadExactError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl<E: fmt::Debug> core::error::Error for ReadExactError<E> {}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum SliceWriteError {
Full,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum WriteFmtError<E> {
FmtError,
Other(E),
}
impl<E> From<E> for WriteFmtError<E> {
fn from(err: E) -> Self {
Self::Other(err)
}
}
impl<E: fmt::Debug> fmt::Display for WriteFmtError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl<E: fmt::Debug> core::error::Error for WriteFmtError<E> {}
pub trait Read: ErrorType {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
while !buf.is_empty() {
match self.read(buf) {
Ok(0) => break,
Ok(n) => buf = &mut buf[n..],
Err(e) => return Err(ReadExactError::Other(e)),
}
}
if buf.is_empty() {
Ok(())
} else {
Err(ReadExactError::UnexpectedEof)
}
}
}
pub trait BufRead: Read {
fn fill_buf(&mut self) -> Result<&[u8], Self::Error>;
fn consume(&mut self, amt: usize);
}
pub trait Write: ErrorType {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error>;
fn flush(&mut self) -> Result<(), Self::Error>;
fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Self::Error> {
while !buf.is_empty() {
match self.write(buf) {
Ok(0) => panic!("write() returned Ok(0)"),
Ok(n) => buf = &buf[n..],
Err(e) => return Err(e),
}
}
Ok(())
}
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<(), WriteFmtError<Self::Error>> {
struct Adapter<'a, T: Write + ?Sized + 'a> {
inner: &'a mut T,
error: Result<(), T::Error>,
}
impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.inner.write_all(s.as_bytes()) {
Ok(()) => Ok(()),
Err(e) => {
self.error = Err(e);
Err(fmt::Error)
}
}
}
}
let mut output = Adapter {
inner: self,
error: Ok(()),
};
match fmt::write(&mut output, fmt) {
Ok(()) => Ok(()),
Err(..) => match output.error {
Err(e) => Err(WriteFmtError::Other(e)),
Ok(()) => Err(WriteFmtError::FmtError),
},
}
}
}
pub trait Seek: ErrorType {
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error>;
fn rewind(&mut self) -> Result<(), Self::Error> {
self.seek(SeekFrom::Start(0))?;
Ok(())
}
fn stream_position(&mut self) -> Result<u64, Self::Error> {
self.seek(SeekFrom::Current(0))
}
fn seek_relative(&mut self, offset: i64) -> Result<(), Self::Error> {
self.seek(SeekFrom::Current(offset))?;
Ok(())
}
}
pub trait ReadReady: ErrorType {
fn read_ready(&mut self) -> Result<bool, Self::Error>;
}
pub trait WriteReady: ErrorType {
fn write_ready(&mut self) -> Result<bool, Self::Error>;
}
impl<T: ?Sized + Read> Read for &mut T {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
T::read(self, buf)
}
#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
T::read_exact(self, buf)
}
}
impl<T: ?Sized + BufRead> BufRead for &mut T {
#[inline]
fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
T::fill_buf(self)
}
#[inline]
fn consume(&mut self, amt: usize) {
T::consume(self, amt);
}
}
impl<T: ?Sized + Write> Write for &mut T {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
T::write(self, buf)
}
#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
T::flush(self)
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
T::write_all(self, buf)
}
}
impl<T: ?Sized + Seek> Seek for &mut T {
#[inline]
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
T::seek(self, pos)
}
#[inline]
fn rewind(&mut self) -> Result<(), Self::Error> {
T::rewind(self)
}
#[inline]
fn stream_position(&mut self) -> Result<u64, Self::Error> {
T::stream_position(self)
}
#[inline]
fn seek_relative(&mut self, offset: i64) -> Result<(), Self::Error> {
T::seek_relative(self, offset)
}
}
impl<T: ?Sized + ReadReady> ReadReady for &mut T {
#[inline]
fn read_ready(&mut self) -> Result<bool, Self::Error> {
T::read_ready(self)
}
}
impl<T: ?Sized + WriteReady> WriteReady for &mut T {
#[inline]
fn write_ready(&mut self) -> Result<bool, Self::Error> {
T::write_ready(self)
}
}