use alloc::boxed::Box;
use alloc::string::String;
use core::fmt;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ErrorKind {
AlreadyExists,
BrokenPipe,
CrossesDevices,
Interrupted,
InvalidData,
InvalidInput,
NotFound,
Other,
PermissionDenied,
UnexpectedEof,
Unsupported,
WriteZero,
}
impl ErrorKind {
fn as_str(self) -> &'static str {
match self {
Self::AlreadyExists => "entity already exists",
Self::BrokenPipe => "broken pipe",
Self::CrossesDevices => "cross-device link or rename",
Self::Interrupted => "operation interrupted",
Self::InvalidData => "invalid data",
Self::InvalidInput => "invalid input parameter",
Self::NotFound => "entity not found",
Self::Other => "other error",
Self::PermissionDenied => "permission denied",
Self::UnexpectedEof => "unexpected end of file",
Self::Unsupported => "unsupported",
Self::WriteZero => "write returned 0 bytes",
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
pub struct Error {
kind: ErrorKind,
message: Option<Box<str>>,
}
impl Error {
pub fn new<M: Into<String>>(kind: ErrorKind, message: M) -> Self {
Self {
kind,
message: Some(message.into().into_boxed_str()),
}
}
#[must_use]
pub const fn from_kind(kind: ErrorKind) -> Self {
Self {
kind,
message: None,
}
}
#[must_use]
pub const fn kind(&self) -> ErrorKind {
self.kind
}
pub fn other<M: Into<String>>(message: M) -> Self {
Self::new(ErrorKind::Other, message)
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Self {
Self::from_kind(kind)
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut dbg = f.debug_struct("Error");
dbg.field("kind", &self.kind);
if let Some(msg) = &self.message {
dbg.field("message", msg);
}
dbg.finish()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.message {
Some(msg) => write!(f, "{}: {msg}", self.kind.as_str()),
None => f.write_str(self.kind.as_str()),
}
}
}
impl core::error::Error for Error {}
#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
let std_kind = err.kind();
let (kind, kind_is_mapped) = match std_kind {
std::io::ErrorKind::AlreadyExists => (ErrorKind::AlreadyExists, true),
std::io::ErrorKind::BrokenPipe => (ErrorKind::BrokenPipe, true),
std::io::ErrorKind::CrossesDevices => (ErrorKind::CrossesDevices, true),
std::io::ErrorKind::Interrupted => (ErrorKind::Interrupted, true),
std::io::ErrorKind::InvalidData => (ErrorKind::InvalidData, true),
std::io::ErrorKind::InvalidInput => (ErrorKind::InvalidInput, true),
std::io::ErrorKind::NotFound => (ErrorKind::NotFound, true),
std::io::ErrorKind::PermissionDenied => (ErrorKind::PermissionDenied, true),
std::io::ErrorKind::UnexpectedEof => (ErrorKind::UnexpectedEof, true),
std::io::ErrorKind::Unsupported => (ErrorKind::Unsupported, true),
std::io::ErrorKind::WriteZero => (ErrorKind::WriteZero, true),
std::io::ErrorKind::Other => (ErrorKind::Other, true),
_ => (ErrorKind::Other, false),
};
if err.raw_os_error().is_some() || err.get_ref().is_some() {
Self::new(kind, alloc::format!("{err}"))
} else if kind_is_mapped {
Self::from_kind(kind)
} else {
Self::new(kind, alloc::format!("{err}"))
}
}
}
#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
fn from(err: Error) -> Self {
let kind = match err.kind {
ErrorKind::AlreadyExists => std::io::ErrorKind::AlreadyExists,
ErrorKind::BrokenPipe => std::io::ErrorKind::BrokenPipe,
ErrorKind::CrossesDevices => std::io::ErrorKind::CrossesDevices,
ErrorKind::Interrupted => std::io::ErrorKind::Interrupted,
ErrorKind::InvalidData => std::io::ErrorKind::InvalidData,
ErrorKind::InvalidInput => std::io::ErrorKind::InvalidInput,
ErrorKind::NotFound => std::io::ErrorKind::NotFound,
ErrorKind::Other => std::io::ErrorKind::Other,
ErrorKind::PermissionDenied => std::io::ErrorKind::PermissionDenied,
ErrorKind::UnexpectedEof => std::io::ErrorKind::UnexpectedEof,
ErrorKind::Unsupported => std::io::ErrorKind::Unsupported,
ErrorKind::WriteZero => std::io::ErrorKind::WriteZero,
};
match err.message {
Some(msg) => Self::new(kind, msg.into_string()),
None => Self::from(kind),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SeekFrom {
Start(u64),
End(i64),
Current(i64),
}
#[cfg(feature = "std")]
impl From<SeekFrom> for std::io::SeekFrom {
fn from(s: SeekFrom) -> Self {
match s {
SeekFrom::Start(n) => Self::Start(n),
SeekFrom::End(n) => Self::End(n),
SeekFrom::Current(n) => Self::Current(n),
}
}
}
#[cfg(feature = "std")]
impl From<std::io::SeekFrom> for SeekFrom {
fn from(s: std::io::SeekFrom) -> Self {
match s {
std::io::SeekFrom::Start(n) => Self::Start(n),
std::io::SeekFrom::End(n) => Self::End(n),
std::io::SeekFrom::Current(n) => Self::Current(n),
}
}
}
#[cfg(feature = "std")]
pub trait Read: std::io::Read {}
#[cfg(feature = "std")]
impl<R: std::io::Read + ?Sized> Read for R {}
#[cfg(feature = "std")]
pub trait Write: std::io::Write {}
#[cfg(feature = "std")]
impl<W: std::io::Write + ?Sized> Write for W {}
#[cfg(feature = "std")]
pub trait Seek: std::io::Seek {}
#[cfg(feature = "std")]
impl<S: std::io::Seek + ?Sized> Seek for S {}
#[cfg(feature = "std")]
pub trait BufRead: std::io::BufRead {}
#[cfg(feature = "std")]
impl<B: std::io::BufRead + ?Sized> BufRead for B {}
#[cfg(not(feature = "std"))]
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
while !buf.is_empty() {
match self.read(buf) {
Ok(0) => break,
Ok(n) => {
let (_, rest) = buf.split_at_mut(n);
buf = rest;
}
Err(e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if buf.is_empty() {
Ok(())
} else {
Err(Error::new(
ErrorKind::UnexpectedEof,
"failed to fill whole buffer",
))
}
}
fn take(self, limit: u64) -> Take<Self>
where
Self: Sized,
{
Take { inner: self, limit }
}
}
#[cfg(not(feature = "std"))]
pub struct Take<R> {
inner: R,
limit: u64,
}
#[cfg(not(feature = "std"))]
impl<R: Read> Read for Take<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
if self.limit == 0 {
return Ok(0);
}
let max = (buf.len() as u64).min(self.limit) as usize;
let (head, _) = buf.split_at_mut(max);
let n = self.inner.read(head)?;
self.limit -= n as u64;
Ok(n)
}
}
#[cfg(not(feature = "std"))]
pub trait BufRead: Read {
fn fill_buf(&mut self) -> Result<&[u8]>;
fn consume(&mut self, amt: usize);
}
#[cfg(not(feature = "std"))]
pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize>;
fn flush(&mut self) -> Result<()>;
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
while !buf.is_empty() {
match self.write(buf) {
Ok(0) => {
return Err(Error::new(
ErrorKind::WriteZero,
"failed to write whole buffer",
));
}
Ok(n) => {
let (_, rest) = buf.split_at(n);
buf = rest;
}
Err(e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}
#[cfg(not(feature = "std"))]
pub trait Seek {
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
fn stream_position(&mut self) -> Result<u64> {
self.seek(SeekFrom::Current(0))
}
fn seek_relative(&mut self, offset: i64) -> Result<()> {
self.seek(SeekFrom::Current(offset))?;
Ok(())
}
}
#[cfg(not(feature = "std"))]
impl<R: Read + ?Sized> Read for &mut R {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
(**self).read(buf)
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
(**self).read_exact(buf)
}
}
#[cfg(not(feature = "std"))]
impl<R: Read + ?Sized> Read for alloc::boxed::Box<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
(**self).read(buf)
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
(**self).read_exact(buf)
}
}
#[cfg(not(feature = "std"))]
impl<W: Write + ?Sized> Write for &mut W {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
(**self).write(buf)
}
fn flush(&mut self) -> Result<()> {
(**self).flush()
}
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
(**self).write_all(buf)
}
}
#[cfg(not(feature = "std"))]
impl<W: Write + ?Sized> Write for alloc::boxed::Box<W> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
(**self).write(buf)
}
fn flush(&mut self) -> Result<()> {
(**self).flush()
}
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
(**self).write_all(buf)
}
}
#[cfg(not(feature = "std"))]
impl<S: Seek + ?Sized> Seek for &mut S {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
(**self).seek(pos)
}
fn stream_position(&mut self) -> Result<u64> {
(**self).stream_position()
}
fn seek_relative(&mut self, offset: i64) -> Result<()> {
(**self).seek_relative(offset)
}
}
#[cfg(not(feature = "std"))]
impl<S: Seek + ?Sized> Seek for alloc::boxed::Box<S> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
(**self).seek(pos)
}
fn stream_position(&mut self) -> Result<u64> {
(**self).stream_position()
}
fn seek_relative(&mut self, offset: i64) -> Result<()> {
(**self).seek_relative(offset)
}
}
#[cfg(not(feature = "std"))]
impl<B: BufRead + ?Sized> BufRead for &mut B {
fn fill_buf(&mut self) -> Result<&[u8]> {
(**self).fill_buf()
}
fn consume(&mut self, amt: usize) {
(**self).consume(amt);
}
}
#[cfg(not(feature = "std"))]
impl<B: BufRead + ?Sized> BufRead for alloc::boxed::Box<B> {
fn fill_buf(&mut self) -> Result<&[u8]> {
(**self).fill_buf()
}
fn consume(&mut self, amt: usize) {
(**self).consume(amt);
}
}
#[cfg(not(feature = "std"))]
pub trait VarintWriter: Write {
fn write_u64_varint(&mut self, mut value: u64) -> Result<()> {
loop {
let mut byte = (value & 0x7f) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
self.write_all(&[byte])?;
if value == 0 {
return Ok(());
}
}
}
fn write_u32_varint(&mut self, value: u32) -> Result<()> {
self.write_u64_varint(u64::from(value))
}
fn write_u16_varint(&mut self, value: u16) -> Result<()> {
self.write_u64_varint(u64::from(value))
}
}
#[cfg(not(feature = "std"))]
impl<W: Write + ?Sized> VarintWriter for W {}
#[cfg(not(feature = "std"))]
pub trait VarintReader: Read {
fn read_u64_varint(&mut self) -> Result<u64> {
let mut result: u64 = 0;
let mut shift: u32 = 0;
loop {
let mut byte = [0u8; 1];
self.read_exact(&mut byte)?;
if shift >= 64 {
return Err(Error::new(ErrorKind::InvalidData, "varint overflows u64"));
}
if shift == 63 && byte[0] & 0xFE != 0 {
return Err(Error::new(
ErrorKind::InvalidData,
"non-canonical varint overflow",
));
}
result |= (u64::from(byte[0] & 0x7f)) << shift;
if byte[0] & 0x80 == 0 {
return Ok(result);
}
shift += 7;
}
}
fn read_u32_varint(&mut self) -> Result<u32> {
let v = self.read_u64_varint()?;
u32::try_from(v).map_err(|_| Error::new(ErrorKind::InvalidData, "varint exceeds u32"))
}
fn read_u16_varint(&mut self) -> Result<u16> {
let v = self.read_u64_varint()?;
u16::try_from(v).map_err(|_| Error::new(ErrorKind::InvalidData, "varint exceeds u16"))
}
}
#[cfg(not(feature = "std"))]
impl<R: Read + ?Sized> VarintReader for R {}
pub trait ByteOrder {
fn u16_from(b: [u8; 2]) -> u16;
fn u32_from(b: [u8; 4]) -> u32;
fn u64_from(b: [u8; 8]) -> u64;
fn u128_from(b: [u8; 16]) -> u128;
fn u16_to(n: u16) -> [u8; 2];
fn u32_to(n: u32) -> [u8; 4];
fn u64_to(n: u64) -> [u8; 8];
fn u128_to(n: u128) -> [u8; 16];
#[must_use]
fn read_u16(buf: &[u8]) -> u16 {
let (head, _) = buf.split_at(2);
let mut a = [0u8; 2];
a.copy_from_slice(head);
Self::u16_from(a)
}
#[must_use]
fn read_u32(buf: &[u8]) -> u32 {
let (head, _) = buf.split_at(4);
let mut a = [0u8; 4];
a.copy_from_slice(head);
Self::u32_from(a)
}
#[must_use]
fn read_u64(buf: &[u8]) -> u64 {
let (head, _) = buf.split_at(8);
let mut a = [0u8; 8];
a.copy_from_slice(head);
Self::u64_from(a)
}
fn write_u16(buf: &mut [u8], n: u16) {
let (head, _) = buf.split_at_mut(2);
head.copy_from_slice(&Self::u16_to(n));
}
fn write_u32(buf: &mut [u8], n: u32) {
let (head, _) = buf.split_at_mut(4);
head.copy_from_slice(&Self::u32_to(n));
}
fn write_u64(buf: &mut [u8], n: u64) {
let (head, _) = buf.split_at_mut(8);
head.copy_from_slice(&Self::u64_to(n));
}
}
#[derive(Clone, Copy, Debug)]
pub enum LittleEndian {}
#[derive(Clone, Copy, Debug)]
pub enum BigEndian {}
pub type LE = LittleEndian;
pub type BE = BigEndian;
impl ByteOrder for LittleEndian {
fn u16_from(b: [u8; 2]) -> u16 {
u16::from_le_bytes(b)
}
fn u32_from(b: [u8; 4]) -> u32 {
u32::from_le_bytes(b)
}
fn u64_from(b: [u8; 8]) -> u64 {
u64::from_le_bytes(b)
}
fn u128_from(b: [u8; 16]) -> u128 {
u128::from_le_bytes(b)
}
fn u16_to(n: u16) -> [u8; 2] {
n.to_le_bytes()
}
fn u32_to(n: u32) -> [u8; 4] {
n.to_le_bytes()
}
fn u64_to(n: u64) -> [u8; 8] {
n.to_le_bytes()
}
fn u128_to(n: u128) -> [u8; 16] {
n.to_le_bytes()
}
}
impl ByteOrder for BigEndian {
fn u16_from(b: [u8; 2]) -> u16 {
u16::from_be_bytes(b)
}
fn u32_from(b: [u8; 4]) -> u32 {
u32::from_be_bytes(b)
}
fn u64_from(b: [u8; 8]) -> u64 {
u64::from_be_bytes(b)
}
fn u128_from(b: [u8; 16]) -> u128 {
u128::from_be_bytes(b)
}
fn u16_to(n: u16) -> [u8; 2] {
n.to_be_bytes()
}
fn u32_to(n: u32) -> [u8; 4] {
n.to_be_bytes()
}
fn u64_to(n: u64) -> [u8; 8] {
n.to_be_bytes()
}
fn u128_to(n: u128) -> [u8; 16] {
n.to_be_bytes()
}
}
pub trait WriteBytesExt: Write {
fn write_u8(&mut self, n: u8) -> Result<()> {
self.write_all(&[n])?;
Ok(())
}
fn write_i8(&mut self, n: i8) -> Result<()> {
self.write_all(&n.to_le_bytes())?;
Ok(())
}
fn write_u16<T: ByteOrder>(&mut self, n: u16) -> Result<()> {
self.write_all(&T::u16_to(n))?;
Ok(())
}
fn write_u32<T: ByteOrder>(&mut self, n: u32) -> Result<()> {
self.write_all(&T::u32_to(n))?;
Ok(())
}
fn write_u64<T: ByteOrder>(&mut self, n: u64) -> Result<()> {
self.write_all(&T::u64_to(n))?;
Ok(())
}
fn write_u128<T: ByteOrder>(&mut self, n: u128) -> Result<()> {
self.write_all(&T::u128_to(n))?;
Ok(())
}
fn write_f32<T: ByteOrder>(&mut self, n: f32) -> Result<()> {
self.write_u32::<T>(n.to_bits())
}
fn write_f64<T: ByteOrder>(&mut self, n: f64) -> Result<()> {
self.write_u64::<T>(n.to_bits())
}
}
impl<W: Write + ?Sized> WriteBytesExt for W {}
pub trait ReadBytesExt: Read {
fn read_u8(&mut self) -> Result<u8> {
let mut b = [0u8; 1];
self.read_exact(&mut b)?;
Ok(u8::from_le_bytes(b))
}
fn read_i8(&mut self) -> Result<i8> {
let mut b = [0u8; 1];
self.read_exact(&mut b)?;
Ok(i8::from_le_bytes(b))
}
fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> {
let mut b = [0u8; 2];
self.read_exact(&mut b)?;
Ok(T::u16_from(b))
}
fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> {
let mut b = [0u8; 4];
self.read_exact(&mut b)?;
Ok(T::u32_from(b))
}
fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> {
let mut b = [0u8; 8];
self.read_exact(&mut b)?;
Ok(T::u64_from(b))
}
fn read_u128<T: ByteOrder>(&mut self) -> Result<u128> {
let mut b = [0u8; 16];
self.read_exact(&mut b)?;
Ok(T::u128_from(b))
}
fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> {
Ok(f32::from_bits(self.read_u32::<T>()?))
}
fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> {
Ok(f64::from_bits(self.read_u64::<T>()?))
}
}
impl<R: Read + ?Sized> ReadBytesExt for R {}
#[cfg(not(feature = "std"))]
impl Write for alloc::vec::Vec<u8> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> Result<()> {
Ok(())
}
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
self.extend_from_slice(buf);
Ok(())
}
}
#[cfg(not(feature = "std"))]
impl Read for &[u8] {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let n = buf.len().min(self.len());
let (head, rest) = self.split_at(n);
let (dst, _) = buf.split_at_mut(n);
dst.copy_from_slice(head);
*self = rest;
Ok(n)
}
}
#[cfg(feature = "std")]
pub use std::io::Cursor;
#[cfg(not(feature = "std"))]
pub struct Cursor<T> {
inner: T,
pos: u64,
}
#[cfg(not(feature = "std"))]
impl<T> Cursor<T> {
pub const fn new(inner: T) -> Self {
Self { inner, pos: 0 }
}
#[must_use]
pub const fn position(&self) -> u64 {
self.pos
}
pub const fn set_position(&mut self, pos: u64) {
self.pos = pos;
}
pub fn into_inner(self) -> T {
self.inner
}
pub const fn get_ref(&self) -> &T {
&self.inner
}
pub const fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
}
#[cfg(not(feature = "std"))]
impl<T: AsRef<[u8]>> Read for Cursor<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let inner = self.inner.as_ref();
let start = (self.pos as usize).min(inner.len());
let (_, remaining) = inner.split_at(start);
let n = buf.len().min(remaining.len());
let (src, _) = remaining.split_at(n);
let (dst, _) = buf.split_at_mut(n);
dst.copy_from_slice(src);
self.pos += n as u64;
Ok(n)
}
}
#[cfg(not(feature = "std"))]
impl<T: AsRef<[u8]>> Seek for Cursor<T> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
let len = self.inner.as_ref().len() as u64;
let new = match pos {
SeekFrom::Start(n) => n,
SeekFrom::End(off) => len.saturating_add_signed(off),
SeekFrom::Current(off) => self.pos.saturating_add_signed(off),
};
self.pos = new;
Ok(new)
}
}
#[cfg(not(feature = "std"))]
impl Write for Cursor<alloc::vec::Vec<u8>> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let pos = self.pos as usize;
if pos > self.inner.len() {
self.inner.resize(pos, 0);
}
let end = pos + buf.len();
if end > self.inner.len() {
self.inner.resize(end, 0);
}
let (_, tail) = self.inner.split_at_mut(pos);
let (dst, _) = tail.split_at_mut(buf.len());
dst.copy_from_slice(buf);
self.pos = end as u64;
Ok(buf.len())
}
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
#[cfg(feature = "std")]
pub use std::io::BufReader;
#[cfg(not(feature = "std"))]
pub struct BufReader<R: Read> {
inner: R,
buf: alloc::vec::Vec<u8>,
pos: usize,
cap: usize,
}
#[cfg(not(feature = "std"))]
impl<R: Read> BufReader<R> {
pub fn new(inner: R) -> Self {
Self::with_capacity(8 * 1024, inner)
}
pub fn with_capacity(capacity: usize, inner: R) -> Self {
Self {
inner,
buf: alloc::vec![0u8; capacity],
pos: 0,
cap: 0,
}
}
pub fn get_mut(&mut self) -> &mut R {
&mut self.inner
}
pub fn get_ref(&self) -> &R {
&self.inner
}
}
#[cfg(not(feature = "std"))]
impl<R: Read> Read for BufReader<R> {
fn read(&mut self, dest: &mut [u8]) -> Result<usize> {
if self.pos >= self.cap && dest.len() >= self.buf.len() {
return self.inner.read(dest);
}
let n = {
let available = self.fill_buf()?;
let n = available.len().min(dest.len());
let (src, _) = available.split_at(n);
let (dst, _) = dest.split_at_mut(n);
dst.copy_from_slice(src);
n
};
self.consume(n);
Ok(n)
}
}
#[cfg(not(feature = "std"))]
impl<R: Read> BufRead for BufReader<R> {
fn fill_buf(&mut self) -> Result<&[u8]> {
if self.pos >= self.cap {
self.cap = self.inner.read(&mut self.buf)?;
self.pos = 0;
}
let (_, rest) = self.buf.split_at(self.pos);
let (out, _) = rest.split_at(self.cap - self.pos);
Ok(out)
}
fn consume(&mut self, amt: usize) {
self.pos = (self.pos + amt).min(self.cap);
}
}
#[cfg(not(feature = "std"))]
impl<R: Read + Seek> Seek for BufReader<R> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
self.pos = 0;
self.cap = 0;
self.inner.seek(pos)
}
}
#[cfg(feature = "std")]
pub use std::io::BufWriter;
#[cfg(not(feature = "std"))]
pub struct BufWriter<W: Write> {
inner: W,
buf: alloc::vec::Vec<u8>,
}
#[cfg(not(feature = "std"))]
impl<W: Write> BufWriter<W> {
pub fn new(inner: W) -> Self {
Self::with_capacity(8 * 1024, inner)
}
pub fn with_capacity(capacity: usize, inner: W) -> Self {
Self {
inner,
buf: alloc::vec::Vec::with_capacity(capacity),
}
}
pub fn get_mut(&mut self) -> &mut W {
&mut self.inner
}
pub fn get_ref(&self) -> &W {
&self.inner
}
fn flush_buf(&mut self) -> Result<()> {
if !self.buf.is_empty() {
self.inner.write_all(&self.buf)?;
self.buf.clear();
}
Ok(())
}
}
#[cfg(not(feature = "std"))]
impl<W: Write> Write for BufWriter<W> {
fn write(&mut self, data: &[u8]) -> Result<usize> {
if self.buf.len() + data.len() > self.buf.capacity() {
self.flush_buf()?;
}
if data.len() >= self.buf.capacity() {
self.inner.write(data)
} else {
self.buf.extend_from_slice(data);
Ok(data.len())
}
}
fn flush(&mut self) -> Result<()> {
self.flush_buf()?;
self.inner.flush()
}
}
#[cfg(not(feature = "std"))]
impl<W: Write + Seek> Seek for BufWriter<W> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
self.flush_buf()?;
self.inner.seek(pos)
}
}
#[cfg(not(feature = "std"))]
impl<W: Write> Drop for BufWriter<W> {
fn drop(&mut self) {
let _ = self.flush_buf();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "std")]
fn assert_read_alias_bound<R: Read>(_: &R) {}
#[cfg(feature = "std")]
fn assert_write_alias_bound<W: Write>(_: &W) {}
#[test]
fn error_kind_strings_are_distinct() {
let all = [
ErrorKind::AlreadyExists,
ErrorKind::BrokenPipe,
ErrorKind::CrossesDevices,
ErrorKind::Interrupted,
ErrorKind::InvalidData,
ErrorKind::InvalidInput,
ErrorKind::NotFound,
ErrorKind::Other,
ErrorKind::PermissionDenied,
ErrorKind::UnexpectedEof,
ErrorKind::Unsupported,
ErrorKind::WriteZero,
];
for (i, a) in all.iter().enumerate() {
for b in all.iter().skip(i + 1) {
assert_ne!(
a.as_str(),
b.as_str(),
"duplicate description for {a:?} vs {b:?}",
);
}
}
}
#[test]
fn error_carries_kind_and_optional_message() {
let e = Error::from_kind(ErrorKind::NotFound);
assert_eq!(e.kind(), ErrorKind::NotFound);
assert_eq!(alloc::format!("{e}"), "entity not found");
let e = Error::new(ErrorKind::InvalidData, "bad magic");
assert_eq!(e.kind(), ErrorKind::InvalidData);
assert_eq!(alloc::format!("{e}"), "invalid data: bad magic");
}
#[test]
fn error_kind_from_kind_is_const_friendly() {
const _E: Error = Error::from_kind(ErrorKind::Interrupted);
}
#[cfg(feature = "std")]
#[test]
fn from_std_io_error_preserves_kind_and_message() {
let std_err = std::io::Error::new(std::io::ErrorKind::WriteZero, "ran out");
let crate_err: Error = std_err.into();
assert_eq!(crate_err.kind(), ErrorKind::WriteZero);
let rendered = alloc::format!("{crate_err}");
assert!(
rendered.contains("ran out"),
"expected std message to survive in {rendered:?}",
);
}
#[cfg(feature = "std")]
#[test]
fn from_std_io_error_maps_unknown_to_other() {
let std_err = std::io::Error::from(std::io::ErrorKind::OutOfMemory);
let crate_err: Error = std_err.into();
assert_eq!(crate_err.kind(), ErrorKind::Other);
}
#[cfg(feature = "std")]
#[test]
fn round_trip_through_std_io_error_preserves_writezero() {
let original = Error::new(ErrorKind::WriteZero, "short write");
let as_std: std::io::Error = original.into();
assert_eq!(as_std.kind(), std::io::ErrorKind::WriteZero);
let back: Error = as_std.into();
assert_eq!(back.kind(), ErrorKind::WriteZero);
}
#[cfg(feature = "std")]
#[test]
fn kind_only_other_std_error_skips_message_attachment() {
let std_err = std::io::Error::from(std::io::ErrorKind::Other);
let ours: Error = std_err.into();
assert_eq!(ours.kind(), ErrorKind::Other);
let rendered = alloc::format!("{ours}");
assert!(
!rendered.contains(':'),
"kind-only Other must not attach a message, got: {rendered:?}"
);
}
#[cfg(feature = "std")]
#[test]
fn seek_from_round_trips_through_std() {
for case in [SeekFrom::Start(42), SeekFrom::End(-7), SeekFrom::Current(0)] {
let std_form: std::io::SeekFrom = case.into();
let back: SeekFrom = std_form.into();
assert_eq!(case, back);
}
}
#[cfg(feature = "std")]
#[test]
fn read_exact_via_blanket_impl_on_slice() -> std::io::Result<()> {
let mut src: &[u8] = b"\x01\x02\x03\x04";
assert_read_alias_bound(&src);
let mut buf = [0u8; 4];
<&[u8] as std::io::Read>::read_exact(&mut src, &mut buf)?;
assert_eq!(buf, [1, 2, 3, 4]);
Ok(())
}
#[cfg(feature = "std")]
#[test]
fn write_all_via_blanket_impl_on_vec() -> std::io::Result<()> {
let mut sink: Vec<u8> = Vec::new();
assert_write_alias_bound(&sink);
<Vec<u8> as std::io::Write>::write_all(&mut sink, b"hello")?;
assert_eq!(sink, b"hello");
Ok(())
}
#[cfg(feature = "std")]
const ALL_KINDS: [ErrorKind; 12] = [
ErrorKind::AlreadyExists,
ErrorKind::BrokenPipe,
ErrorKind::CrossesDevices,
ErrorKind::Interrupted,
ErrorKind::InvalidData,
ErrorKind::InvalidInput,
ErrorKind::NotFound,
ErrorKind::Other,
ErrorKind::PermissionDenied,
ErrorKind::UnexpectedEof,
ErrorKind::Unsupported,
ErrorKind::WriteZero,
];
#[cfg(feature = "std")]
#[test]
fn every_kind_only_error_round_trips_through_std() {
for kind in ALL_KINDS {
let original = Error::from_kind(kind);
let as_std: std::io::Error = original.into();
let back: Error = as_std.into();
assert_eq!(back.kind(), kind, "kind {kind:?} did not round-trip");
}
}
#[cfg(feature = "std")]
#[test]
fn every_kind_only_std_error_maps_to_matching_kind() {
let mapped = [
(std::io::ErrorKind::AlreadyExists, ErrorKind::AlreadyExists),
(std::io::ErrorKind::BrokenPipe, ErrorKind::BrokenPipe),
(
std::io::ErrorKind::CrossesDevices,
ErrorKind::CrossesDevices,
),
(std::io::ErrorKind::Interrupted, ErrorKind::Interrupted),
(std::io::ErrorKind::InvalidData, ErrorKind::InvalidData),
(std::io::ErrorKind::InvalidInput, ErrorKind::InvalidInput),
(std::io::ErrorKind::NotFound, ErrorKind::NotFound),
(
std::io::ErrorKind::PermissionDenied,
ErrorKind::PermissionDenied,
),
(std::io::ErrorKind::UnexpectedEof, ErrorKind::UnexpectedEof),
(std::io::ErrorKind::Unsupported, ErrorKind::Unsupported),
(std::io::ErrorKind::WriteZero, ErrorKind::WriteZero),
];
for (std_kind, want) in mapped {
let ours: Error = std::io::Error::from(std_kind).into();
assert_eq!(ours.kind(), want, "std {std_kind:?} mis-mapped");
}
}
#[cfg(feature = "std")]
#[test]
fn from_raw_os_error_preserves_os_detail_as_message() {
let std_err = std::io::Error::from_raw_os_error(2); let ours: Error = std_err.into();
let rendered = alloc::format!("{ours}");
assert!(
rendered.contains(':'),
"os-detail error must attach a message, got: {rendered:?}"
);
}
#[test]
fn debug_renders_kind_always_and_message_when_present() {
let kind_only = Error::from_kind(ErrorKind::NotFound);
let dbg = alloc::format!("{kind_only:?}");
assert!(dbg.contains("NotFound"), "missing kind in {dbg:?}");
assert!(
!dbg.contains("message"),
"kind-only must omit message: {dbg:?}"
);
let with_msg = Error::new(ErrorKind::InvalidData, "bad magic");
let dbg = alloc::format!("{with_msg:?}");
assert!(dbg.contains("message"), "expected message field in {dbg:?}");
assert!(dbg.contains("bad magic"), "expected payload in {dbg:?}");
}
#[test]
fn other_constructor_and_kind_from_conversion() {
let e = Error::other("boom");
assert_eq!(e.kind(), ErrorKind::Other);
assert_eq!(alloc::format!("{e}"), "other error: boom");
let e: Error = ErrorKind::PermissionDenied.into();
assert_eq!(e.kind(), ErrorKind::PermissionDenied);
assert_eq!(alloc::format!("{e}"), "permission denied");
}
#[test]
fn error_kind_display_matches_as_str() {
let all = [
ErrorKind::AlreadyExists,
ErrorKind::BrokenPipe,
ErrorKind::CrossesDevices,
ErrorKind::Interrupted,
ErrorKind::InvalidData,
ErrorKind::InvalidInput,
ErrorKind::NotFound,
ErrorKind::Other,
ErrorKind::PermissionDenied,
ErrorKind::UnexpectedEof,
ErrorKind::Unsupported,
ErrorKind::WriteZero,
];
for kind in all {
assert_eq!(alloc::format!("{kind}"), kind.as_str());
}
}
#[test]
fn big_endian_byte_order_round_trips_all_widths() {
assert_eq!(BigEndian::u16_to(0x0102), [0x01, 0x02]);
assert_eq!(BigEndian::u16_from([0x01, 0x02]), 0x0102);
assert_eq!(BigEndian::u32_to(0x0102_0304), [0x01, 0x02, 0x03, 0x04]);
assert_eq!(BigEndian::u32_from([0x01, 0x02, 0x03, 0x04]), 0x0102_0304);
assert_eq!(
BigEndian::u64_to(0x0102_0304_0506_0708),
[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
);
assert_eq!(
BigEndian::u64_from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]),
0x0102_0304_0506_0708
);
let v = 0x0102_0304_0506_0708_090a_0b0c_0d0e_0f10u128;
assert_eq!(BigEndian::u128_from(BigEndian::u128_to(v)), v);
assert_eq!(BigEndian::u128_to(v)[0], 0x01, "MSB must land first");
}
#[test]
fn byte_order_buf_helpers_round_trip_u64() {
let mut buf = [0u8; 8];
LittleEndian::write_u64(&mut buf, 0xdead_beef_cafe_f00d);
assert_eq!(LittleEndian::read_u64(&buf), 0xdead_beef_cafe_f00d);
}
#[cfg(feature = "std")]
#[test]
fn read_bytes_ext_reads_floats_in_byte_order() -> crate::io::Result<()> {
let f32_bytes = 1.5f32.to_le_bytes();
let mut cur = Cursor::new(&f32_bytes[..]);
assert_eq!(cur.read_f32::<LittleEndian>()?.to_bits(), 1.5f32.to_bits());
let f64_bytes = (-2.25f64).to_le_bytes();
let mut cur = Cursor::new(&f64_bytes[..]);
assert_eq!(
cur.read_f64::<LittleEndian>()?.to_bits(),
(-2.25f64).to_bits()
);
Ok(())
}
}