use std::{ any::Any, cell::{Cell, RefCell, UnsafeCell}, }; pub struct HookList { vals: RefCell>>>, idx: Cell, } impl Default for HookList { fn default() -> Self { Self { vals: Default::default(), idx: Cell::new(0), } } } struct InnerHook { cell: UnsafeCell, } impl InnerHook { fn new(new: T) -> Self { Self { cell: UnsafeCell::new(new), } } } impl HookList { pub(crate) fn next(&self) -> Option<&mut T> { self.vals.borrow().get(self.idx.get()).and_then(|inn| { self.idx.set(self.idx.get() + 1); let raw_box = unsafe { &mut *inn.cell.get() }; raw_box.downcast_mut::() }) } pub(crate) fn push(&self, new: T) { self.vals.borrow_mut().push(InnerHook::new(Box::new(new))) } /// This resets the internal iterator count /// It's okay that we've given out each hook, but now we have the opportunity to give it out again /// Therefore, resetting is cosudered unsafe /// /// This should only be ran by Dioxus itself before "running scope". /// Dioxus knows how to descened through the tree to prevent mutable aliasing. pub(crate) unsafe fn reset(&mut self) { self.idx.set(0); } #[inline] pub(crate) fn len(&self) -> usize { self.vals.borrow().len() } #[inline] pub(crate) fn cur_idx(&self) -> usize { self.idx.get() } #[inline] pub(crate) fn at_end(&self) -> bool { self.cur_idx() >= self.len() } }