use core::fmt;
pub trait BvllSink {
fn remaining_capacity(&self) -> Option<usize>;
fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SinkFull {
pub needed: usize,
pub available: usize,
}
impl fmt::Display for SinkFull {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"sink full: need {}, have {}",
self.needed, self.available
)
}
}
impl core::error::Error for SinkFull {}
impl BvllSink for &mut [u8] {
fn remaining_capacity(&self) -> Option<usize> {
Some(self.len())
}
fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull> {
if self.len() < bytes.len() {
return Err(SinkFull {
needed: bytes.len(),
available: self.len(),
});
}
let (head, tail) = core::mem::take(self).split_at_mut(bytes.len());
head.copy_from_slice(bytes);
*self = tail;
Ok(())
}
}
#[cfg(feature = "heapless")]
impl<const N: usize> BvllSink for heapless::Vec<u8, N> {
fn remaining_capacity(&self) -> Option<usize> {
Some(N - self.len())
}
fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull> {
let available = N - self.len();
self.extend_from_slice(bytes).map_err(|_| SinkFull {
needed: bytes.len(),
available,
})
}
}
#[cfg(feature = "alloc")]
impl BvllSink for alloc::vec::Vec<u8> {
fn remaining_capacity(&self) -> Option<usize> {
None
}
fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull> {
self.extend_from_slice(bytes);
Ok(())
}
}
#[cfg(feature = "bytes")]
impl BvllSink for bytes::BytesMut {
fn remaining_capacity(&self) -> Option<usize> {
None
}
fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull> {
self.extend_from_slice(bytes);
Ok(())
}
}