use core::fmt;
use core::ptr::NonNull;
use super::TaggedPtr;
#[repr(transparent)]
pub struct Ptr<T> {
pub(crate) inner: Option<NonNull<T>>,
}
impl<T> Default for Ptr<T> {
#[inline]
fn default() -> Self {
Self { inner: None }
}
}
impl<T> Copy for Ptr<T> {}
impl<T> Clone for Ptr<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T> fmt::Debug for Ptr<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.inner, f)
}
}
impl<T> Ptr<T> {
#[inline]
pub const fn new(ptr: Option<NonNull<T>>) -> Self {
Self { inner: ptr }
}
#[inline]
pub const fn null() -> Self {
Self { inner: None }
}
#[inline]
pub const fn none() -> Self {
Self { inner: None }
}
#[inline]
pub fn cast<U>(self) -> Ptr<U> {
Ptr {
inner: self.inner.map(|p| p.cast()),
}
}
#[inline]
pub fn as_mut_ptr(self) -> *mut T {
self.inner
.map(|p| p.as_ptr())
.unwrap_or(core::ptr::null_mut())
}
#[inline]
pub fn as_ptr(self) -> *const T {
self.inner
.map(|p| p.as_ptr() as *const T)
.unwrap_or(core::ptr::null())
}
#[inline]
pub const fn option(self) -> Option<NonNull<T>> {
self.inner
}
#[inline]
pub const fn as_option(self) -> Option<NonNull<T>> {
self.inner
}
#[inline]
pub fn is_null(self) -> bool {
self.inner.is_none()
}
#[inline]
pub fn is_some(self) -> bool {
self.inner.is_some()
}
#[inline]
pub fn is_none(self) -> bool {
self.inner.is_none()
}
#[inline]
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
self.inner.map(|p| unsafe { p.as_ref() })
}
#[inline]
pub unsafe fn as_mut<'a>(mut self) -> Option<&'a mut T> {
self.inner.as_mut().map(|p| unsafe { p.as_mut() })
}
#[inline]
pub fn expect(self, msg: &str) -> NonNull<T> {
self.inner.expect(msg)
}
#[inline]
pub fn unwrap(self) -> NonNull<T> {
self.inner
.expect("called `Ptr::unwrap()` on a null pointer")
}
#[inline]
pub fn unwrap_or(self, default: NonNull<T>) -> NonNull<T> {
self.inner.unwrap_or(default)
}
#[inline]
pub fn map<U, F>(self, f: F) -> Ptr<U>
where
F: FnOnce(NonNull<T>) -> NonNull<U>,
{
Ptr::new(self.inner.map(f))
}
#[inline]
pub fn map_or<U, F>(self, default: U, f: F) -> U
where
F: FnOnce(NonNull<T>) -> U,
{
self.inner.map_or(default, f)
}
#[inline]
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
where
D: FnOnce() -> U,
F: FnOnce(NonNull<T>) -> U,
{
self.inner.map_or_else(default, f)
}
#[inline]
pub unsafe fn read(self) -> T {
unsafe { core::ptr::read(self.as_ptr()) }
}
#[inline]
pub unsafe fn read_volatile(self) -> T {
unsafe { core::ptr::read_volatile(self.as_ptr()) }
}
#[inline]
pub unsafe fn read_unaligned(self) -> T {
unsafe { core::ptr::read_unaligned(self.as_ptr()) }
}
#[inline]
pub unsafe fn write(self, val: T) {
unsafe { core::ptr::write(self.as_mut_ptr(), val) }
}
#[inline]
pub unsafe fn write_volatile(self, val: T) {
unsafe { core::ptr::write_volatile(self.as_mut_ptr(), val) }
}
#[inline]
pub unsafe fn write_unaligned(self, val: T) {
unsafe { core::ptr::write_unaligned(self.as_mut_ptr(), val) }
}
#[inline]
pub unsafe fn replace(self, val: T) -> T {
unsafe { core::ptr::replace(self.as_mut_ptr(), val) }
}
#[inline]
pub unsafe fn swap(self, with: Ptr<T>) {
unsafe { core::ptr::swap(self.as_mut_ptr(), with.as_mut_ptr()) }
}
#[inline]
pub unsafe fn copy_to(self, dest: Ptr<T>, count: usize) {
unsafe { core::ptr::copy(self.as_ptr(), dest.as_mut_ptr(), count) }
}
#[inline]
pub unsafe fn copy_to_nonoverlapping(self, dest: Ptr<T>, count: usize) {
unsafe { core::ptr::copy_nonoverlapping(self.as_ptr(), dest.as_mut_ptr(), count) }
}
#[inline]
pub unsafe fn copy_from(self, src: Ptr<T>, count: usize) {
unsafe { core::ptr::copy(src.as_ptr(), self.as_mut_ptr(), count) }
}
#[inline]
pub unsafe fn copy_from_nonoverlapping(self, src: Ptr<T>, count: usize) {
unsafe { core::ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), count) }
}
#[inline]
pub unsafe fn offset(self, count: isize) -> Self {
Self {
inner: self.inner.map(|p| unsafe { NonNull::new_unchecked(p.as_ptr().offset(count)) }),
}
}
#[inline]
pub unsafe fn add(self, count: usize) -> Self {
Self {
inner: self.inner.map(|p| unsafe { NonNull::new_unchecked(p.as_ptr().add(count)) }),
}
}
#[inline]
pub unsafe fn sub(self, count: usize) -> Self {
Self {
inner: self.inner.map(|p| unsafe { NonNull::new_unchecked(p.as_ptr().sub(count)) }),
}
}
#[inline]
pub fn wrapping_offset(self, count: isize) -> Self {
Self {
inner: self.inner.map(|p| unsafe { NonNull::new_unchecked(p.as_ptr().wrapping_offset(count)) }),
}
}
#[inline]
pub fn wrapping_add(self, count: usize) -> Self {
Self {
inner: self.inner.map(|p| unsafe { NonNull::new_unchecked(p.as_ptr().wrapping_add(count)) }),
}
}
#[inline]
pub fn wrapping_sub(self, count: usize) -> Self {
Self {
inner: self.inner.map(|p| unsafe { NonNull::new_unchecked(p.as_ptr().wrapping_sub(count)) }),
}
}
}
impl<T> fmt::Pointer for Ptr<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.as_ptr(), f)
}
}
impl<T> PartialOrd for Ptr<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for Ptr<T> {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.as_ptr().cmp(&other.as_ptr())
}
}
impl<T> From<Ptr<T>> for *const T {
#[inline]
fn from(ptr: Ptr<T>) -> Self {
ptr.as_ptr()
}
}
impl<T> From<Ptr<T>> for *mut T {
#[inline]
fn from(ptr: Ptr<T>) -> Self {
ptr.as_mut_ptr()
}
}
impl<T> From<Ptr<T>> for Option<*const T> {
#[inline]
fn from(ptr: Ptr<T>) -> Self {
ptr.inner.map(|p| p.as_ptr() as *const T)
}
}
impl<T> From<Ptr<T>> for Option<*mut T> {
#[inline]
fn from(ptr: Ptr<T>) -> Self {
ptr.inner.map(|p| p.as_ptr())
}
}
impl<T> PartialEq for Ptr<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl<T> Eq for Ptr<T> {}
impl<T> core::hash::Hash for Ptr<T> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.inner.hash(state);
}
}
impl<T> PartialEq<Option<NonNull<T>>> for Ptr<T> {
#[inline]
fn eq(&self, other: &Option<NonNull<T>>) -> bool {
self.inner == *other
}
}
impl<T> PartialEq<NonNull<T>> for Ptr<T> {
#[inline]
fn eq(&self, other: &NonNull<T>) -> bool {
self.inner == Some(*other)
}
}
impl<T> PartialEq<*const T> for Ptr<T> {
#[inline]
fn eq(&self, other: &*const T) -> bool {
self.as_ptr() == *other
}
}
impl<T> PartialEq<*mut T> for Ptr<T> {
#[inline]
fn eq(&self, other: &*mut T) -> bool {
self.as_mut_ptr() == *other
}
}
impl<T> From<Option<NonNull<T>>> for Ptr<T> {
#[inline]
fn from(ptr: Option<NonNull<T>>) -> Self {
Self { inner: ptr }
}
}
impl<T> From<NonNull<T>> for Ptr<T> {
#[inline]
fn from(ptr: NonNull<T>) -> Self {
Self { inner: Some(ptr) }
}
}
impl<T> From<*const T> for Ptr<T> {
#[inline]
fn from(ptr: *const T) -> Self {
Self {
inner: NonNull::new(ptr as *mut T),
}
}
}
impl<T> From<*mut T> for Ptr<T> {
#[inline]
fn from(ptr: *mut T) -> Self {
Self {
inner: NonNull::new(ptr),
}
}
}
impl<T> From<TaggedPtr<T>> for Ptr<T> {
#[inline]
fn from(tagged: TaggedPtr<T>) -> Self {
tagged.ptr
}
}
impl<T> From<Ptr<T>> for Option<NonNull<T>> {
#[inline]
fn from(ptr: Ptr<T>) -> Self {
ptr.inner
}
}