Don't use boxed cell slice, use a refcell instead

This commit is contained in:
Jonathan Kelley committed 2023-07-19 12:08:13 -07:00
1 parent f69b84bf34
commit 2871c8bb4d
7 files changed
+24 -119

No files matched your search

+3 -102
View File
@@ -5,7 +5,7 @@ use bumpalo::boxed::Box as BumpBox;
use bumpalo::Bump;
use std::{
any::{Any, TypeId},
cell::{Cell, RefCell, UnsafeCell},
cell::{Cell, RefCell},
fmt::{Arguments, Debug},
};
@@ -54,7 +54,7 @@ pub struct VNode<'a> {
/// The IDs for the roots of this template - to be used when moving the template around and removing it from
/// the actual Dom
pub root_ids: BoxedCellSlice,
pub root_ids: RefCell<Vec<ElementId>>,
/// The dynamic parts of the template
pub dynamic_nodes: &'a [DynamicNode<'a>],
@@ -63,112 +63,13 @@ pub struct VNode<'a> {
pub dynamic_attrs: &'a [Attribute<'a>],
}
// Saftey: There is no way to get references to the internal data of this struct so no refrences will be invalidated by mutating the data with a immutable reference (The same principle behind Cell)
#[derive(Debug, Default)]
pub struct BoxedCellSlice(UnsafeCell<Option<Box<[ElementId]>>>);
impl Clone for BoxedCellSlice {
fn clone(&self) -> Self {
Self(UnsafeCell::new(unsafe { (*self.0.get()).clone() }))
}
}
impl BoxedCellSlice {
pub fn last(&self) -> Option<ElementId> {
unsafe {
(*self.0.get())
.as_ref()
.and_then(|inner| inner.as_ref().last().copied())
}
}
pub fn get(&self, idx: usize) -> Option<ElementId> {
unsafe {
(*self.0.get())
.as_ref()
.and_then(|inner| inner.as_ref().get(idx).copied())
}
}
pub unsafe fn get_unchecked(&self, idx: usize) -> Option<ElementId> {
(*self.0.get())
.as_ref()
.and_then(|inner| inner.as_ref().get(idx).copied())
}
pub fn set(&self, idx: usize, new: ElementId) {
unsafe {
if let Some(inner) = &mut *self.0.get() {
inner[idx] = new;
}
}
}
pub fn intialize(&self, contents: Box<[ElementId]>) {
unsafe {
*self.0.get() = Some(contents);
}
}
pub fn transfer(&self, other: &Self) {
unsafe {
*self.0.get() = (*other.0.get()).clone();
}
}
pub fn take_from(&self, other: &Self) {
unsafe {
*self.0.get() = (*other.0.get()).take();
}
}
pub fn len(&self) -> usize {
unsafe {
(*self.0.get())
.as_ref()
.map(|inner| inner.len())
.unwrap_or(0)
}
}
}
impl<'a> IntoIterator for &'a BoxedCellSlice {
type Item = ElementId;
type IntoIter = BoxedCellSliceIter<'a>;
fn into_iter(self) -> Self::IntoIter {
BoxedCellSliceIter {
index: 0,
borrow: self,
}
}
}
pub struct BoxedCellSliceIter<'a> {
index: usize,
borrow: &'a BoxedCellSlice,
}
impl Iterator for BoxedCellSliceIter<'_> {
type Item = ElementId;
fn next(&mut self) -> Option<Self::Item> {
let result = self.borrow.get(self.index);
if result.is_some() {
self.index += 1;
}
result
}
}
impl<'a> VNode<'a> {
/// Create a template with no nodes that will be skipped over during diffing
pub fn empty() -> Element<'a> {
Some(VNode {
key: None,
parent: None,
root_ids: BoxedCellSlice::default(),
root_ids: Default::default(),
dynamic_nodes: &[],
dynamic_attrs: &[],
template: Cell::new(Template {