#![allow(unsafe_code)]
use std::mem::MaybeUninit;
pub trait Buffer: sealed::Sealed {}
impl Buffer for Vec<u8> {}
impl Buffer for String {}
pub(crate) mod sealed {
use super::SpareCapacity;
use std::mem::MaybeUninit;
pub trait Sealed {
unsafe fn ascii_vec(&mut self) -> &mut Vec<u8>;
#[inline(always)]
unsafe fn append_ascii(
&mut self,
max_len: usize,
fill: impl FnOnce(&mut [MaybeUninit<u8>]) -> usize,
) -> usize {
let vec = unsafe { self.ascii_vec() };
let start = vec.len();
let written = unsafe { vec.append_with(max_len, fill) };
debug_assert!(vec.get(start..).is_some_and(<[u8]>::is_ascii));
written
}
#[inline]
fn push_ascii(&mut self, bytes: &[u8]) -> usize {
self.push_ascii_where(bytes, |_| true)
}
#[inline]
fn push_ascii_where(&mut self, bytes: &[u8], keep: impl Fn(u8) -> bool) -> usize {
unsafe {
self.append_ascii(bytes.len(), |dst| {
for (slot, &byte) in dst.iter_mut().zip(bytes) {
slot.write(if byte.is_ascii() && keep(byte) {
byte
} else {
b'?'
});
}
bytes.len()
})
}
}
#[inline]
fn reserve_ascii(&mut self, additional: usize) {
unsafe { self.ascii_vec() }.reserve(additional);
}
}
impl Sealed for Vec<u8> {
#[inline(always)]
unsafe fn ascii_vec(&mut self) -> &mut Vec<u8> {
self
}
}
impl Sealed for String {
#[inline(always)]
unsafe fn ascii_vec(&mut self) -> &mut Vec<u8> {
unsafe { self.as_mut_vec() }
}
}
}
pub(crate) trait SpareCapacity {
unsafe fn append_with(
&mut self,
max_len: usize,
fill: impl FnOnce(&mut [MaybeUninit<u8>]) -> usize,
) -> usize;
}
impl SpareCapacity for Vec<u8> {
#[inline(always)]
unsafe fn append_with(
&mut self,
max_len: usize,
fill: impl FnOnce(&mut [MaybeUninit<u8>]) -> usize,
) -> usize {
self.reserve(max_len);
let start = self.len();
let spare = self.spare_capacity_mut();
let region = match spare.get_mut(..max_len) {
Some(region) => region,
None => spare,
};
let filled = fill(region);
debug_assert!(filled <= max_len);
let written = filled.min(max_len);
unsafe { self.set_len(start + written) };
written
}
}
pub(crate) trait Uninit {
unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>];
}
impl Uninit for [u8] {
#[inline(always)]
unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
unsafe { &mut *(std::ptr::from_mut(self) as *mut [MaybeUninit<u8>]) }
}
}
pub(crate) trait Initialized {
unsafe fn initialized(&self, len: usize) -> &[u8];
}
impl Initialized for [MaybeUninit<u8>] {
#[inline(always)]
unsafe fn initialized(&self, len: usize) -> &[u8] {
debug_assert!(len <= self.len());
let len = len.min(self.len());
unsafe { std::slice::from_raw_parts(self.as_ptr().cast(), len) }
}
}