#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(feature = "std")]
extern crate std;
#[cfg(all(feature = "alloc",not(feature = "std")))]
extern crate alloc;
use core::fmt;
mod foreign;
pub type SerResult<T> = Result<T, SerError>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SerError {
BufferFull,
}
impl fmt::Display for SerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SerError::BufferFull => f.write_str("buffer is full"),
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for SerError {}
pub trait SerWrite {
type Error;
fn write(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
#[inline]
fn write_byte(&mut self, byte: u8) -> Result<(), Self::Error> {
self.write(core::slice::from_ref(&byte))
}
#[inline]
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.write(s.as_bytes())
}
}
impl<T: SerWrite> SerWrite for &'_ mut T {
type Error = T::Error;
#[inline(always)]
fn write(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
(*self).write(buf)
}
#[inline(always)]
fn write_byte(&mut self, byte: u8) -> Result<(), Self::Error> {
(*self).write_byte(byte)
}
#[inline(always)]
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
(*self).write_str(s)
}
}
#[derive(Debug, PartialEq)]
pub struct SliceWriter<'a> {
pub buf: &'a mut [u8],
pub len: usize
}
impl<'a> AsRef<[u8]> for SliceWriter<'a> {
fn as_ref(&self) -> &[u8] {
&self.buf[..self.len]
}
}
impl<'a> AsMut<[u8]> for SliceWriter<'a> {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.buf[..self.len]
}
}
impl<'a> SliceWriter<'a> {
pub fn new(buf: &'a mut [u8]) -> Self {
SliceWriter { buf, len: 0 }
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn capacity(&self) -> usize {
self.buf.len()
}
pub fn rem_capacity(&self) -> usize {
self.buf.len() - self.len
}
pub fn clear(&mut self) {
self.len = 0;
}
pub fn split(self) -> (&'a mut[u8], Self) {
let (res, buf) = self.buf.split_at_mut(self.len);
(res, Self { buf, len: 0 })
}
}
impl SerWrite for SliceWriter<'_> {
type Error = SerError;
fn write(&mut self, buf: &[u8]) -> SerResult<()> {
let end = self.len + buf.len();
match self.buf.get_mut(self.len..end) {
Some(chunk) => {
chunk.copy_from_slice(buf);
self.len = end;
Ok(())
}
None => Err(SerError::BufferFull)
}
}
}
impl<'a> fmt::Write for SliceWriter<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
SerWrite::write_str(self, s).map_err(|_| fmt::Error)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_slice_writer() {
let mut buf = [0u8;22];
let mut writer = SliceWriter::new(&mut buf);
writer.write(b"Hello World!").unwrap();
writer.write_byte(b' ').unwrap();
writer.write_str("Good Bye!").unwrap();
let expected = b"Hello World! Good Bye!";
assert_eq!(writer.as_ref(), expected);
let (head, mut writer) = writer.split();
assert_eq!(head, expected);
assert_eq!(writer.write_byte(b' ').unwrap_err(), SerError::BufferFull);
}
}