hooklist.rs 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. use std::{
  2. any::Any,
  3. cell::{Cell, RefCell, UnsafeCell},
  4. };
  5. /// An abstraction over internally stored data using a hook-based memory layout.
  6. ///
  7. /// Hooks are allocated using Boxes and then our stored references are given out.
  8. ///
  9. /// It's unsafe to "reset" the hooklist, but it is safe to add hooks into it.
  10. ///
  11. /// Todo: this could use its very own bump arena, but that might be a tad overkill
  12. #[derive(Default)]
  13. pub(crate) struct HookList {
  14. vals: RefCell<Vec<UnsafeCell<Box<dyn Any>>>>,
  15. idx: Cell<usize>,
  16. }
  17. impl HookList {
  18. pub(crate) fn next<T: 'static>(&self) -> Option<&mut T> {
  19. self.vals.borrow().get(self.idx.get()).and_then(|inn| {
  20. self.idx.set(self.idx.get() + 1);
  21. let raw_box = unsafe { &mut *inn.get() };
  22. raw_box.downcast_mut::<T>()
  23. })
  24. }
  25. /// This resets the internal iterator count
  26. /// It's okay that we've given out each hook, but now we have the opportunity to give it out again
  27. /// Therefore, resetting is cosudered unsafe
  28. ///
  29. /// This should only be ran by Dioxus itself before "running scope".
  30. /// Dioxus knows how to descened through the tree to prevent mutable aliasing.
  31. pub(crate) unsafe fn reset(&mut self) {
  32. self.idx.set(0);
  33. }
  34. pub(crate) fn push<T: 'static>(&self, new: T) {
  35. self.vals.borrow_mut().push(UnsafeCell::new(Box::new(new)))
  36. }
  37. pub(crate) fn len(&self) -> usize {
  38. self.vals.borrow().len()
  39. }
  40. pub(crate) fn cur_idx(&self) -> usize {
  41. self.idx.get()
  42. }
  43. pub(crate) fn at_end(&self) -> bool {
  44. self.cur_idx() >= self.len()
  45. }
  46. }