use crate::memory::DeviceCopy;
use cust_raw::CUdeviceptr;
use core::{
fmt::{self, Debug, Pointer},
hash::Hash,
ptr,
};
use std::ffi::c_void;
use std::marker::PhantomData;
use std::mem::size_of;
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct DevicePointer<T: ?Sized + DeviceCopy> {
ptr: CUdeviceptr,
marker: PhantomData<*mut T>,
}
unsafe impl<T: ?Sized + DeviceCopy> DeviceCopy for DevicePointer<T> {}
impl<T: DeviceCopy> Pointer for DevicePointer<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let ptr = self.ptr as *const c_void;
fmt::Pointer::fmt(&ptr, f)
}
}
impl<T: ?Sized + DeviceCopy> DevicePointer<T> {
pub fn as_ptr(&self) -> *const T {
self.ptr as *const T
}
pub fn as_mut_ptr(&self) -> *mut T {
self.ptr as *mut T
}
pub fn as_raw(&self) -> CUdeviceptr {
self.ptr
}
pub fn from_raw(ptr: CUdeviceptr) -> Self {
Self {
ptr,
marker: PhantomData,
}
}
pub fn is_null(self) -> bool {
self.ptr == 0
}
pub fn null() -> Self
where
T: Sized,
{
Self {
ptr: 0,
marker: PhantomData,
}
}
pub unsafe fn offset(self, count: isize) -> Self
where
T: Sized,
{
let ptr = self.ptr + (count as usize * size_of::<T>()) as u64;
Self {
ptr,
marker: PhantomData,
}
}
pub fn wrapping_offset(self, count: isize) -> Self
where
T: Sized,
{
let ptr = self
.ptr
.wrapping_add((count as usize * size_of::<T>()) as u64);
Self {
ptr,
marker: PhantomData,
}
}
#[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())
}
pub fn cast<U: DeviceCopy>(self) -> DevicePointer<U> {
DevicePointer::from_raw(self.ptr)
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct UnifiedPointer<T: ?Sized + DeviceCopy>(*mut T);
unsafe impl<T: ?Sized + DeviceCopy> DeviceCopy for UnifiedPointer<T> {}
impl<T: DeviceCopy> Pointer for UnifiedPointer<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self.0, f)
}
}
impl<T: ?Sized + DeviceCopy> 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())
}
}