use crate::node::State::{Trace, Unknown};
use crate::node::{NodeHead, NodeTrait};
use crate::root_ref::RootRef;
use crate::target::RefSet;
use std::cell::{Cell, RefCell};
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
use std::ptr::NonNull;
pub struct StrongVec<'gc, T: ?Sized + NodeTrait<'gc> + 'gc> {
_marker: PhantomData<*mut &'gc ()>,
vec: RefCell<Vec<Cell<NonNull<T>>>>,
}
impl<'gc, T: ?Sized + NodeTrait<'gc> + 'gc> StrongVec<'gc, T> {
#[inline(always)]
pub fn get(&self, index: usize) -> Result<RootRef<'gc, T>, ()> {
self.vec
.borrow()
.get(index)
.map(|i| RootRef::new(unsafe { i.get().as_ref() }))
.ok_or(())
}
#[inline(always)]
pub fn set(&self, index: usize, r: &T) -> Result<(), ()> {
self.vec
.borrow()
.get(index)
.map(|i| i.set(NonNull::from(r)))
.ok_or(())
}
#[inline(always)]
pub fn push(&self, r: &T) {
self.vec.borrow_mut().push(Cell::new(NonNull::from(r)));
}
pub fn extend<'s, I: IntoIterator<Item = &'s T>>(&self, i: I)
where
'gc: 's,
{
self.vec
.borrow_mut()
.extend(i.into_iter().map(|i| Cell::new(NonNull::from(i))))
}
pub fn get_all<B: FromIterator<RootRef<'gc, T>>>(&self) -> B {
self.vec
.borrow()
.iter()
.map(|i| RootRef::new(unsafe { i.get().as_ref() }))
.collect()
}
}
impl<'gc, T: ?Sized + NodeTrait<'gc>> Debug for StrongVec<'gc, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut s = f.debug_list();
s.entries(self.vec.borrow().iter().map(|i| i.get()));
s.finish()
}
}
unsafe impl<'gc, T: ?Sized + NodeTrait<'gc>> RefSet<'gc> for StrongVec<'gc, T> {
#[inline(always)]
unsafe fn build() -> Self {
Self {
_marker: PhantomData,
vec: Default::default(),
}
}
#[inline(always)]
unsafe fn collect(&self, stack: &mut Vec<&dyn NodeTrait<'gc>>) {
for i in self.vec.borrow().iter() {
let r = i.get().as_ref();
if NodeHead::from_node_trait(r).get_marker() == Unknown {
NodeHead::from_node_trait(r).set_marker(Trace);
stack.push(r.as_dyn_node());
}
}
}
}