runmat_gc_api/
lib.rs

1#![forbid(unsafe_op_in_unsafe_fn)]
2
3use std::fmt;
4use std::hash::{Hash, Hasher};
5use std::marker::PhantomData;
6use std::ops::{Deref, DerefMut};
7
8#[derive(Copy, Clone)]
9pub struct GcPtr<T> {
10    ptr: *const T,
11    _phantom: PhantomData<T>,
12}
13
14impl<T> GcPtr<T> {
15    /// # Safety
16    ///
17    /// - `ptr` must be non-null and correctly aligned for `T`.
18    /// - `ptr` must point to a valid instance of `T` allocated by RunMat's GC and
19    ///   remain alive for the duration of all uses of the returned `GcPtr`.
20    /// - The caller is responsible for upholding aliasing and lifetime invariants
21    ///   when this pointer is dereferenced via `Deref`/`DerefMut`.
22    pub unsafe fn from_raw(ptr: *const T) -> Self {
23        Self {
24            ptr,
25            _phantom: PhantomData,
26        }
27    }
28    pub fn null() -> Self {
29        Self {
30            ptr: std::ptr::null(),
31            _phantom: PhantomData,
32        }
33    }
34    pub fn is_null(&self) -> bool {
35        self.ptr.is_null()
36    }
37    /// # Safety
38    ///
39    /// The returned raw pointer may become invalid if the underlying object is
40    /// collected by the GC. The caller must ensure the object is kept alive
41    /// (e.g., via rooting) for any dereference, and must respect aliasing and
42    /// lifetime rules when using the pointer.
43    pub unsafe fn as_raw(&self) -> *const T {
44        self.ptr
45    }
46    /// # Safety
47    ///
48    /// Returns a mutable raw pointer to the underlying object. The caller must
49    /// ensure exclusive access when mutating through this pointer, that the
50    /// object outlives all uses, and that aliasing/lifetime invariants are
51    /// respected. Mutating a collected or shared object is undefined behavior.
52    pub unsafe fn as_raw_mut(&self) -> *mut T {
53        self.ptr as *mut T
54    }
55}
56
57impl<T> Deref for GcPtr<T> {
58    type Target = T;
59    fn deref(&self) -> &Self::Target {
60        unsafe { &*self.ptr }
61    }
62}
63impl<T> DerefMut for GcPtr<T> {
64    fn deref_mut(&mut self) -> &mut Self::Target {
65        unsafe { &mut *(self.ptr as *mut T) }
66    }
67}
68
69impl<T: PartialEq> PartialEq for GcPtr<T> {
70    fn eq(&self, other: &Self) -> bool {
71        if self.is_null() && other.is_null() {
72            true
73        } else if self.is_null() || other.is_null() {
74            false
75        } else {
76            **self == **other
77        }
78    }
79}
80impl<T: Eq> Eq for GcPtr<T> {}
81impl<T: Hash> Hash for GcPtr<T> {
82    fn hash<H: Hasher>(&self, state: &mut H) {
83        if !self.is_null() {
84            (**self).hash(state)
85        }
86    }
87}
88impl<T: fmt::Debug> fmt::Debug for GcPtr<T> {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        if self.is_null() {
91            write!(f, "GcPtr(null)")
92        } else {
93            write!(f, "GcPtr({:?})", **self)
94        }
95    }
96}
97impl<T: fmt::Display> fmt::Display for GcPtr<T> {
98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99        if self.is_null() {
100            write!(f, "null")
101        } else {
102            write!(f, "{}", **self)
103        }
104    }
105}
106
107unsafe impl<T: Send> Send for GcPtr<T> {}
108unsafe impl<T: Sync> Sync for GcPtr<T> {}