159 lines
4.1 KiB
Rust
159 lines
4.1 KiB
Rust
use core::{
|
|
cmp::Ordering,
|
|
fmt, hash,
|
|
marker::Send,
|
|
num::NonZero,
|
|
ops::{Deref, DerefMut},
|
|
ptr::NonNull,
|
|
};
|
|
|
|
#[repr(transparent)]
|
|
pub struct SendNonNull<T>(NonNull<T>);
|
|
|
|
impl<T> fmt::Debug for SendNonNull<T> {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
|
}
|
|
}
|
|
|
|
impl<T> Copy for SendNonNull<T> {}
|
|
|
|
impl<T> Clone for SendNonNull<T> {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
|
|
impl<T> Eq for SendNonNull<T> {}
|
|
|
|
impl<T> PartialEq for SendNonNull<T> {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.as_ptr() == other.as_ptr()
|
|
}
|
|
}
|
|
|
|
impl<T> Ord for SendNonNull<T> {
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
self.as_ptr().cmp(&other.as_ptr())
|
|
}
|
|
}
|
|
|
|
impl<T> PartialOrd for SendNonNull<T> {
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
self.as_ptr().partial_cmp(&other.as_ptr())
|
|
}
|
|
}
|
|
|
|
impl<T> hash::Hash for SendNonNull<T> {
|
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
|
self.as_ptr().hash(state);
|
|
}
|
|
}
|
|
|
|
impl<T> From<NonNull<T>> for SendNonNull<T> {
|
|
fn from(ptr: NonNull<T>) -> Self {
|
|
Self(ptr)
|
|
}
|
|
}
|
|
|
|
impl<T> From<SendNonNull<T>> for NonNull<T> {
|
|
fn from(ptr: SendNonNull<T>) -> Self {
|
|
ptr.0
|
|
}
|
|
}
|
|
|
|
impl<T> From<&mut T> for SendNonNull<T> {
|
|
fn from(ptr: &mut T) -> Self {
|
|
Self(NonNull::from(ptr))
|
|
}
|
|
}
|
|
|
|
impl<T> From<&T> for SendNonNull<T> {
|
|
fn from(ptr: &T) -> Self {
|
|
Self(NonNull::from(ptr))
|
|
}
|
|
}
|
|
|
|
impl<T> fmt::Pointer for SendNonNull<T> {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
<NonNull<T> as fmt::Pointer>::fmt(&self.0, f)
|
|
}
|
|
}
|
|
|
|
unsafe impl<T> Send for SendNonNull<T> {}
|
|
|
|
impl<T> Deref for SendNonNull<T> {
|
|
type Target = NonNull<T>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl<T> DerefMut for SendNonNull<T> {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.0
|
|
}
|
|
}
|
|
|
|
impl<T> SendNonNull<T> {
|
|
pub const fn new(ptr: *mut T) -> Option<Self> {
|
|
match NonNull::new(ptr) {
|
|
Some(ptr) => Some(Self(ptr)),
|
|
None => None,
|
|
}
|
|
}
|
|
|
|
pub const fn dangling() -> Self {
|
|
Self(NonNull::dangling())
|
|
}
|
|
|
|
pub const fn cast<U>(self) -> SendNonNull<U> {
|
|
SendNonNull(self.0.cast())
|
|
}
|
|
|
|
pub fn with_addr(self, addr: NonZero<usize>) -> 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<usize>) -> NonZero<usize>) -> 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> {
|
|
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)) }
|
|
}
|
|
}
|