#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BufError {
OutOfBounds,
UnexpectedEof,
UnexpectedValue,
BufferTooSmall,
InvalidLength,
ProtocolError(&'static str),
}
impl core::error::Error for BufError {}
impl core::fmt::Display for BufError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
BufError::OutOfBounds => write!(f, "Buffer offset out of bounds"),
BufError::UnexpectedEof => write!(f, "Unexpected end of buffer"),
BufError::UnexpectedValue => write!(f, "Unexpected value in buffer"),
BufError::BufferTooSmall => write!(f, "Buffer is too small"),
BufError::InvalidLength => write!(f, "Invalid length"),
BufError::ProtocolError(msg) => write!(f, "Protocol error: {msg}"),
}
}
}
pub type BufResult<T> = core::result::Result<T, BufError>;
pub trait Buf {
fn length(&self) -> usize;
fn is_empty(&self) -> bool {
self.length() == 0
}
fn get_u8(&self, offset: usize) -> BufResult<u8>;
fn get_u16_be(&self, offset: usize) -> BufResult<u16> {
Ok(u16::from_be_bytes(self.get_array(offset)?))
}
fn get_u16_le(&self, offset: usize) -> BufResult<u16> {
Ok(u16::from_le_bytes(self.get_array(offset)?))
}
fn get_u32_be(&self, offset: usize) -> BufResult<u32> {
Ok(u32::from_be_bytes(self.get_array(offset)?))
}
fn get_u32_le(&self, offset: usize) -> BufResult<u32> {
Ok(u32::from_le_bytes(self.get_array(offset)?))
}
fn get_u64_be(&self, offset: usize) -> BufResult<u64> {
Ok(u64::from_be_bytes(self.get_array(offset)?))
}
fn get_u64_le(&self, offset: usize) -> BufResult<u64> {
Ok(u64::from_le_bytes(self.get_array(offset)?))
}
fn get_u128_be(&self, offset: usize) -> BufResult<u128> {
Ok(u128::from_be_bytes(self.get_array(offset)?))
}
fn get_u128_le(&self, offset: usize) -> BufResult<u128> {
Ok(u128::from_le_bytes(self.get_array(offset)?))
}
fn get_usize_be(&self, offset: usize) -> BufResult<usize> {
let bytes: [u8; core::mem::size_of::<usize>()] = self.get_array(offset)?;
Ok(usize::from_be_bytes(bytes))
}
fn get_usize_le(&self, offset: usize) -> BufResult<usize> {
let bytes: [u8; core::mem::size_of::<usize>()] = self.get_array(offset)?;
Ok(usize::from_le_bytes(bytes))
}
fn get_array<const N: usize>(&self, offset: usize) -> BufResult<[u8; N]> {
let mut arr = [0u8; N];
self.read_into(offset, &mut arr)?;
Ok(arr)
}
fn read_into(&self, offset: usize, dest: &mut [u8]) -> BufResult<()> {
for (i, byte) in dest.iter_mut().enumerate() {
*byte = self.get_u8(offset + i)?;
}
Ok(())
}
}
pub trait BufMut: Buf {
fn set_u8(&mut self, offset: usize, val: u8) -> BufResult<()>;
fn set_u16_be(&mut self, offset: usize, val: u16) -> BufResult<()> {
self.set_array(offset, &val.to_be_bytes())
}
fn set_u16_le(&mut self, offset: usize, val: u16) -> BufResult<()> {
self.set_array(offset, &val.to_le_bytes())
}
fn set_u32_be(&mut self, offset: usize, val: u32) -> BufResult<()> {
self.set_array(offset, &val.to_be_bytes())
}
fn set_u32_le(&mut self, offset: usize, val: u32) -> BufResult<()> {
self.set_array(offset, &val.to_le_bytes())
}
fn set_u64_be(&mut self, offset: usize, val: u64) -> BufResult<()> {
self.set_array(offset, &val.to_be_bytes())
}
fn set_u64_le(&mut self, offset: usize, val: u64) -> BufResult<()> {
self.set_array(offset, &val.to_le_bytes())
}
fn set_u128_be(&mut self, offset: usize, val: u128) -> BufResult<()> {
self.set_array(offset, &val.to_be_bytes())
}
fn set_u128_le(&mut self, offset: usize, val: u128) -> BufResult<()> {
self.set_array(offset, &val.to_le_bytes())
}
fn set_usize_be(&mut self, offset: usize, val: usize) -> BufResult<()> {
self.set_array(offset, &val.to_be_bytes())
}
fn set_usize_le(&mut self, offset: usize, val: usize) -> BufResult<()> {
self.set_array(offset, &val.to_le_bytes())
}
fn set_array<const N: usize>(&mut self, offset: usize, val: &[u8; N]) -> BufResult<()> {
self.set_slice(offset, val)
}
fn set_slice(&mut self, offset: usize, src: &[u8]) -> BufResult<()> {
for (i, &byte) in src.iter().enumerate() {
self.set_u8(offset + i, byte)?;
}
Ok(())
}
}
impl Buf for [u8] {
#[inline]
fn length(&self) -> usize {
self.len()
}
#[inline]
fn get_u8(&self, offset: usize) -> BufResult<u8> {
self.get(offset).copied().ok_or(BufError::OutOfBounds)
}
#[inline]
fn get_array<const N: usize>(&self, offset: usize) -> BufResult<[u8; N]> {
let end = offset.checked_add(N).ok_or(BufError::OutOfBounds)?;
let slice = self.get(offset..end).ok_or(BufError::OutOfBounds)?;
let mut arr = [0u8; N];
arr.copy_from_slice(slice);
Ok(arr)
}
#[inline]
fn read_into(&self, offset: usize, dest: &mut [u8]) -> BufResult<()> {
let end = offset
.checked_add(dest.len())
.ok_or(BufError::OutOfBounds)?;
let slice = self.get(offset..end).ok_or(BufError::OutOfBounds)?;
dest.copy_from_slice(slice);
Ok(())
}
}
impl BufMut for [u8] {
#[inline]
fn set_u8(&mut self, offset: usize, val: u8) -> BufResult<()> {
let byte = self.get_mut(offset).ok_or(BufError::OutOfBounds)?;
*byte = val;
Ok(())
}
#[inline]
fn set_array<const N: usize>(&mut self, offset: usize, val: &[u8; N]) -> BufResult<()> {
self.set_slice(offset, val)
}
#[inline]
fn set_slice(&mut self, offset: usize, src: &[u8]) -> BufResult<()> {
let end = offset.checked_add(src.len()).ok_or(BufError::OutOfBounds)?;
let slice = self.get_mut(offset..end).ok_or(BufError::OutOfBounds)?;
slice.copy_from_slice(src);
Ok(())
}
}
impl<const N: usize> Buf for [u8; N] {
#[inline]
fn length(&self) -> usize {
self.as_slice().length()
}
#[inline]
fn get_u8(&self, offset: usize) -> BufResult<u8> {
self.as_slice().get_u8(offset)
}
#[inline]
fn get_array<const M: usize>(&self, offset: usize) -> BufResult<[u8; M]> {
self.as_slice().get_array(offset)
}
#[inline]
fn read_into(&self, offset: usize, dest: &mut [u8]) -> BufResult<()> {
self.as_slice().read_into(offset, dest)
}
}
impl<const N: usize> BufMut for [u8; N] {
#[inline]
fn set_u8(&mut self, offset: usize, val: u8) -> BufResult<()> {
self.as_mut_slice().set_u8(offset, val)
}
#[inline]
fn set_array<const M: usize>(&mut self, offset: usize, val: &[u8; M]) -> BufResult<()> {
self.as_mut_slice().set_array(offset, val)
}
#[inline]
fn set_slice(&mut self, offset: usize, src: &[u8]) -> BufResult<()> {
self.as_mut_slice().set_slice(offset, src)
}
}
impl<T: Buf + ?Sized> Buf for &T {
#[inline]
fn length(&self) -> usize {
(**self).length()
}
#[inline]
fn is_empty(&self) -> bool {
(**self).is_empty()
}
#[inline]
fn get_u8(&self, offset: usize) -> BufResult<u8> {
(**self).get_u8(offset)
}
#[inline]
fn get_array<const N: usize>(&self, offset: usize) -> BufResult<[u8; N]> {
(**self).get_array(offset)
}
#[inline]
fn read_into(&self, offset: usize, dest: &mut [u8]) -> BufResult<()> {
(**self).read_into(offset, dest)
}
}
impl<T: Buf + ?Sized> Buf for &mut T {
#[inline]
fn length(&self) -> usize {
(**self).length()
}
#[inline]
fn is_empty(&self) -> bool {
(**self).is_empty()
}
#[inline]
fn get_u8(&self, offset: usize) -> BufResult<u8> {
(**self).get_u8(offset)
}
#[inline]
fn get_array<const N: usize>(&self, offset: usize) -> BufResult<[u8; N]> {
(**self).get_array(offset)
}
#[inline]
fn read_into(&self, offset: usize, dest: &mut [u8]) -> BufResult<()> {
(**self).read_into(offset, dest)
}
}
impl<T: BufMut + ?Sized> BufMut for &mut T {
#[inline]
fn set_u8(&mut self, offset: usize, val: u8) -> BufResult<()> {
(**self).set_u8(offset, val)
}
#[inline]
fn set_array<const N: usize>(&mut self, offset: usize, val: &[u8; N]) -> BufResult<()> {
(**self).set_array(offset, val)
}
#[inline]
fn set_slice(&mut self, offset: usize, src: &[u8]) -> BufResult<()> {
(**self).set_slice(offset, src)
}
}
#[cfg(feature = "alloc")]
impl Buf for Vec<u8> {
#[inline(always)]
fn length(&self) -> usize {
self.as_slice().len()
}
fn get_u8(&self, offset: usize) -> BufResult<u8> {
self.as_slice().get_u8(offset)
}
fn get_array<const N: usize>(&self, offset: usize) -> BufResult<[u8; N]> {
self.as_slice().get_array::<N>(offset)
}
fn read_into(&self, offset: usize, dest: &mut [u8]) -> BufResult<()> {
self.as_slice().read_into(offset, dest)
}
}
#[cfg(feature = "alloc")]
impl BufMut for Vec<u8> {
fn set_u8(&mut self, offset: usize, val: u8) -> BufResult<()> {
if offset >= self.len() {
self.resize(offset + 1, 0);
}
self.as_mut_slice()[offset] = val;
Ok(())
}
fn set_slice(&mut self, offset: usize, src: &[u8]) -> BufResult<()> {
let end = offset + src.len();
if end > self.len() {
self.resize(end, 0);
}
self.as_mut_slice()[offset..end].copy_from_slice(src);
Ok(())
}
}