use crate::memory::DeviceCopy;
use core::{
cmp::Ordering,
fmt::{self, Debug, Pointer},
hash::{Hash, Hasher},
ptr,
};
macro_rules! derive_traits {
( $( $Ptr:ty )* ) => ($(
impl<T: ?Sized> Debug for $Ptr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl<T: ?Sized> Pointer for $Ptr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Pointer::fmt(&self.0, f)
}
}
impl<T: ?Sized> Hash for $Ptr {
fn hash<H: Hasher>(&self, h: &mut H) {
Hash::hash(&self.0, h);
}
}
impl<T: ?Sized> PartialEq for $Ptr {
fn eq(&self, other: &$Ptr) -> bool {
PartialEq::eq(&self.0, &other.0)
}
}
impl<T: ?Sized> Eq for $Ptr {}
impl<T: ?Sized> PartialOrd for $Ptr {
fn partial_cmp(&self, other: &$Ptr) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.0, &other.0)
}
}
impl<T: ?Sized> Ord for $Ptr {
fn cmp(&self, other: &$Ptr) -> Ordering {
Ord::cmp(&self.0, &other.0)
}
}
impl<T: ?Sized> Clone for $Ptr {
fn clone(&self) -> Self {
Self(self.0)
}
}
impl<T: ?Sized> Copy for $Ptr {}
)*)
}
derive_traits!(DevicePointer<T> UnifiedPointer<T>);
#[repr(transparent)]
pub struct DevicePointer<T: ?Sized>(*mut T);
unsafe impl<T: ?Sized> DeviceCopy for DevicePointer<T> {}
impl<T: ?Sized> DevicePointer<T> {
pub unsafe fn wrap(ptr: *mut T) -> Self {
DevicePointer(ptr)
}
pub fn as_raw(self) -> *const T {
self.0
}
pub fn as_raw_mut(&mut self) -> *mut T {
self.0
}
pub fn is_null(self) -> bool {
self.0.is_null()
}
pub fn null() -> Self
where
T: Sized,
{
unsafe { Self::wrap(ptr::null_mut()) }
}
pub unsafe fn offset(self, count: isize) -> Self
where
T: Sized,
{
Self::wrap(self.0.offset(count))
}
pub fn wrapping_offset(self, count: isize) -> Self
where
T: Sized,
{
unsafe { Self::wrap(self.0.wrapping_offset(count)) }
}
#[allow(clippy::should_implement_trait)]
pub unsafe fn add(self, count: usize) -> Self
where
T: Sized,
{
self.offset(count as isize)
}
#[allow(clippy::should_implement_trait)]
pub unsafe fn sub(self, count: usize) -> Self
where
T: Sized,
{
self.offset((count as isize).wrapping_neg())
}
pub fn wrapping_add(self, count: usize) -> Self
where
T: Sized,
{
self.wrapping_offset(count as isize)
}
pub fn wrapping_sub(self, count: usize) -> Self
where
T: Sized,
{
self.wrapping_offset((count as isize).wrapping_neg())
}
}
#[repr(transparent)]
pub struct UnifiedPointer<T: ?Sized>(*mut T);
unsafe impl<T: ?Sized + DeviceCopy> DeviceCopy for UnifiedPointer<T> {}
impl<T: ?Sized> UnifiedPointer<T> {
pub unsafe fn wrap(ptr: *mut T) -> Self {
UnifiedPointer(ptr)
}
pub fn as_raw(self) -> *const T {
self.0
}
pub fn as_raw_mut(&mut self) -> *mut T {
self.0
}
pub fn is_null(self) -> bool {
self.0.is_null()
}
pub fn null() -> Self
where
T: Sized,
{
unsafe { Self::wrap(ptr::null_mut()) }
}
pub unsafe fn offset(self, count: isize) -> Self
where
T: Sized,
{
Self::wrap(self.0.offset(count))
}
pub fn wrapping_offset(self, count: isize) -> Self
where
T: Sized,
{
unsafe { Self::wrap(self.0.wrapping_offset(count)) }
}
#[allow(clippy::should_implement_trait)]
pub unsafe fn add(self, count: usize) -> Self
where
T: Sized,
{
self.offset(count as isize)
}
#[allow(clippy::should_implement_trait)]
pub unsafe fn sub(self, count: usize) -> Self
where
T: Sized,
{
self.offset((count as isize).wrapping_neg())
}
pub fn wrapping_add(self, count: usize) -> Self
where
T: Sized,
{
self.wrapping_offset(count as isize)
}
pub fn wrapping_sub(self, count: usize) -> Self
where
T: Sized,
{
self.wrapping_offset((count as isize).wrapping_neg())
}
}