151 lines
3.3 KiB
Rust
151 lines
3.3 KiB
Rust
use core::marker::PhantomData;
|
|
use core::ops::Index;
|
|
|
|
#[repr(transparent)]
|
|
#[derive(Debug)]
|
|
pub struct Ptr<T: ?Sized> {
|
|
ptr: *const T,
|
|
}
|
|
|
|
impl<T: ?Sized> Clone for Ptr<T> {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
impl<T: ?Sized> Copy for Ptr<T> {}
|
|
|
|
impl<T: ?Sized> PartialEq for Ptr<T> {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
core::ptr::addr_eq(self.ptr, other.ptr)
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> Eq for Ptr<T> {}
|
|
|
|
unsafe impl<T: ?Sized + Send> Send for Ptr<T> {}
|
|
unsafe impl<T: ?Sized + Sync> Sync for Ptr<T> {}
|
|
|
|
impl<T> Ptr<T> {
|
|
pub const fn null() -> Self {
|
|
Self {
|
|
ptr: core::ptr::null(),
|
|
}
|
|
}
|
|
|
|
pub const fn is_null(self) -> bool {
|
|
self.ptr.is_null()
|
|
}
|
|
|
|
pub fn from_raw(ptr: *const T) -> Self {
|
|
Self { ptr }
|
|
}
|
|
|
|
pub fn as_raw(self) -> *const T {
|
|
self.ptr
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub unsafe fn as_ref<'a>(self) -> &'a T {
|
|
debug_assert!(!self.is_null(), "null Ptr dereference");
|
|
unsafe { &*self.ptr }
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn get<'a>(self) -> Option<&'a T> {
|
|
if self.is_null() {
|
|
None
|
|
} else {
|
|
Some(unsafe { &*self.ptr })
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub unsafe fn at<'a>(self, index: usize) -> &'a T {
|
|
debug_assert!(!self.is_null(), "null Ptr array access");
|
|
unsafe { &*self.ptr.add(index) }
|
|
}
|
|
|
|
/// Get element at index, returns None if ptr is null
|
|
#[inline(always)]
|
|
pub fn get_at<'a>(self, index: usize) -> Option<&'a T> {
|
|
if self.is_null() {
|
|
None
|
|
} else {
|
|
Some(unsafe { &*self.ptr.add(index) })
|
|
}
|
|
}
|
|
|
|
/// Offset the pointer, returning a new Ptr
|
|
#[inline(always)]
|
|
pub unsafe fn add(self, count: usize) -> Self {
|
|
Self {
|
|
ptr: unsafe { self.ptr.add(count) },
|
|
}
|
|
}
|
|
|
|
/// Convert to slice (requires knowing the length)
|
|
#[inline(always)]
|
|
pub unsafe fn as_slice<'a>(self, len: usize) -> &'a [T] {
|
|
debug_assert!(!self.is_null() || len == 0, "null Ptr to non-empty slice");
|
|
if len == 0 {
|
|
&[]
|
|
} else {
|
|
unsafe { core::slice::from_raw_parts(self.ptr, len) }
|
|
}
|
|
}
|
|
|
|
/// Convert to slice, returns None if null
|
|
#[inline(always)]
|
|
pub fn get_slice<'a>(self, len: usize) -> Option<&'a [T]> {
|
|
if self.is_null() {
|
|
if len == 0 { Some(&[]) } else { None }
|
|
} else {
|
|
Some(unsafe { core::slice::from_raw_parts(self.ptr, len) })
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> core::ops::Deref for Ptr<T> {
|
|
type Target = T;
|
|
|
|
#[inline(always)]
|
|
fn deref(&self) -> &T {
|
|
debug_assert!(!self.is_null(), "Null Ptr dereference");
|
|
unsafe { &*self.ptr }
|
|
}
|
|
}
|
|
|
|
impl<T> Default for Ptr<T> {
|
|
fn default() -> Self {
|
|
Self::null()
|
|
}
|
|
}
|
|
|
|
impl<T> From<&T> for Ptr<T> {
|
|
fn from(r: &T) -> Self {
|
|
Self { ptr: r as *const T }
|
|
}
|
|
}
|
|
|
|
impl<T> From<&[T]> for Ptr<T> {
|
|
fn from(slice: &[T]) -> Self {
|
|
Self {
|
|
ptr: slice.as_ptr(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> From<*const T> for Ptr<T> {
|
|
fn from(ptr: *const T) -> Self {
|
|
Self { ptr }
|
|
}
|
|
}
|
|
|
|
impl<T> From<Option<&T>> for Ptr<T> {
|
|
fn from(opt: Option<&T>) -> Self {
|
|
match opt {
|
|
Some(r) => Ptr::from(r),
|
|
None => Ptr::null(),
|
|
}
|
|
}
|
|
}
|