use core::cmp;
use core::mem::MaybeUninit;
pub(crate) struct ReadBuf<'a> {
buf: &'a mut [MaybeUninit<u8>],
filled: usize,
initialized: usize,
}
impl<'a> ReadBuf<'a> {
#[inline]
pub(crate) fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a> {
ReadBuf {
buf,
filled: 0,
initialized: 0,
}
}
#[inline]
#[must_use]
pub(crate) fn capacity(&self) -> usize {
self.buf.len()
}
#[inline]
pub(crate) fn initialized_mut(&mut self) -> &mut [u8] {
unsafe { slice_assume_init_mut(&mut self.buf[0..self.initialized]) }
}
#[inline]
pub(crate) fn uninitialized_mut(&mut self) -> &mut [MaybeUninit<u8>] {
&mut self.buf[self.initialized..]
}
#[inline]
pub(crate) fn initialize_unfilled(&mut self) -> &mut [u8] {
self.initialize_unfilled_to(self.remaining())
}
#[inline]
pub(crate) fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] {
assert!(self.remaining() >= n);
let extra_init = self.initialized - self.filled;
if n > extra_init {
let uninit = n - extra_init;
let unfilled = &mut self.uninitialized_mut()[0..uninit];
for byte in &mut *unfilled {
byte.write(0);
}
unsafe {
self.assume_init(n);
}
}
let filled = self.filled;
&mut self.initialized_mut()[filled..filled + n]
}
#[inline]
#[must_use]
pub(crate) fn remaining(&self) -> usize {
self.capacity() - self.filled
}
#[inline]
pub(crate) fn add_filled(&mut self, n: usize) {
self.set_filled(self.filled + n);
}
#[inline]
pub(crate) fn set_filled(&mut self, n: usize) {
assert!(n <= self.initialized);
self.filled = n;
}
#[inline]
pub(crate) unsafe fn assume_init(&mut self, n: usize) {
self.initialized = cmp::max(self.initialized, self.filled + n);
}
#[inline]
#[must_use]
pub(crate) fn filled_len(&self) -> usize {
self.filled
}
#[inline]
#[must_use]
pub(crate) fn initialized_len(&self) -> usize {
self.initialized
}
}
#[inline]
pub(crate) unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {
&mut *(core::ptr::from_mut::<[MaybeUninit<T>]>(slice) as *mut [T])
}