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 {}
impl Sealed for u64 {}
impl Sealed for i64 {}
impl Sealed for usize {}
impl Sealed for isize {}
impl Sealed for i32 {}
impl Sealed for u32 {}
}
pub trait ValueType: sealed::Sealed + Copy {}
impl ValueType for i8 {}
impl ValueType for u8 {}
impl ValueType for u64 {}
impl ValueType for i64 {}
impl ValueType for usize {}
impl ValueType for isize {}
impl ValueType for i32 {}
impl ValueType for u32 {}
#[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) }
}
}
impl<T> Default for AlignedBuffer<T, { crate::fs::types::BUFFER_SIZE }>
where
T: ValueType
+ Default
+ Copy
+ core::ops::Add
+ core::ops::Sub
+ core::ops::Mul
+ core::ops::Div,
{
#[inline]
fn default() -> Self {
Self {
data: MaybeUninit::new([T::default(); crate::fs::types::BUFFER_SIZE]),
}
}
}
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_of::<T>() * 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.assume_init_ref() }
}
#[inline]
pub const unsafe fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { self.data.assume_init_mut() }
}
#[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(), Self::BUFFER_SIZE) }
}
#[inline]
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
pub unsafe fn getdirentries64(&mut self, fd: &crate::fs::FileDes, basep: &mut i64) -> isize {
unsafe {
crate::util::getdirentries64(
fd.0,
self.as_mut_ptr().cast(),
Self::BUFFER_SIZE,
core::ptr::from_mut(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.assume_init_ref() }
}
#[inline]
const unsafe fn assume_init_mut(&mut self) -> &mut [T; SIZE] {
unsafe { self.data.assume_init_mut() }
}
}