1use std::{marker::PhantomData, ptr::NonNull};
2
3use crate::{gc_box::GcBox, Collect, Gc, Invariant};
4
5pub struct Weak<'b, T: ?Sized>(NonNull<()>, Invariant<'b>, PhantomData<*const T>);
6
7impl<T: ?Sized> Default for Weak<'_, T> {
8 fn default() -> Self {
9 Weak(
10 NonNull::new(core::ptr::without_provenance_mut(usize::MAX)).unwrap(),
11 Invariant,
12 PhantomData,
13 )
14 }
15}
16
17impl<'b, T: ?Sized> Weak<'b, T> {
18 pub fn new() -> Weak<'b, T> {
19 Weak::default()
20 }
21
22 pub(crate) fn as_box(&self) -> Option<GcBox<T>> {
23 if self.0.addr().get() == usize::MAX {
24 None
25 } else {
26 Some(unsafe { GcBox::from_raw(self.0) })
29 }
30 }
31
32 pub(crate) unsafe fn from_box(ptr: GcBox<T>) -> Weak<'b, T> {
33 Weak(ptr.into_raw(), Invariant, PhantomData)
34 }
35
36 pub fn upgrade(self) -> Option<Gc<'b, T>> {
37 if let Some(b) = self.as_box() {
38 if b.is_initialized() {
39 Some(unsafe { Gc::from_box(b) })
40 } else {
41 None
42 }
43 } else {
44 None
45 }
46 }
47}
48
49unsafe impl<T: ?Sized> Collect for Weak<'_, T> {
50 const NEEDS_TRACE: bool = true;
51
52 fn trace(&self, _c: &crate::Collector) {
53 use crate::gc_box::Colour;
54
55 if let Some(gc) = self.as_box() {
56 unsafe { gc.set_colour(Colour::Weak) };
57 }
58 }
59}