use std::marker::{PhantomData, PhantomPinned};
use gc::{GcPtr, Trace};
use crate::Gc;
pub struct GcStore<'root, T: ?Sized + 'root> {
ptr: GcPtr<T>,
_marker: PhantomData<(&'root T, PhantomPinned)>,
}
impl<'root, T: Trace> GcStore<'root, T> {
pub fn new(data: T) -> GcStore<'root, T> {
GcStore {
ptr: gc::alloc_unmanaged(data),
_marker: PhantomData,
}
}
}
impl<'root, T: ?Sized> GcStore<'root, T> {
pub fn get(&self) -> &T {
unsafe {
if self.ptr.is_unmanaged() {
self.ptr.data()
} else {
panic!("Cannot call `GcStore::get` after the GcStore has been rooted.")
}
}
}
pub fn get_mut(&mut self) -> &mut T {
panic!()
}
pub fn get_maybe(&self) -> Option<&T> {
unsafe {
if self.ptr.is_unmanaged() {
Some(self.ptr.data())
} else {
None
}
}
}
pub fn get_mut_maybe(&mut self) -> Option<&mut T> {
panic!()
}
pub fn raw(this: &GcStore<'root, T>) -> GcPtr<T> {
this.ptr
}
}
unsafe impl<'root, T: Trace + ?Sized> Trace for GcStore<'root, T> {
unsafe fn mark(&self) {
self.ptr.mark();
}
unsafe fn manage(&self) {
self.ptr.manage();
}
unsafe fn finalize(&mut self) {}
}
impl<'root, T: ?Sized + Trace> From<Gc<'root, T>> for GcStore<'root, T> {
fn from(gc: Gc<'root, T>) -> GcStore<'root, T> {
GcStore {
ptr: Gc::raw(gc),
_marker: PhantomData,
}
}
}
impl<'root, T: ?Sized> Drop for GcStore<'root, T> {
fn drop(&mut self) {
unsafe {
if self.ptr.is_unmanaged() {
self.ptr.deallocate()
}
}
}
}