use std::{
mem,
mem::MaybeUninit,
ops::{Deref, DerefMut},
slice,
};
pub(crate) fn init_array<T, const N: usize>(default: impl Fn() -> T) -> [T; N] {
let mut array: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
for elem in &mut array {
elem.write(default());
}
unsafe { mem::transmute_copy(&array) }
}
#[repr(C)]
pub(crate) struct ArrayWithHeaderAndTrailer<
T,
const HEADER_SIZE: usize,
const N: usize,
const TRAILER_SIZE: usize,
> {
header: [T; HEADER_SIZE],
array: [T; N],
trailer: [T; TRAILER_SIZE],
}
impl<T, const HEADER_SIZE: usize, const N: usize, const TRAILER_SIZE: usize> Deref
for ArrayWithHeaderAndTrailer<T, HEADER_SIZE, N, TRAILER_SIZE>
{
type Target = [T];
fn deref(&self) -> &Self::Target {
unsafe {
slice::from_raw_parts(self as *const _ as *const T, HEADER_SIZE + N + TRAILER_SIZE)
}
}
}
impl<T, const HEADER_SIZE: usize, const N: usize, const TRAILER_SIZE: usize> DerefMut
for ArrayWithHeaderAndTrailer<T, HEADER_SIZE, N, TRAILER_SIZE>
{
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe {
slice::from_raw_parts_mut(self as *mut _ as *mut T, HEADER_SIZE + N + TRAILER_SIZE)
}
}
}
impl<T, const HEADER_SIZE: usize, const N: usize, const TRAILER_SIZE: usize>
ArrayWithHeaderAndTrailer<T, HEADER_SIZE, N, TRAILER_SIZE>
{
pub(crate) fn new(default: impl Fn() -> T) -> Self {
Self {
header: init_array(&default),
array: init_array(&default),
trailer: init_array(&default),
}
}
}
impl<T, const HEADER_SIZE: usize, const N: usize, const TRAILER_SIZE: usize> Default
for ArrayWithHeaderAndTrailer<T, HEADER_SIZE, N, TRAILER_SIZE>
where
T: Default + Clone,
{
fn default() -> Self {
Self::new(T::default)
}
}