elise 0.1.1

A concurrent GC.
Documentation
use std::ops::Deref;
use std::pin::Pin;

use gc::{GcPtr, Root, Trace};

use crate::root::Reroot;
use crate::Gc;

pub struct HeapRoot<T: ?Sized> {
    #[allow(dead_code)]
    root: Pin<Box<Root>>,
    ptr: GcPtr<T>,
}

impl<'root, T> HeapRoot<T>
where
    T: Reroot<'root> + Trace,
    T::Rerooted: Trace,
{
    pub fn new(data: T) -> HeapRoot<T::Rerooted> {
        unsafe { HeapRoot::make(gc::alloc(data)) }
    }
}

impl<'root, T> HeapRoot<T>
where
    T: Reroot<'root> + ?Sized,
    T::Rerooted: Trace,
{
    pub fn reroot(gc: Gc<'_, T>) -> HeapRoot<T::Rerooted> {
        unsafe { HeapRoot::make(Gc::raw(gc)) }
    }
}

impl<'root, T> HeapRoot<T>
where
    T: Reroot<'root> + ?Sized,
    T::Rerooted: Trace,
{
    unsafe fn make(ptr: GcPtr<T>) -> HeapRoot<T::Rerooted> {
        let ptr = super::reroot(ptr);
        let root = Pin::from(Box::new(Root::new()));
        Pin::get_ref(Pin::as_ref(&root)).enroot(ptr);
        HeapRoot { root, ptr }
    }
}

impl<T: ?Sized> HeapRoot<T> {
    pub fn gc<'root>(&'root self) -> Gc<'root, T> {
        unsafe { Gc::rooted(self.ptr) }
    }
}

impl<T: Trace + ?Sized> Clone for HeapRoot<T> {
    fn clone(&self) -> HeapRoot<T> {
        let root = Pin::from(Box::new(Root::new()));
        unsafe { Pin::get_ref(Pin::as_ref(&root)).enroot(self.ptr) };
        HeapRoot {
            root,
            ptr: self.ptr,
        }
    }
}

impl<T: ?Sized> Deref for HeapRoot<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe { self.ptr.data() }
    }
}