use std::{
fmt,
marker::PhantomData,
ops::{Deref, DerefMut},
ptr::NonNull,
};
#[cfg(feature = "types")]
use crate::types::Type;
use crate::value::{ByteVector, Pair, SmartString, ValueId, Vector};
use super::{Mutator, Root, Slot, Trace};
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Pointer<'a, T: fmt::Debug>(NonNull<Slot<T>>, PhantomData<Mutator<'a>>);
impl<'a, T: fmt::Debug> Pointer<'a, T> {
#[must_use]
pub fn new(ptr: NonNull<Slot<T>>) -> Self {
let mut ptr = Self(ptr, PhantomData);
ptr.lock();
ptr
}
#[must_use]
pub const unsafe fn new_unchecked(ptr: NonNull<Slot<T>>) -> Self {
Self(ptr, PhantomData)
}
#[must_use]
#[inline]
pub unsafe fn into_inner(self) -> NonNull<Slot<T>> {
self.0
}
#[must_use]
#[inline]
pub const unsafe fn as_inner(&self) -> NonNull<Slot<T>> {
self.0
}
#[must_use]
#[inline]
pub unsafe fn into_raw(self) -> *mut Slot<T> {
let ptr = self.0.as_ptr();
std::mem::forget(self);
ptr
}
#[must_use]
#[inline]
pub const fn as_ptr(&self) -> *const Slot<T> {
self.0.as_ptr()
}
#[inline]
fn lock(&mut self) {
let entry = unsafe { self.0.as_mut() };
entry.lock();
}
#[inline]
fn unlock(&mut self) {
let entry = unsafe { self.0.as_mut() };
entry.unlock();
}
}
impl<'a> Pointer<'a, Pair<'a>> {
#[must_use]
#[inline]
pub fn id(&self) -> ValueId {
self.into()
}
}
impl<'a> Pointer<'a, SmartString> {
#[must_use]
#[inline]
pub fn id(&self) -> ValueId {
self.into()
}
}
impl<'a> Pointer<'a, Box<str>> {
#[must_use]
#[inline]
pub fn id(&self) -> ValueId {
self.into()
}
}
impl<'a> Pointer<'a, ByteVector> {
#[must_use]
#[inline]
pub fn id(&self) -> ValueId {
self.into()
}
}
impl<'a> Pointer<'a, Vector<'a>> {
#[must_use]
#[inline]
pub fn id(&self) -> ValueId {
self.into()
}
}
impl<'a, T: fmt::Debug> Deref for Pointer<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
let entry = unsafe { self.0.as_ref() };
entry.value().expect("undefined-pointer")
}
}
impl<'a, T: fmt::Debug> DerefMut for Pointer<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
let entry = unsafe { self.0.as_mut() };
entry.value_mut().expect("undefined-pointer")
}
}
impl<'a, T: fmt::Debug> Clone for Pointer<'a, T> {
fn clone(&self) -> Self {
let mut cloned = Self(self.0, PhantomData);
cloned.lock();
cloned
}
}
impl<'a, T: fmt::Debug> Drop for Pointer<'a, T> {
fn drop(&mut self) {
self.unlock();
}
}
impl<'a, T: Trace<'a> + fmt::Debug> Trace<'a> for Pointer<'a, T> {
fn trace(&self, traced: &mut Vec<Root<'a>>) {
let value = unsafe { self.0.as_ref() };
let value = value.value().expect("undefined-pointer");
value.trace(traced);
}
}
impl<'a, T: fmt::Debug> fmt::Debug for Pointer<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let entry = unsafe { self.0.as_ref() };
f.debug_tuple("Pointer").field(entry).finish()
}
}
impl<'a, T: fmt::Debug + fmt::Display> fmt::Display for Pointer<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let entry = unsafe { self.0.as_ref() };
if let Some(value) = entry.value() {
fmt::Display::fmt(value, f)
} else {
write!(f, "<undefined>")
}
}
}
impl<'a> From<NonNull<Slot<Pair<'a>>>> for Pointer<'a, Pair<'a>> {
#[inline]
fn from(ptr: NonNull<Slot<Pair<'a>>>) -> Self {
Self::new(ptr)
}
}
impl<'a> From<NonNull<Slot<SmartString>>> for Pointer<'a, SmartString> {
#[inline]
fn from(ptr: NonNull<Slot<SmartString>>) -> Self {
Self::new(ptr)
}
}
impl<'a> From<NonNull<Slot<Box<str>>>> for Pointer<'a, Box<str>> {
#[inline]
fn from(ptr: NonNull<Slot<Box<str>>>) -> Self {
Self::new(ptr)
}
}
impl<'a> From<NonNull<Slot<ByteVector>>> for Pointer<'a, ByteVector> {
#[inline]
fn from(ptr: NonNull<Slot<ByteVector>>) -> Self {
Self::new(ptr)
}
}
impl<'a> From<NonNull<Slot<Vector<'a>>>> for Pointer<'a, Vector<'a>> {
#[inline]
fn from(ptr: NonNull<Slot<Vector<'a>>>) -> Self {
Self::new(ptr)
}
}
#[cfg(feature = "types")]
impl<'a> From<NonNull<Slot<Type>>> for Pointer<'a, Type> {
#[inline]
fn from(ptr: NonNull<Slot<Type>>) -> Self {
Self::new(ptr)
}
}