use lua_gc::{Gc, Marker, Trace};
#[derive(Debug)]
pub struct GcRef<T: Trace + 'static>(pub Gc<T>);
impl<T: Trace + 'static> GcRef<T> {
pub fn new(value: T) -> Self {
let gc = lua_gc::with_current_heap(|heap| match heap {
Some(heap) => heap.allocate(value),
None => Gc::new_uncollected(value),
});
GcRef(gc)
}
pub fn trace_obj(&self, m: &mut Marker) {
if m.try_visit(self.identity()) {
(**self).trace(m);
}
}
}
impl<T: Trace + 'static> GcRef<T> {
pub fn ptr_eq(a: &Self, b: &Self) -> bool {
Gc::ptr_eq(a.0, b.0)
}
pub fn identity(&self) -> usize {
self.0.identity()
}
pub fn strong_count(&self) -> usize {
1
}
pub fn weak_count(&self) -> usize {
0
}
pub fn downgrade(&self) -> GcWeak<T> {
GcWeak(self.0)
}
}
#[derive(Debug)]
pub struct GcWeak<T: Trace + 'static>(pub Gc<T>);
impl<T: Trace + 'static> GcWeak<T> {
pub fn upgrade(&self) -> Option<GcRef<T>> {
Some(GcRef(self.0))
}
pub fn strong_count(&self) -> usize {
1
}
}
impl<T: Trace + 'static> Clone for GcWeak<T> {
fn clone(&self) -> Self {
GcWeak(self.0)
}
}
impl<T: Trace + 'static> Clone for GcRef<T> {
fn clone(&self) -> Self {
GcRef(self.0)
}
}
impl<T: Trace + 'static> Copy for GcRef<T> {}
impl<T: Trace + 'static> std::ops::Deref for GcRef<T> {
type Target = T;
fn deref(&self) -> &T {
&*self.0
}
}
impl<T: Trace + 'static> AsRef<T> for GcRef<T> {
fn as_ref(&self) -> &T {
&*self.0
}
}
impl<T: PartialEq + Trace + 'static> PartialEq for GcRef<T> {
fn eq(&self, other: &Self) -> bool {
Gc::ptr_eq(self.0, other.0) || **self == **other
}
}