use super::{RcBox, RcMeta};
use core::mem::{forget, MaybeUninit};
use core::ptr::drop_in_place;
#[must_use]
pub(crate) struct SliceBuilder<'a, T> {
rcbox: &'a mut RcBox<[MaybeUninit<T>]>,
n_elems: usize,
}
impl<'a, T> SliceBuilder<'a, T> {
#[inline]
pub fn new(meta: RcMeta, length: usize) -> Self {
let rcbox = RcBox::<T>::allocate_slice(meta, length, false);
Self { rcbox, n_elems: 0 }
}
#[inline]
pub fn append(&mut self, item: T) {
self.rcbox.data[self.n_elems].write(item);
self.n_elems += 1;
}
#[inline]
pub fn finish(self) -> &'a mut RcBox<[T]> {
assert_eq!(self.n_elems, self.rcbox.data.len());
let rcbox: *mut _ = self.rcbox;
forget(self);
unsafe { (*rcbox).assume_init() }
}
}
impl<T> Drop for SliceBuilder<'_, T> {
#[cold]
fn drop(&'_ mut self) {
let slice = &mut self.rcbox.data[..self.n_elems];
unsafe {
let slice: &mut [T] = &mut *(slice as *mut [MaybeUninit<T>] as *mut [T]);
drop_in_place(slice);
}
unsafe {
RcBox::dealloc(self.rcbox.into());
}
}
}