use crate::alloc::MemPool;
use crate::alloc::PmemUsage;
use crate::{PSafe, TxOutSafe};
use std::fmt::{Debug, Display, Formatter};
use std::marker::PhantomData;
use std::ops::*;
use std::ptr::NonNull;
#[derive(Eq)]
pub struct Ptr<T: ?Sized, A: MemPool> {
off: u64,
marker: PhantomData<(A, T)>,
}
impl<A: MemPool, T> !Send for Ptr<T, A> {}
impl<A: MemPool, T> !Sync for Ptr<T, A> {}
impl<A: MemPool, T> !TxOutSafe for Ptr<T, A> {}
unsafe impl<A: MemPool, T: PSafe + ?Sized> PSafe for Ptr<T, A> {}
impl<A: MemPool, T: ?Sized> Ptr<T, A> {
#[inline]
pub(crate) fn try_deref(&self) -> Option<&T> {
if self.is_dangling() {
None
} else {
Some(self.as_ref())
}
}
#[inline]
pub(crate) fn try_deref_mut(&mut self) -> Option<&mut T> {
if self.is_dangling() {
None
} else {
Some(self.as_mut())
}
}
}
impl<A: MemPool, T: ?Sized> Ptr<T, A> {
#[inline]
pub(crate) fn new(p: &T) -> Option<Ptr<T, A>> {
if let Ok(off) = A::off(p) {
Some(Self {
off,
marker: PhantomData,
})
} else {
None
}
}
#[inline]
pub(crate) fn as_mut(&mut self) -> &mut T {
unsafe { A::get_mut_unchecked(self.off) }
}
#[inline]
pub(crate) fn as_ref(&self) -> &T {
unsafe { A::get_unchecked(self.off) }
}
#[inline]
pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
unsafe { A::get_mut_unchecked(self.off) }
}
#[inline]
pub(crate) fn get_mut_ptr(&self) -> *mut T {
unsafe { A::get_mut_unchecked(self.off) }
}
#[inline]
pub(crate) fn as_ptr(&self) -> *const T {
unsafe { A::get_mut_unchecked(self.off) }
}
#[inline]
#[allow(clippy::mut_from_ref)]
pub(crate) fn get_mut(&self) -> &mut T {
unsafe { A::get_mut_unchecked(self.off) }
}
pub(crate) unsafe fn dup(&self) -> Ptr<T, A> {
let src = self.as_ref();
let dst = A::alloc_for_value(src);
let trg = A::off_unchecked(dst);
let len = std::alloc::Layout::for_value(src).size();
std::ptr::copy_nonoverlapping(
src as *const T as *const u8,
dst as *mut T as *mut u8,
len,
);
Ptr::from_off_unchecked(trg)
}
#[inline]
pub fn is_dangling(&self) -> bool {
self.off == u64::MAX
}
#[inline]
pub fn off(&self) -> u64 {
self.off
}
#[inline]
pub fn off_ref(&self) -> &u64 {
&self.off
}
#[inline]
pub(crate) fn off_mut(&self) -> &mut u64 {
unsafe { &mut *(&self.off as *const u64 as *mut u64) }
}
#[inline]
pub(crate) fn replace(&self, new: u64) -> u64 {
let old = self.off;
*self.off_mut() = new;
old
}
#[inline]
pub(crate) unsafe fn new_unchecked(ptr: *const T) -> Self {
Self {
off: A::off_unchecked(ptr),
marker: PhantomData,
}
}
#[inline]
pub(crate) const fn dangling() -> Ptr<T, A> {
Self {
off: u64::MAX,
marker: PhantomData,
}
}
#[inline]
pub(crate) const unsafe fn from_off_unchecked(off: u64) -> Ptr<T, A> {
Self {
off,
marker: PhantomData,
}
}
#[inline]
#[track_caller]
pub(crate) fn as_option(&mut self) -> Option<&mut Self> {
if self.is_dangling() {
None
} else {
debug_assert!(A::allocated(self.off(), 1), "Access Violation at address 0x{:x}", self.off());
Some(self)
}
}
#[inline]
pub(crate) fn from_option<U: PSafe>(p: Option<Self>) -> Ptr<U, A> {
if let Some(p) = p {
Ptr {
off: p.off,
marker: PhantomData,
}
} else {
Ptr::<U, A>::dangling()
}
}
#[inline]
pub(crate) fn try_from<'a, U: 'a + PSafe>(off: u64) -> Option<Ptr<U, A>> {
if off == u64::MAX || !A::contains(off) {
None
} else {
unsafe { Some(Ptr::<U, A>::from_off_unchecked(off)) }
}
}
#[inline]
pub(crate) fn cast<U: PSafe>(&self) -> Ptr<U, A> {
Ptr::<U, A> {
off: self.off,
marker: PhantomData,
}
}
}
unsafe impl<A: MemPool, T: PSafe> PSafe for Ptr<[T], A> {}
impl<A: MemPool, T: PSafe + ?Sized> Copy for Ptr<T, A> {}
impl<A: MemPool, T: PSafe + ?Sized> Clone for Ptr<T, A> {
fn clone(&self) -> Self {
Self {
off: self.off,
marker: PhantomData,
}
}
}
impl<A: MemPool, T: PSafe> PmemUsage for Ptr<T, A> {
fn size_of() -> usize {
std::mem::size_of::<T>() + std::mem::size_of::<Self>()
}
}
impl<A: MemPool, T: ?Sized> Ptr<T, A> {
#[inline]
#[track_caller]
pub unsafe fn from_raw(other: *const T) -> Self {
let off = if !other.is_null() {
A::off(other).unwrap()
} else {
0
};
Self {
off,
marker: PhantomData,
}
}
#[inline]
#[track_caller]
pub(crate) fn from_ref(other: &T) -> Self {
Self {
off: A::off(other as *const T).unwrap(),
marker: PhantomData,
}
}
#[inline]
#[track_caller]
pub(crate) fn from_mut(other: &mut T) -> Self {
Self {
off: A::off(other as *const T).unwrap(),
marker: PhantomData,
}
}
#[inline]
#[track_caller]
pub(crate) fn from_non_null(other: NonNull<T>) -> Self {
Self {
off: A::off(other.as_ptr()).unwrap(),
marker: PhantomData,
}
}
}
impl<A: MemPool, T: ?Sized> PartialEq for Ptr<T, A> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.off == other.off
}
}
impl<A: MemPool, T: PSafe + ?Sized> Deref for Ptr<T, A> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.as_ref()
}
}
impl<A: MemPool, T: PSafe + ?Sized> DerefMut for Ptr<T, A> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
self.as_mut()
}
}
impl<A: MemPool, T: Debug + PSafe + ?Sized> Debug for Ptr<T, A> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.as_ref())
}
}
impl<A: MemPool, T: Display + PSafe + ?Sized> Display for Ptr<T, A> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_ref())
}
}