#![allow(clippy::missing_inline_in_public_items)]
use crate::{c_char, dirent64};
use core::convert::From;
use core::ffi::CStr;
use core::fmt;
use core::marker::PhantomData;
use core::ptr::NonNull;
#[repr(transparent)]
pub struct Unique<T: ?Sized>(NonNull<T>, PhantomData<T>);
unsafe impl<T: Send + ?Sized> Send for Unique<T> {}
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> {}
impl<T: Sized> Unique<T> {
#[inline]
#[must_use]
pub const fn dangling() -> Self {
unsafe { Self::new_unchecked(core::ptr::dangling_mut::<T>()) }
}
}
impl<T: ?Sized> Unique<T> {
#[inline]
pub const unsafe fn new_unchecked(ptr: *const T) -> Self {
unsafe { Self(NonNull::new_unchecked(ptr.cast_mut()), PhantomData) }
}
#[inline]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub const fn new(ptr: *const T) -> Option<Self> {
#[expect(clippy::if_not_else, reason = "prefer to take this branch")]
if !ptr.is_null() {
Some(unsafe { Self::new_unchecked(ptr) })
} else {
None
}
}
#[inline]
#[must_use]
pub const fn as_ptr(self) -> *const T {
self.0.as_ptr().cast_const()
}
#[inline]
#[must_use]
pub const fn as_non_null_ptr(self) -> NonNull<T> {
self.0
}
#[inline]
#[must_use]
pub const unsafe fn as_ref(&self) -> &T {
unsafe { &*self.as_ptr() }
}
#[inline]
#[must_use]
pub const fn cast<U>(self) -> Unique<U> {
unsafe { Unique::new_unchecked(self.as_ptr().cast()) }
}
}
impl<T: ?Sized> Clone for Unique<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T: ?Sized> Copy for Unique<T> {}
impl<T: ?Sized> fmt::Debug for Unique<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.as_ptr(), f)
}
}
impl<T: ?Sized> fmt::Pointer for Unique<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.as_ptr(), f)
}
}
impl<T: ?Sized> From<&mut T> for Unique<T> {
#[inline]
fn from(reference: &mut T) -> Self {
unsafe { Self::new_unchecked(core::ptr::from_mut(reference)) }
}
}
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
#[inline]
fn from(unique: Unique<T>) -> Self {
unique.0
}
}
impl Unique<dirent64> {
#[inline]
#[must_use]
pub const fn d_ino(self) -> u64 {
unsafe { access_dirent!(self.0.as_ptr(), d_ino) }
}
#[inline]
#[must_use]
pub const fn d_type(self) -> u8 {
#[cfg(has_d_type)]
unsafe {
access_dirent!(self.0.as_ptr(), d_type)
}
#[cfg(not(has_d_type))]
libc::DT_UNKNOWN
}
#[must_use]
#[inline]
#[cfg(has_d_namlen)]
pub const fn d_namlen(self) -> usize {
unsafe { access_dirent!(self.0.as_ptr(), d_namlen) }
}
#[must_use]
#[inline]
pub fn d_name_slice<'pointer>(self) -> &'pointer [u8] {
unsafe { core::slice::from_raw_parts(self.d_name().cast(), self.name_length()) }
}
#[must_use]
#[inline]
pub fn d_name_slice_c_str<'pointer>(self) -> &'pointer CStr {
let as_slice =
unsafe { core::slice::from_raw_parts(self.d_name().cast(), self.name_length() + 1) };
unsafe { CStr::from_bytes_with_nul_unchecked(as_slice) }
}
#[inline]
#[must_use]
pub const fn d_name(self) -> *const c_char {
unsafe { access_dirent!(self.0.as_ptr(), d_name) }
}
#[inline]
#[must_use]
pub fn name_length(self) -> usize {
unsafe { crate::util::dirent_name_length(self.as_ptr()) }
}
}