use std::mem::MaybeUninit;
pub(crate) struct VecWriter<'a, T> {
vec: &'a mut Vec<T>,
len: usize,
}
impl<'a, T> VecWriter<'a, T> {
#[inline(always)]
pub(crate) fn new(vec: &'a mut Vec<T>) -> Self {
let len = vec.len();
Self { vec, len }
}
#[inline(always)]
pub(crate) fn ensure_capacity(&mut self, additional: usize) {
let required = self.len + additional;
if required > self.vec.capacity() {
self.vec.reserve(required - self.vec.len());
}
}
#[inline(always)]
pub(crate) unsafe fn next_chunk_unchecked<const W: usize>(&mut self) -> &mut [MaybeUninit<T>; W] {
debug_assert!(
self.len + W <= self.vec.capacity(),
"VecWriter: cursor {} + chunk {} exceeds capacity {}",
self.len,
W,
self.vec.capacity(),
);
let ptr = self.vec.as_mut_ptr().wrapping_add(self.len) as *mut MaybeUninit<T>;
unsafe { &mut *(ptr as *mut [MaybeUninit<T>; W]) }
}
#[inline(always)]
pub(crate) unsafe fn advance(&mut self, n: usize) {
debug_assert!(
self.len + n <= self.vec.capacity(),
"VecWriter: advance would exceed capacity"
);
self.len += n;
}
#[inline(always)]
pub(crate) fn finish(self) -> usize {
let written = self.len;
unsafe { self.vec.set_len(written) };
std::mem::forget(self);
written
}
}
impl<T> Drop for VecWriter<'_, T> {
fn drop(&mut self) {
unsafe { self.vec.set_len(self.len) };
}
}