mod cursor;
pub use cursor::*;
use crate::*;
#[derive(Debug)]
pub enum Error {
InvalidData,
IncorrectLength,
WriterOutOfSpace,
ReaderOutOfData,
#[cfg(feature = "std")]
StdIo(std::io::Error),
#[cfg(not(feature = "std"))]
StdIo(StdIoShim),
}
#[cfg(not(feature = "std"))]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum StdIoShim {}
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Error::InvalidData => write!(
f,
"Invalid data was encountered (corrupted or incorrect bits/bytes in data stream)"
),
Error::IncorrectLength => write!(f, "Incorrect length"),
Error::WriterOutOfSpace => write!(f, "Tried to write past the capacity of the writer"),
Error::ReaderOutOfData => write!(
f,
"Tried to read past the end of the reader's available data"
),
#[cfg(feature = "std")]
Error::StdIo(e) => write!(f, "IO error: {e}"),
#[cfg(not(feature = "std"))]
Error::StdIo(_) => write!(f, "IO error (shimmed)"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
#[inline(always)]
fn from(err: std::io::Error) -> Self {
Error::StdIo(err)
}
}
#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
fn from(err: Error) -> Self {
match err {
Error::WriterOutOfSpace => {
std::io::Error::new(std::io::ErrorKind::WriteZero, "Write short")
}
Error::InvalidData => {
std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid data")
}
Error::IncorrectLength => {
std::io::Error::new(std::io::ErrorKind::InvalidInput, "Incorrect length")
}
#[cfg(feature = "std")]
Error::StdIo(e) => e,
Error::ReaderOutOfData => {
std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "End of data")
}
}
}
}
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
#[inline(always)]
fn buf(&self) -> Option<&[u8]> {
None
}
#[inline(always)]
fn advance(&mut self, _n: usize) {}
}
pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize>;
fn flush(&mut self) -> Result<()>;
#[inline(always)]
fn buf_mut(&mut self) -> Option<&mut [u8]> {
None
}
#[inline(always)]
fn advance_mut(&mut self, _n: usize) {}
#[inline(always)]
fn reserve(&mut self, _additional: usize) {}
}
#[cfg(feature = "std")]
impl<R: std::io::Read> Read for R {
#[inline(always)]
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.read(buf).map_err(Error::from)
}
}
#[cfg(feature = "std")]
impl<W: std::io::Write> Write for W {
#[inline(always)]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.write(buf).map_err(Error::from)
}
#[inline(always)]
fn flush(&mut self) -> Result<()> {
self.flush().map_err(Error::from)
}
}
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(feature = "std")]
extern crate alloc;
pub struct VecWriter(pub alloc::vec::Vec<u8>);
impl Default for VecWriter {
fn default() -> Self {
Self::new()
}
}
impl VecWriter {
#[inline(always)]
pub const fn new() -> Self {
Self(alloc::vec::Vec::new())
}
#[inline(always)]
pub fn with_capacity(cap: usize) -> Self {
Self(alloc::vec::Vec::with_capacity(cap))
}
#[inline(always)]
pub fn into_inner(self) -> alloc::vec::Vec<u8> {
self.0
}
#[inline(always)]
pub fn as_slice(&self) -> &[u8] {
&self.0
}
}
impl Write for VecWriter {
#[inline(always)]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let len = self.0.len();
let cap = self.0.capacity();
let add = buf.len();
if cap - len < add {
self.0.reserve(cap.max(256).max(add));
}
unsafe {
let dst = self.0.as_mut_ptr().add(len);
core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, add);
self.0.set_len(len + add);
}
Ok(add)
}
#[inline(always)]
fn flush(&mut self) -> Result<()> {
Ok(())
}
#[inline(always)]
fn buf_mut(&mut self) -> Option<&mut [u8]> {
let len = self.0.len();
let mut cap = self.0.capacity();
if cap - len < 17 {
self.0.reserve(cap.max(256));
cap = self.0.capacity();
}
unsafe {
Some(core::slice::from_raw_parts_mut(
self.0.as_mut_ptr().add(len),
cap - len,
))
}
}
#[inline(always)]
fn advance_mut(&mut self, n: usize) {
let new_len = self.0.len() + n;
unsafe { self.0.set_len(new_len) };
}
#[inline(always)]
fn reserve(&mut self, additional: usize) {
self.0.reserve(additional);
}
}
#[cfg(not(feature = "std"))]
impl Write for alloc::vec::Vec<u8> {
#[inline(always)]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let len = self.len();
let cap = self.capacity();
let add = buf.len();
if cap - len < add {
self.reserve(cap.max(256).max(add));
}
unsafe {
let dst = self.as_mut_ptr().add(len);
core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, add);
self.set_len(len + add);
}
Ok(add)
}
#[inline(always)]
fn flush(&mut self) -> Result<()> {
Ok(())
}
#[inline(always)]
fn buf_mut(&mut self) -> Option<&mut [u8]> {
let len = self.len();
let mut cap = self.capacity();
if cap - len < 17 {
self.reserve(cap.max(256));
cap = self.capacity();
}
unsafe {
Some(core::slice::from_raw_parts_mut(
self.as_mut_ptr().add(len),
cap - len,
))
}
}
#[inline(always)]
fn advance_mut(&mut self, n: usize) {
let new_len = self.len() + n;
unsafe { self.set_len(new_len) };
}
#[inline(always)]
fn reserve(&mut self, additional: usize) {
alloc::vec::Vec::reserve(self, additional);
}
}
#[test]
fn test_write_vec() {
let mut my_vec = alloc::vec::Vec::new();
let data = b"Hello, world!";
assert_eq!(my_vec.write(data).unwrap(), data.len());
assert_eq!(my_vec, data);
assert_eq!(my_vec, b"Hello, world!".to_vec());
}