use core::{cmp, fmt, hash, ptr::NonNull};
use crate::ffi;
#[repr(C)]
pub(crate) struct Opaque {
_data: [u8; 0],
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}
#[repr(transparent)]
pub struct NonNullConst<T>(NonNull<T>)
where
T: ?Sized;
#[repr(transparent)]
pub struct NonNullMut<T>(NonNull<T>)
where
T: ?Sized;
impl<T> NonNullConst<T>
where
T: ?Sized,
{
#[inline]
#[must_use]
pub const fn into_nonnull(self) -> NonNull<T> {
self.0
}
#[inline]
#[must_use]
pub const fn as_nonnull(&self) -> &NonNull<T> {
&self.0
}
#[inline]
#[must_use]
pub const unsafe fn new_unchecked(ptr: *const T) -> Self {
let mut_ptr = cast_mut(ptr);
let inner = unsafe { NonNull::new_unchecked(mut_ptr) };
Self(inner)
}
#[inline]
#[must_use]
pub fn new(ptr: *const T) -> Option<Self> {
let mut_ptr = cast_mut(ptr);
NonNull::new(mut_ptr).map(Self)
}
#[inline]
#[must_use]
pub const fn from_ref(r: &T) -> Self {
unsafe { Self::new_unchecked(r) }
}
#[inline]
#[must_use]
pub const fn as_ptr(&self) -> *const T {
self.0.as_ptr()
}
#[inline]
#[must_use]
pub unsafe fn as_ref<'a>(&self) -> &'a T {
unsafe { &*self.as_ptr() }
}
#[inline]
#[must_use]
pub const fn cast<U>(self) -> NonNullConst<U> {
let ptr = const_cast_to(self.0.as_ptr());
unsafe { NonNullConst::new_unchecked(ptr) }
}
}
impl NonNullConst<ffi::c_void> {
#[inline]
#[must_use]
pub const unsafe fn new_void_unchecked<U>(ptr: *const U) -> Self
where
U: ?Sized,
{
let void_ptr: *const ffi::c_void = const_cast_to(ptr);
let mut_void_ptr = cast_mut(void_ptr);
let inner = unsafe { NonNull::new_unchecked(mut_void_ptr) };
Self(inner)
}
#[inline]
#[must_use]
pub fn new_void<U>(ptr: *const U) -> Option<Self>
where
U: ?Sized,
{
let void_ptr: *const ffi::c_void = const_cast_to(ptr);
let mut_void_ptr = cast_mut(void_ptr);
NonNull::new(mut_void_ptr).map(Self)
}
}
#[cfg(feature = "std")]
impl NonNullConst<ffi::c_char> {
#[inline]
#[must_use]
pub unsafe fn as_c_str(&self) -> &std::ffi::CStr {
unsafe { std::ffi::CStr::from_ptr(self.as_ptr()) }
}
}
impl<T> NonNullMut<T>
where
T: ?Sized,
{
#[inline]
#[must_use]
pub const fn into_nonnull(self) -> NonNull<T> {
self.0
}
#[inline]
#[must_use]
pub const fn as_nonnull(&self) -> &NonNull<T> {
&self.0
}
#[inline]
#[must_use]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
let inner = unsafe { NonNull::new_unchecked(ptr) };
Self(inner)
}
#[inline]
#[must_use]
pub fn new(ptr: *mut T) -> Option<Self> {
NonNull::new(ptr).map(Self)
}
#[inline]
#[must_use]
pub fn from_mut(r: &mut T) -> Self {
unsafe { Self::new_unchecked(r) }
}
#[inline]
#[must_use]
pub const fn as_ptr(&self) -> *mut T {
self.0.as_ptr()
}
#[inline]
#[must_use]
pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
unsafe { &mut *self.as_ptr() }
}
#[inline]
#[must_use]
pub const fn cast<U>(self) -> NonNullMut<U> {
let ptr = mut_cast_to(self.0.as_ptr());
unsafe { NonNullMut::new_unchecked(ptr) }
}
#[inline]
#[must_use]
pub const fn cast_const(self) -> NonNullConst<T> {
let ptr = cast_const(self.0.as_ptr());
unsafe { NonNullConst::new_unchecked(ptr) }
}
}
impl NonNullMut<ffi::c_void> {
#[inline]
#[must_use]
pub const unsafe fn new_void_unchecked<U>(ptr: *mut U) -> Self
where
U: ?Sized,
{
let void_ptr: *mut ffi::c_void = mut_cast_to(ptr);
let inner = unsafe { NonNull::new_unchecked(void_ptr) };
Self(inner)
}
#[inline]
#[must_use]
pub fn new_void<U>(ptr: *mut U) -> Option<Self>
where
U: ?Sized,
{
let void_ptr: *mut ffi::c_void = mut_cast_to(ptr);
NonNull::new(void_ptr).map(Self)
}
}
impl<T> fmt::Debug for NonNullConst<T>
where
T: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl<T> fmt::Pointer for NonNullConst<T>
where
T: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.0, f)
}
}
impl<T> Clone for NonNullConst<T>
where
T: ?Sized,
{
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for NonNullConst<T> where T: ?Sized {}
impl<T> PartialEq for NonNullConst<T>
where
T: ?Sized,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
#[allow(ambiguous_wide_pointer_comparisons)]
self.0.eq(&other.0)
}
}
impl<T> Eq for NonNullConst<T> where T: ?Sized {}
impl<T> PartialOrd for NonNullConst<T>
where
T: ?Sized,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for NonNullConst<T>
where
T: ?Sized,
{
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
#[allow(ambiguous_wide_pointer_comparisons)]
self.0.cmp(&other.0)
}
}
impl<T> hash::Hash for NonNullConst<T>
where
T: ?Sized,
{
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}
impl<T> From<&T> for NonNullConst<T>
where
T: ?Sized,
{
#[inline]
fn from(r: &T) -> Self {
Self::from_ref(r)
}
}
impl<T> fmt::Debug for NonNullMut<T>
where
T: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl<T> fmt::Pointer for NonNullMut<T>
where
T: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.0, f)
}
}
impl<T> Clone for NonNullMut<T>
where
T: ?Sized,
{
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for NonNullMut<T> where T: ?Sized {}
impl<T> PartialEq for NonNullMut<T>
where
T: ?Sized,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
#[allow(ambiguous_wide_pointer_comparisons)]
self.0.eq(&other.0)
}
}
impl<T> Eq for NonNullMut<T> where T: ?Sized {}
impl<T> PartialOrd for NonNullMut<T>
where
T: ?Sized,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for NonNullMut<T>
where
T: ?Sized,
{
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
#[allow(ambiguous_wide_pointer_comparisons)]
self.0.cmp(&other.0)
}
}
impl<T> hash::Hash for NonNullMut<T>
where
T: ?Sized,
{
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}
impl<T> From<&mut T> for NonNullMut<T>
where
T: ?Sized,
{
#[inline]
fn from(r: &mut T) -> Self {
Self::from_mut(r)
}
}
const fn cast_mut<T>(p: *const T) -> *mut T
where
T: ?Sized,
{
p as _
}
const fn cast_const<T>(p: *mut T) -> *const T
where
T: ?Sized,
{
p as _
}
const fn const_cast_to<T, U>(p: *const T) -> *const U
where
T: ?Sized,
{
p as _
}
const fn mut_cast_to<T, U>(p: *mut T) -> *mut U
where
T: ?Sized,
{
p as _
}