use core::{
ffi::CStr,
fmt,
marker::PhantomData,
ops::{Deref, DerefMut},
};
pub struct Pointer<'a, T: Pointee + ?Sized> {
target: *const T,
_value: PhantomData<fn() -> &'a T>,
}
impl<'a, T: Pointee + ?Sized> Pointer<'a, T> {
pub const unsafe fn new(target: *const T) -> Option<Self> {
if !target.is_null() {
Some(Self {
target,
_value: PhantomData,
})
} else {
None
}
}
pub const fn of(value: &'a T) -> Self {
Self {
target: value,
_value: PhantomData,
}
}
}
impl<T: Pointee + ?Sized> Deref for Pointer<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.target }
}
}
impl<T: Pointee + ?Sized> AsRef<T> for Pointer<'_, T> {
fn as_ref(&self) -> &T {
self
}
}
impl<T: Pointee + fmt::Debug + ?Sized> fmt::Debug for Pointer<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Pointer")
.field("type", &T::TYPE)
.field("ptr", &self.target)
.finish()
}
}
pub struct PointerMut<'a, T: Pointee + ?Sized> {
target: *mut T,
_value: PhantomData<fn() -> &'a mut T>,
}
impl<'a, T: Pointee + ?Sized> PointerMut<'a, T> {
pub const unsafe fn new(target: *mut T) -> Option<Self> {
if !target.is_null() {
Some(Self {
target,
_value: PhantomData,
})
} else {
None
}
}
pub const fn of(value: &'a mut T) -> Self {
Self {
target: value,
_value: PhantomData,
}
}
}
impl<T: Pointee + ?Sized> Deref for PointerMut<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.target }
}
}
impl<T: Pointee + ?Sized> DerefMut for PointerMut<'_, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.target }
}
}
impl<T: Pointee + ?Sized> AsRef<T> for PointerMut<'_, T> {
fn as_ref(&self) -> &T {
self
}
}
impl<T: Pointee + fmt::Debug + ?Sized> fmt::Debug for PointerMut<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PointerMut")
.field("type", &T::TYPE)
.field("ptr", &self.target)
.finish()
}
}
pub trait Pointee {
const TYPE: &'static CStr;
}