use core::marker::Copy;
use core::mem::MaybeUninit;
use core::ops::{Index, IndexMut};
use core::slice::SliceIndex;
mod sealed {
pub trait Sealed {}
impl Sealed for i8 {}
impl Sealed for u8 {}
}
pub trait ValueType: sealed::Sealed + Copy {}
impl ValueType for i8 {}
impl ValueType for u8 {}
#[derive(Debug)]
#[repr(C, align(8))] pub struct AlignedBuffer<T, const SIZE: usize>
where
T: ValueType, {
pub(crate) data: MaybeUninit<[T; SIZE]>,
}
impl<T, const SIZE: usize, Idx> Index<Idx> for AlignedBuffer<T, SIZE>
where
T: ValueType,
Idx: SliceIndex<[T]>,
{
type Output = Idx::Output;
#[inline]
fn index(&self, index: Idx) -> &Self::Output {
unsafe { self.assume_init().get_unchecked(index) }
}
}
impl<T, const SIZE: usize, Idx> IndexMut<Idx> for AlignedBuffer<T, SIZE>
where
T: ValueType,
Idx: SliceIndex<[T]>,
{
#[inline]
fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
unsafe { self.assume_init_mut().get_unchecked_mut(index) }
}
}
#[allow(clippy::new_without_default)]
impl<T, const SIZE: usize> AlignedBuffer<T, SIZE>
where
T: ValueType,
{
#[must_use]
#[inline]
pub const fn new() -> Self {
Self {
data: MaybeUninit::uninit(),
}
}
pub const BUFFER_SIZE: usize = SIZE;
#[inline]
#[must_use]
pub const fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_mut_ptr().cast()
}
#[inline]
#[must_use]
pub const fn as_ptr(&self) -> *const T {
self.data.as_ptr().cast()
}
#[inline]
pub const unsafe fn as_slice(&self) -> &[T] {
unsafe { &*self.data.as_ptr() }
}
#[inline]
pub const unsafe fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { &mut *self.data.as_mut_ptr() }
}
#[inline]
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "illumos"
))]
pub fn getdents(&mut self, fd: &crate::fs::FileDes) -> isize {
unsafe { crate::util::getdents64(fd.0, self.as_mut_ptr().cast(), SIZE) }
}
#[inline]
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
pub(crate) unsafe fn getdirentries64(
&mut self,
fd: &crate::fs::FileDes,
basep: *mut i64,
) -> isize {
unsafe { crate::util::getdirentries64(fd.0, self.as_mut_ptr().cast(), SIZE, basep) }
}
#[inline]
pub unsafe fn get_unchecked<R>(&self, range: R) -> &R::Output
where
R: SliceIndex<[T]>,
{
unsafe { self.as_slice().get_unchecked(range) }
}
#[inline]
pub unsafe fn get_unchecked_mut<R>(&mut self, range: R) -> &mut R::Output
where
R: SliceIndex<[T]>,
{
unsafe { self.as_mut_slice().get_unchecked_mut(range) }
}
#[inline]
const unsafe fn assume_init(&self) -> &[T; SIZE] {
unsafe { &*self.data.as_ptr() }
}
#[inline]
const unsafe fn assume_init_mut(&mut self) -> &mut [T; SIZE] {
unsafe { &mut *self.data.as_mut_ptr() }
}
}