#![cfg_attr(not(feature = "std"), no_std)]
#![deny(missing_docs)]
#![deny(clippy::all)]
#![deny(clippy::cargo)]
#[cfg(feature = "alloc")]
extern crate alloc;
pub trait Read {
type Error;
fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error>;
}
pub trait Write {
type Error;
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error>;
fn flush(&mut self) -> Result<(), Self::Error>;
}
#[cfg(feature = "std")]
impl<T: std::io::Read> Read for T {
type Error = std::io::Error;
#[inline]
fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.read_exact(data)
}
}
#[cfg(feature = "std")]
impl<T: std::io::Write> Write for T {
type Error = std::io::Error;
#[inline]
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.write_all(data)
}
#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
self.flush()
}
}
#[cfg(not(feature = "std"))]
impl<R: Read + ?Sized> Read for &mut R {
type Error = R::Error;
#[inline]
fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
(**self).read_exact(data)
}
}
#[cfg(not(feature = "std"))]
impl<W: Write + ?Sized> Write for &mut W {
type Error = W::Error;
#[inline]
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
(**self).write_all(data)
}
#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
(**self).flush()
}
}
#[cfg(not(feature = "std"))]
#[derive(Debug)]
pub struct EndOfFile(());
#[cfg(not(feature = "std"))]
impl Read for &[u8] {
type Error = EndOfFile;
#[inline]
fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
if data.len() > self.len() {
return Err(EndOfFile(()));
}
let (prefix, suffix) = self.split_at(data.len());
data.copy_from_slice(prefix);
*self = suffix;
Ok(())
}
}
#[cfg(not(feature = "std"))]
#[derive(Debug)]
pub struct OutOfSpace(());
#[cfg(not(feature = "std"))]
impl Write for &mut [u8] {
type Error = OutOfSpace;
#[inline]
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
if data.len() > self.len() {
return Err(OutOfSpace(()));
}
let (prefix, suffix) = core::mem::take(self).split_at_mut(data.len());
prefix.copy_from_slice(data);
*self = suffix;
Ok(())
}
#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
#[cfg(all(not(feature = "std"), feature = "alloc"))]
impl Write for alloc::vec::Vec<u8> {
type Error = core::convert::Infallible;
#[inline]
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.extend_from_slice(data);
Ok(())
}
#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn read_eof() {
let mut reader = &[1u8; 0][..];
let mut buffer = [0u8; 1];
reader.read_exact(&mut buffer[..]).unwrap_err();
}
#[test]
fn read_one() {
let mut reader = &[1u8; 1][..];
let mut buffer = [0u8; 1];
reader.read_exact(&mut buffer[..]).unwrap();
assert_eq!(buffer[0], 1);
reader.read_exact(&mut buffer[..]).unwrap_err();
}
#[test]
fn read_two() {
let mut reader = &[1u8; 2][..];
let mut buffer = [0u8; 1];
reader.read_exact(&mut buffer[..]).unwrap();
assert_eq!(buffer[0], 1);
reader.read_exact(&mut buffer[..]).unwrap();
assert_eq!(buffer[0], 1);
reader.read_exact(&mut buffer[..]).unwrap_err();
}
#[test]
#[cfg(feature = "std")]
fn read_std() {
let mut reader = std::io::repeat(1);
let mut buffer = [0u8; 2];
reader.read_exact(&mut buffer[..]).unwrap();
assert_eq!(buffer[0], 1);
assert_eq!(buffer[1], 1);
}
#[test]
fn write_oos() {
let mut writer = &mut [0u8; 0][..];
writer.write_all(&[1u8; 1][..]).unwrap_err();
}
#[test]
fn write_one() {
let mut buffer = [0u8; 1];
let mut writer = &mut buffer[..];
writer.write_all(&[1u8; 1][..]).unwrap();
writer.write_all(&[1u8; 1][..]).unwrap_err();
assert_eq!(buffer[0], 1);
}
#[test]
fn write_two() {
let mut buffer = [0u8; 2];
let mut writer = &mut buffer[..];
writer.write_all(&[1u8; 1][..]).unwrap();
writer.write_all(&[1u8; 1][..]).unwrap();
writer.write_all(&[1u8; 1][..]).unwrap_err();
assert_eq!(buffer[0], 1);
assert_eq!(buffer[1], 1);
}
#[test]
#[cfg(feature = "alloc")]
fn write_vec() {
let mut buffer = alloc::vec::Vec::new();
buffer.write_all(&[1u8; 1][..]).unwrap();
buffer.write_all(&[1u8; 1][..]).unwrap();
assert_eq!(buffer.len(), 2);
assert_eq!(buffer[0], 1);
assert_eq!(buffer[1], 1);
}
#[test]
#[cfg(feature = "std")]
fn write_std() {
let mut writer = std::io::sink();
writer.write_all(&[1u8; 1][..]).unwrap();
writer.write_all(&[1u8; 1][..]).unwrap();
}
}