1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253 |
- use std::{
- any::Any,
- cell::{Cell, RefCell, UnsafeCell},
- };
- /// An abstraction over internally stored data using a hook-based memory layout.
- ///
- /// Hooks are allocated using Boxes and then our stored references are given out.
- ///
- /// It's unsafe to "reset" the hooklist, but it is safe to add hooks into it.
- ///
- /// Todo: this could use its very own bump arena, but that might be a tad overkill
- #[derive(Default)]
- pub(crate) struct HookList {
- vals: RefCell<Vec<UnsafeCell<Box<dyn Any>>>>,
- idx: Cell<usize>,
- }
- impl HookList {
- pub(crate) fn next<T: 'static>(&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.get() };
- raw_box.downcast_mut::<T>()
- })
- }
- /// 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);
- }
- pub(crate) fn push<T: 'static>(&self, new: T) {
- self.vals.borrow_mut().push(UnsafeCell::new(Box::new(new)))
- }
- pub(crate) fn len(&self) -> usize {
- self.vals.borrow().len()
- }
- pub(crate) fn cur_idx(&self) -> usize {
- self.idx.get()
- }
- pub(crate) fn at_end(&self) -> bool {
- self.cur_idx() >= self.len()
- }
- }
|