1use std::{
2 collections::HashMap,
3 fmt::{self},
4 marker::PhantomData,
5 ops::{Deref, DerefMut},
6 ptr::NonNull,
7};
8
9use crate::{header::HeapObjectHeader, internal::{finalize_trait::FinalizeTrait, gc_info::{GCInfoIndex, GCInfoTrait}, trace_trait::TraceTrait}};
10#[repr(C)]
18pub struct GcRef<T> {
19 pub(crate) raw: UntypedGcRef,
20 pub(crate) marker: PhantomData<T>,
21}
22
23impl<T> GcRef<T> {
24 pub fn into_raw(self) -> *const HeapObjectHeader {
25 self.raw.header.as_ptr()
26 }
27 pub fn downcast(self) -> UntypedGcRef {
28 self.raw
29 }
30}
31
32impl<T> Deref for GcRef<T> {
33 type Target = T;
34 fn deref(&self) -> &Self::Target {
35 unsafe { &*self.raw.get().cast::<T>() }
36 }
37}
38impl<T> DerefMut for GcRef<T> {
39 fn deref_mut(&mut self) -> &mut Self::Target {
40 unsafe { &mut *self.raw.get().cast::<T>() }
41 }
42}
43
44#[derive(Clone, Copy)]
52#[repr(C)]
53pub struct UntypedGcRef {
54 pub(crate) header: NonNull<HeapObjectHeader>,
55}
56
57impl UntypedGcRef {
58 pub fn get(&self) -> *mut u8 {
60 unsafe { (*self.header.as_ptr()).payload() as _ }
61 }
62 pub fn is(&self,index: GCInfoIndex) -> bool {
64 unsafe {
65 let header = &*self.header.as_ptr();
66 header.get_gc_info_index() == index
67 }
68 }
69 pub fn cast<T: GCInfoTrait<T> + TraceTrait + FinalizeTrait<T> + 'static>(
71 self,
72 ) -> Option<GcRef<T>> {
73 unsafe {
74 let header = &*self.header.as_ptr();
75 if header.get_gc_info_index() == T::index() {
76 return Some(GcRef {
77 raw: self,
78 marker: PhantomData,
79 });
80 } else {
81 None
82 }
83 }
84 }
85 pub unsafe fn cast_unchecked<T: GCInfoTrait<T> + TraceTrait + FinalizeTrait<T> + 'static>(
87 self,
88 ) -> GcRef<T> {
89 self.cast::<T>()
90 .unwrap_or_else(|| unsafe { core::hint::unreachable_unchecked() })
91 }
92}
93
94impl fmt::Debug for UntypedGcRef {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 write!(f, "UntypedGcRef({:p})", self.header)
97 }
98}
99impl fmt::Pointer for UntypedGcRef {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 write!(f, "UntypedGcRef({:p})", self.header)
102 }
103}
104impl<T> std::fmt::Pointer for GcRef<T> {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 write!(f, "{:p}", self.raw)
107 }
108}
109
110impl<T: std::fmt::Debug> std::fmt::Debug for GcRef<T> {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 write!(f, "{:?}", **self)
113 }
114}
115impl<T: std::fmt::Display> std::fmt::Display for GcRef<T> {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 write!(f, "{}", **self)
118 }
119}
120pub struct WeakSlot {
121 pub(crate) value: Option<UntypedGcRef>,
122}
123
124impl FinalizeTrait<WeakSlot> for WeakSlot {}
125impl TraceTrait for WeakSlot {}
126
127
128#[repr(transparent)]
130#[derive(Clone, Copy)]
131pub struct WeakGcRef {
132 pub(crate) slot: GcRef<WeakSlot>,
133}
134
135impl WeakGcRef {
136 pub fn upgrade(&self) -> Option<UntypedGcRef> {
137 self.slot.value
138 }
139
140 pub fn slot(self) -> GcRef<WeakSlot> {
141 self.slot
142 }
143}
144impl<T> Copy for GcRef<T> {}
145
146impl<T> Clone for GcRef<T> {
147 fn clone(&self) -> Self {
148 *self
149 }
150}
151
152impl<T: TraceTrait> TraceTrait for GcRef<T> {
153 fn trace(&self, vis: &mut crate::visitor::Visitor) {
154 vis.trace_gcref(*self);
155 }
156}
157
158impl TraceTrait for UntypedGcRef {
159 fn trace(&self, vis: &mut crate::visitor::Visitor) {
160 vis.trace_untyped(*self);
161 }
162}
163
164macro_rules! impl_prim {
165 ($($t:ty)*) => {
166 $(
167 impl FinalizeTrait<$t> for $t {
168
169 }
170 impl TraceTrait for $t {}
171 )*
172 };
173}
174
175impl_prim! (
176 bool f32 f64
177 u8 u16 u32 u64 u128 usize
178 i8 i16 i32 i64 i128 isize
179 String std::fs::File
180 std::path::PathBuf
181);
182
183impl<T> FinalizeTrait<Vec<T>> for Vec<T> {}
184impl<T: TraceTrait> TraceTrait for Vec<T> {
185 fn trace(&self, vis: &mut crate::visitor::Visitor) {
186 for elem in self.iter() {
187 vis.trace_ref(elem);
188 }
189 }
190}
191
192impl<K, V> FinalizeTrait<HashMap<K, V>> for HashMap<K, V> {}
193impl<K: TraceTrait, V: TraceTrait> TraceTrait for HashMap<K, V> {
194 fn trace(&self, vis: &mut crate::visitor::Visitor) {
195 for (k, v) in self.iter() {
196 k.trace(vis);
197 v.trace(vis);
198 }
199 }
200}
201
202impl<T> FinalizeTrait<Option<T>> for Option<T> {}
203
204impl<T: TraceTrait> TraceTrait for Option<T> {
205 fn trace(&self, vis: &mut crate::visitor::Visitor) {
206 match self {
207 Some(elem) => vis.trace_ref(elem),
208 _ => (),
209 }
210 }
211}
212
213impl<T, E> FinalizeTrait<Result<T, E>> for Result<T, E> {}
214impl<T: TraceTrait, E: TraceTrait> TraceTrait for Result<T, E> {
215 fn trace(&self, vis: &mut crate::visitor::Visitor) {
216 match self {
217 Ok(x) => x.trace(vis),
218 Err(x) => x.trace(vis),
219 }
220 }
221}
222
223impl PartialEq for UntypedGcRef {
224 fn eq(&self, other: &Self) -> bool {
225 self.header == other.header
226 }
227}
228
229impl Eq for UntypedGcRef {}
230
231impl<T> PartialEq for GcRef<T> {
232 fn eq(&self, other: &Self) -> bool {
233 self.raw == other.raw
234 }
235}
236
237impl<T> Eq for GcRef<T> {}