use core::fmt;
use core::mem::MaybeUninit;
use core::ops::Deref;
use core::ptr;
use crate::offset;
use crate::offset::Offset;
use crate::Ptr;
#[repr(transparent)]
pub struct NonNull<T: ?Sized> {
p: ptr::NonNull<T>,
}
const _: () = {
const fn assert_pointer_sizes<T: ?Sized>() {
use core::mem::size_of;
assert!(size_of::<NonNull<T>>() == size_of::<Ptr<T>>());
assert!(size_of::<NonNull<T>>() == size_of::<ptr::NonNull<T>>());
assert!(size_of::<NonNull<T>>() == size_of::<*mut T>());
assert!(size_of::<NonNull<T>>() == size_of::<Option<NonNull<T>>>());
}
assert_pointer_sizes::<u8>();
assert_pointer_sizes::<i32>();
assert_pointer_sizes::<[i32]>();
assert_pointer_sizes::<str>();
assert_pointer_sizes::<dyn core::fmt::Debug>();
};
impl<T: ?Sized> PartialEq<Ptr<T>> for NonNull<T> {
fn eq(&self, other: &Ptr<T>) -> bool {
self.to_raw() == other.to_raw()
}
}
impl<T: ?Sized> PartialEq<NonNull<T>> for NonNull<T> {
fn eq(&self, other: &NonNull<T>) -> bool {
self.to_raw() == other.to_raw()
}
}
impl<T: ?Sized> Eq for NonNull<T> {}
impl<T: ?Sized> Clone for NonNull<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: ?Sized> Copy for NonNull<T> {}
impl<T: ?Sized> fmt::Debug for NonNull<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.p, f)
}
}
impl<T: ?Sized> fmt::Pointer for NonNull<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self.p, f)
}
}
impl<T: ?Sized> From<&T> for NonNull<T> {
fn from(value: &T) -> Self {
Self::new(value.into())
}
}
impl<T: ?Sized> From<&mut T> for NonNull<T> {
fn from(value: &mut T) -> Self {
Self::new(value.into())
}
}
impl<T: ?Sized> From<ptr::NonNull<T>> for NonNull<T> {
fn from(value: ptr::NonNull<T>) -> Self {
Self::new(value)
}
}
impl<T: ?Sized> From<NonNull<T>> for *const T {
fn from(value: NonNull<T>) -> Self {
value.to_raw()
}
}
impl<T: ?Sized> From<NonNull<T>> for *mut T {
fn from(value: NonNull<T>) -> Self {
value.to_raw()
}
}
impl<T: ?Sized> From<NonNull<T>> for ptr::NonNull<T> {
fn from(value: NonNull<T>) -> Self {
value.p
}
}
impl<T: ?Sized> Deref for NonNull<T> {
type Target = Ptr<T>;
fn deref(&self) -> &Ptr<T> {
self.as_ptr()
}
}
impl<T: ?Sized> NonNull<T> {
pub const fn new(ptr: ptr::NonNull<T>) -> Self {
NonNull { p: ptr }
}
pub const fn to_ptr(self) -> Ptr<T> {
Ptr::new(self.p.as_ptr())
}
pub const fn as_ptr(&self) -> &Ptr<T> {
let cast = Ptr::new(self as *const Self as *mut Self).cast::<Ptr<T>>();
unsafe { cast.deref_unbound() }
}
pub const fn cast<U>(self) -> NonNull<U> {
unsafe { self.to_ptr().cast().to_non_null_unchecked() }
}
}
impl<T> NonNull<T> {
pub const fn dangling() -> Self {
unsafe { Ptr::dangling().to_non_null_unchecked() }
}
pub const unsafe fn invalid(addr: usize) -> Self {
Ptr::invalid(addr).to_non_null_unchecked()
}
pub const unsafe fn from_exposed_addr(addr: usize) -> Self {
Ptr::invalid(addr).to_non_null_unchecked()
}
pub unsafe fn with_addr(self, addr: usize) -> NonNull<T> {
self.to_ptr().with_addr(addr).to_non_null_unchecked()
}
pub unsafe fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self {
self.with_addr(f(self.addr()))
}
pub fn is_aligned(self) -> bool {
self.to_ptr().is_aligned()
}
pub fn misalignment(self) -> usize {
self.to_ptr().misalignment()
}
pub unsafe fn align_down(self) -> Self {
self.to_ptr().align_down().to_non_null_unchecked()
}
pub unsafe fn align_up(self) -> Self {
self.to_ptr().align_up().to_non_null_unchecked()
}
pub unsafe fn at<U>(self, offset: impl Offset<T, U>) -> NonNull<U> {
self.to_ptr().at(offset).to_non_null_unchecked()
}
pub const unsafe fn at_raw(self, offset: offset::Measurement) -> NonNull<T> {
self.to_ptr().at_raw(offset).to_non_null_unchecked()
}
pub fn to_slice(self, len: usize) -> NonNull<[T]> {
unsafe { self.to_ptr().to_slice(len).to_non_null_unchecked() }
}
pub const fn to_uninit(self) -> NonNull<MaybeUninit<T>> {
self.cast()
}
}
impl<T> NonNull<[T]> {
pub const fn element(self) -> NonNull<T> {
self.cast::<T>()
}
}
impl<T, const N: usize> NonNull<[T; N]> {
pub const fn element(self) -> NonNull<T> {
self.cast::<T>()
}
}