use std::{marker::PhantomData, ptr::NonNull};
use crate::{gc_box::GcBox, Collect, Gc, Invariant};
pub struct Weak<'b, T: ?Sized>(NonNull<()>, Invariant<'b>, PhantomData<*const T>);
impl<T: ?Sized> Default for Weak<'_, T> {
fn default() -> Self {
Weak(
NonNull::new(core::ptr::without_provenance_mut(usize::MAX)).unwrap(),
Invariant,
PhantomData,
)
}
}
impl<'b, T: ?Sized> Weak<'b, T> {
pub fn new() -> Weak<'b, T> {
Weak::default()
}
pub(crate) fn as_box(&self) -> Option<GcBox<T>> {
if self.0.addr().get() == usize::MAX {
None
} else {
Some(unsafe { GcBox::from_raw(self.0) })
}
}
pub(crate) unsafe fn from_box(ptr: GcBox<T>) -> Weak<'b, T> {
Weak(ptr.into_raw(), Invariant, PhantomData)
}
pub fn upgrade(self) -> Option<Gc<'b, T>> {
if let Some(b) = self.as_box() {
if b.is_initialized() {
Some(unsafe { Gc::from_box(b) })
} else {
None
}
} else {
None
}
}
}
unsafe impl<T: ?Sized> Collect for Weak<'_, T> {
const NEEDS_TRACE: bool = true;
fn trace(&self, _c: &crate::Collector) {
use crate::gc_box::Colour;
if let Some(gc) = self.as_box() {
unsafe { gc.set_colour(Colour::Weak) };
}
}
}