use core::{ cmp::Ordering, fmt, hash, marker::Send, num::NonZero, ops::{Deref, DerefMut}, ptr::NonNull, }; #[repr(transparent)] pub struct SendNonNull(NonNull); impl fmt::Debug for SendNonNull { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Pointer::fmt(&self.as_ptr(), f) } } impl Copy for SendNonNull {} impl Clone for SendNonNull { fn clone(&self) -> Self { *self } } impl Eq for SendNonNull {} impl PartialEq for SendNonNull { fn eq(&self, other: &Self) -> bool { self.as_ptr() == other.as_ptr() } } impl Ord for SendNonNull { fn cmp(&self, other: &Self) -> Ordering { self.as_ptr().cmp(&other.as_ptr()) } } impl PartialOrd for SendNonNull { fn partial_cmp(&self, other: &Self) -> Option { self.as_ptr().partial_cmp(&other.as_ptr()) } } impl hash::Hash for SendNonNull { fn hash(&self, state: &mut H) { self.as_ptr().hash(state); } } impl From> for SendNonNull { fn from(ptr: NonNull) -> Self { Self(ptr) } } impl From> for NonNull { fn from(ptr: SendNonNull) -> Self { ptr.0 } } impl From<&mut T> for SendNonNull { fn from(ptr: &mut T) -> Self { Self(NonNull::from(ptr)) } } impl From<&T> for SendNonNull { fn from(ptr: &T) -> Self { Self(NonNull::from(ptr)) } } impl fmt::Pointer for SendNonNull { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { as fmt::Pointer>::fmt(&self.0, f) } } unsafe impl Send for SendNonNull {} impl Deref for SendNonNull { type Target = NonNull; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for SendNonNull { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl SendNonNull { pub const fn new(ptr: *mut T) -> Option { match NonNull::new(ptr) { Some(ptr) => Some(Self(ptr)), None => None, } } pub const fn dangling() -> Self { Self(NonNull::dangling()) } pub const fn cast(self) -> SendNonNull { SendNonNull(self.0.cast()) } pub fn with_addr(self, addr: NonZero) -> Self { // SAFETY: addr is non-zero, so the pointer is valid. unsafe { Self(NonNull::new_unchecked( self.as_ptr().with_addr(addr.get()) as *mut _ )) } } pub fn map_addr(self, f: impl FnOnce(NonZero) -> NonZero) -> Self { // SAFETY: addr is non-zero, so the pointer is valid. self.with_addr(f(self.addr())) } pub unsafe fn offset(self, offset: isize) -> Self { // SAFETY: self is a valid pointer, offset is guaranteed to point to a valid memory location by the contract of `offset` unsafe { Self(NonNull::new_unchecked(self.as_ptr().offset(offset))) } } pub unsafe fn byte_offset(self, offset: isize) -> Self { // SAFETY: self is a valid pointer, offset is guaranteed to point to a valid memory location by the contract of `offset` unsafe { Self(NonNull::new_unchecked(self.as_ptr().byte_offset(offset))) } } pub unsafe fn add(self, count: usize) -> Self { // SAFETY: self is a valid pointer, count is guaranteed to point to a valid memory location by the contract of `add` unsafe { Self(NonNull::new_unchecked(self.as_ptr().add(count))) } } pub unsafe fn byte_add(self, count: usize) -> Self { // SAFETY: self is a valid pointer, count is guaranteed to point to a valid memory location by the contract of `add` unsafe { Self(NonNull::new_unchecked(self.as_ptr().byte_add(count))) } } pub const fn new_const(ptr: *const T) -> Option { Self::new(ptr.cast_mut()) } /// ptr must be non-null pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: ptr must be non-null, which is guaranteed by the caller. unsafe { Self(NonNull::new_unchecked(ptr)) } } }