use alloc::vec::Vec;
use core::ops::{Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
const MAX_CAPACITY_WHEN_CLEARED: usize = 16384;
pub struct WriteBuf {
inner: Vec<u8>,
filled: usize,
}
impl WriteBuf {
#[inline]
pub const fn new() -> Self {
Self {
inner: Vec::new(),
filled: 0,
}
}
#[inline]
pub const fn from_vec(buffer: Vec<u8>) -> Self {
Self {
inner: buffer,
filled: 0,
}
}
#[inline]
pub fn into_inner(self) -> Vec<u8> {
self.inner
}
#[inline]
pub const fn filled_len(&self) -> usize {
self.filled
}
#[inline]
pub fn filled(&self) -> &[u8] {
&self.inner[..self.filled]
}
#[inline]
pub fn initialize(&mut self, additional: usize) {
if self.inner.len() < self.filled + additional {
self.inner.resize(self.filled + additional, 0);
}
}
#[inline]
pub fn unfilled_to(&mut self, n: usize) -> &mut [u8] {
self.initialize(n);
&mut self.inner[self.filled..self.filled + n]
}
#[inline]
pub fn unfilled_mut(&mut self) -> &mut [u8] {
&mut self.inner[self.filled..]
}
#[inline]
pub fn write_array<const N: usize>(&mut self, array: [u8; N]) {
self.initialize(N);
self.inner[self.filled..self.filled + N].copy_from_slice(&array);
self.filled += N;
}
#[inline]
pub fn write_slice(&mut self, slice: &[u8]) {
let n = slice.len();
self.initialize(n);
self.inner[self.filled..self.filled + n].copy_from_slice(slice);
self.filled += n;
}
#[inline]
pub fn write_u8(&mut self, value: u8) {
self.write_array(value.to_le_bytes())
}
#[inline]
pub fn write_u16(&mut self, value: u16) {
self.write_array(value.to_le_bytes())
}
#[inline]
pub fn write_u16_be(&mut self, value: u16) {
self.write_array(value.to_be_bytes())
}
#[inline]
pub fn write_u32(&mut self, value: u32) {
self.write_array(value.to_le_bytes())
}
#[inline]
pub fn write_u32_be(&mut self, value: u32) {
self.write_array(value.to_be_bytes())
}
#[inline]
pub fn write_u64(&mut self, value: u64) {
self.write_array(value.to_le_bytes())
}
#[inline]
pub fn write_u64_be(&mut self, value: u64) {
self.write_array(value.to_be_bytes())
}
#[inline]
pub fn clear(&mut self) {
self.filled = 0;
self.inner.shrink_to(MAX_CAPACITY_WHEN_CLEARED);
}
#[inline]
pub fn advance(&mut self, len: usize) {
self.filled += len;
debug_assert!(self.filled <= self.inner.len());
}
}
impl Default for WriteBuf {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "std")]
impl std::io::Write for WriteBuf {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.write_slice(buf);
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl Index<Range<usize>> for WriteBuf {
type Output = [u8];
#[inline]
fn index(&self, range: Range<usize>) -> &Self::Output {
&self.filled()[range]
}
}
impl Index<RangeFrom<usize>> for WriteBuf {
type Output = [u8];
#[inline]
fn index(&self, range: RangeFrom<usize>) -> &Self::Output {
&self.filled()[range]
}
}
impl Index<RangeFull> for WriteBuf {
type Output = [u8];
#[inline]
fn index(&self, _: RangeFull) -> &Self::Output {
self.filled()
}
}
impl Index<RangeInclusive<usize>> for WriteBuf {
type Output = [u8];
#[inline]
fn index(&self, range: RangeInclusive<usize>) -> &Self::Output {
&self.filled()[range]
}
}
impl Index<RangeTo<usize>> for WriteBuf {
type Output = [u8];
#[inline]
fn index(&self, range: RangeTo<usize>) -> &Self::Output {
&self.filled()[range]
}
}
impl Index<RangeToInclusive<usize>> for WriteBuf {
type Output = [u8];
#[inline]
fn index(&self, range: RangeToInclusive<usize>) -> &Self::Output {
&self.filled()[range]
}
}