use core::fmt::{self, Debug};
use core::mem::{ManuallyDrop, MaybeUninit};
use crate::array::ArrayConsumer;
#[repr(C)]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
pub struct ArrayBuilder<T, const N: usize> {
array: [MaybeUninit<T>; N],
inited: usize,
}
impl<T, const N: usize> ArrayBuilder<T, N> {
pub const fn new() -> Self {
ArrayBuilder {
array: crate::maybe_uninit::uninit_array(),
inited: 0,
}
}
pub const fn len(&self) -> usize {
self.inited
}
pub const fn is_full(&self) -> bool {
self.inited == N
}
pub const fn as_slice(&self) -> &[T] {
unsafe {
core::slice::from_raw_parts(self.array.as_ptr().cast::<T>(), self.inited)
}
}
pub const fn as_mut_slice(&mut self) -> &mut [T] {
unsafe {
core::slice::from_raw_parts_mut(self.array.as_mut_ptr().cast::<T>(), self.inited)
}
}
pub const fn push(&mut self, val: T) {
assert!(self.inited < N, "trying to add an element to full array");
self.array[self.inited] = MaybeUninit::new(val);
self.inited += 1;
}
pub const fn build(self) -> [T; N] {
assert!(self.is_full(), "trying to unwrap a non-fully-initialized array");
unsafe {
let mut this = ManuallyDrop::new(self);
(&raw mut this).cast::<[T; N]>().read()
}
}
pub const fn copy(&self) -> Self
where
T: Copy
{
Self {..*self}
}
pub const fn infer_length_from_consumer<U>(&self, _consumer: &ArrayConsumer<U, N>) {}
}
impl<T: Debug, const N: usize> Debug for ArrayBuilder<T, N> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("ArrayBuilder")
.field("array", &self.as_slice())
.field("uninit_len", &(N - self.inited))
.finish()
}
}
impl<T: Clone, const N: usize> Clone for ArrayBuilder<T, N> {
fn clone(&self) -> Self {
let mut this = Self::new();
for elem in self.as_slice() {
this.push(elem.clone());
}
this
}
}
impl<T, const N: usize> Drop for ArrayBuilder<T, N> {
fn drop(&mut self) {
unsafe {
let inited = self.inited;
let ptr = self.array.as_mut_ptr().cast::<T>();
core::ptr::slice_from_raw_parts_mut(ptr, inited).drop_in_place();
}
}
}