intial update to new mutations

This commit is contained in:
Evan Almloff 2022-11-24 15:05:15 -06:00
parent 078b8ba833
commit dcad2fe8a2
6 changed files with 442 additions and 757 deletions

View file

@ -5,8 +5,6 @@ pub mod node;
pub mod node_ref;
pub mod real_dom;
pub mod state;
#[doc(hidden)]
pub mod traversable;
pub mod tree;
pub mod utils;

View file

@ -1,4 +1,4 @@
use crate::{state::State, tree::NodeId, RealNodeId};
use crate::{state::State, tree::NodeId};
use dioxus_core::ElementId;
use rustc_hash::{FxHashMap, FxHashSet};
@ -13,12 +13,15 @@ pub struct Node<S: State> {
#[derive(Debug, Clone)]
pub struct NodeData {
/// The id of the node
pub node_id: NodeId,
/// The id of the node in the vdom.
pub element_id: Option<ElementId>,
/// Additional inforation specific to the node type
pub node_type: NodeType,
/// The number of parents before the root node. The root node has height 1.
pub height: u16,
height_dirty: bool,
}
/// A type of node with data specific to the node type. The types are a subset of the [VNode] types.
@ -29,7 +32,7 @@ pub enum NodeType {
},
Element {
tag: String,
namespace: Option<&'static str>,
namespace: Option<String>,
attributes: FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue>,
listeners: FxHashSet<String>,
},
@ -44,29 +47,12 @@ impl<S: State> Node<S> {
element_id: None,
node_type,
height: 0,
node_id: NodeId(0),
height_dirty: true,
},
}
}
/// link a child node
fn add_child(&mut self, child: RealNodeId) {
if let NodeType::Element { children, .. } = &mut self.node_data.node_type {
children.push(child);
}
}
/// remove a child node
fn remove_child(&mut self, child: RealNodeId) {
if let NodeType::Element { children, .. } = &mut self.node_data.node_type {
children.retain(|c| c != &child);
}
}
/// link the parent node
fn set_parent(&mut self, parent: RealNodeId) {
self.node_data.parent = Some(parent);
}
/// get the mounted id of the node
pub fn mounted_id(&self) -> Option<ElementId> {
self.node_data.element_id

View file

@ -42,7 +42,7 @@ impl<'a> NodeView<'a> {
self.mask
.namespace
.then_some(match &self.inner.node_type {
NodeType::Element { namespace, .. } => *namespace,
NodeType::Element { namespace, .. } => namespace.as_deref(),
_ => None,
})
.flatten()
@ -93,7 +93,7 @@ impl<'a> NodeView<'a> {
pub enum AttributeMask {
All,
/// A list of attribute names that are visible, this list must be sorted
Dynamic(Vec<&'static str>),
Dynamic(Vec<String>),
/// A list of attribute names that are visible, this list must be sorted
Static(&'static [&'static str]),
}
@ -105,14 +105,14 @@ impl AttributeMask {
fn contains_attribute(&self, attr: &str) -> bool {
match self {
AttributeMask::All => true,
AttributeMask::Dynamic(l) => l.binary_search(&attr).is_ok(),
AttributeMask::Dynamic(l) => l.binary_search_by_key(&attr, |s| s.as_str()).is_ok(),
AttributeMask::Static(l) => l.binary_search(&attr).is_ok(),
}
}
/// Create a new dynamic attribute mask with a single attribute
pub fn single(new: &'static str) -> Self {
Self::Dynamic(vec![new])
pub fn single(new: &str) -> Self {
Self::Dynamic(vec![new.to_string()])
}
/// Ensure the attribute list is sorted.
@ -133,15 +133,27 @@ impl AttributeMask {
/// Combine two attribute masks
pub fn union(&self, other: &Self) -> Self {
let new = match (self, other) {
(AttributeMask::Dynamic(s), AttributeMask::Dynamic(o)) => AttributeMask::Dynamic(
union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
),
(AttributeMask::Static(s), AttributeMask::Dynamic(o)) => AttributeMask::Dynamic(
union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
),
(AttributeMask::Dynamic(s), AttributeMask::Static(o)) => AttributeMask::Dynamic(
union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
),
(AttributeMask::Dynamic(s), AttributeMask::Dynamic(o)) => {
AttributeMask::Dynamic(union_ordered_iter(
s.iter().map(|s| s.as_str()),
o.iter().map(|s| s.as_str()),
s.len() + o.len(),
))
}
(AttributeMask::Static(s), AttributeMask::Dynamic(o)) => {
AttributeMask::Dynamic(union_ordered_iter(
s.iter().copied(),
o.iter().map(|s| s.as_str()),
s.len() + o.len(),
))
}
(AttributeMask::Dynamic(s), AttributeMask::Static(o)) => {
AttributeMask::Dynamic(union_ordered_iter(
s.iter().map(|s| s.as_str()),
o.iter().copied(),
s.len() + o.len(),
))
}
(AttributeMask::Static(s), AttributeMask::Static(o)) => AttributeMask::Dynamic(
union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
),
@ -153,9 +165,9 @@ impl AttributeMask {
/// Check if two attribute masks overlap
fn overlaps(&self, other: &Self) -> bool {
fn overlaps_iter(
self_iter: impl Iterator<Item = &'static str>,
mut other_iter: impl Iterator<Item = &'static str>,
fn overlaps_iter<'a>(
self_iter: impl Iterator<Item = &'a str>,
mut other_iter: impl Iterator<Item = &'a str>,
) -> bool {
if let Some(mut other_attr) = other_iter.next() {
for self_attr in self_iter {
@ -180,13 +192,13 @@ impl AttributeMask {
(AttributeMask::Dynamic(v), AttributeMask::All) => !v.is_empty(),
(AttributeMask::Static(s), AttributeMask::All) => !s.is_empty(),
(AttributeMask::Dynamic(v1), AttributeMask::Dynamic(v2)) => {
overlaps_iter(v1.iter().copied(), v2.iter().copied())
overlaps_iter(v1.iter().map(|s| s.as_str()), v2.iter().map(|s| s.as_str()))
}
(AttributeMask::Dynamic(v), AttributeMask::Static(s)) => {
overlaps_iter(v.iter().copied(), s.iter().copied())
overlaps_iter(v.iter().map(|s| s.as_str()), s.iter().copied())
}
(AttributeMask::Static(s), AttributeMask::Dynamic(v)) => {
overlaps_iter(v.iter().copied(), s.iter().copied())
overlaps_iter(v.iter().map(|s| s.as_str()), s.iter().copied())
}
(AttributeMask::Static(s1), AttributeMask::Static(s2)) => {
overlaps_iter(s1.iter().copied(), s2.iter().copied())

File diff suppressed because it is too large Load diff

View file

@ -1,17 +1,18 @@
use std::{cmp::Ordering, fmt::Debug};
use std::cmp::Ordering;
use crate::node::NodeData;
use crate::node_ref::{NodeMask, NodeView};
use crate::tree::TreeView;
use crate::RealNodeId;
use anymap::AnyMap;
use rustc_hash::FxHashSet;
/// Join two sorted iterators
pub(crate) fn union_ordered_iter<T: Ord + Debug>(
s_iter: impl Iterator<Item = T>,
o_iter: impl Iterator<Item = T>,
pub(crate) fn union_ordered_iter<'a>(
s_iter: impl Iterator<Item = &'a str>,
o_iter: impl Iterator<Item = &'a str>,
new_len_guess: usize,
) -> Vec<T> {
) -> Vec<String> {
let mut s_peekable = s_iter.peekable();
let mut o_peekable = o_iter.peekable();
let mut v = Vec::with_capacity(new_len_guess);
@ -22,7 +23,7 @@ pub(crate) fn union_ordered_iter<T: Ord + Debug>(
break;
}
Ordering::Less => {
v.push(o_peekable.next().unwrap());
v.push(o_peekable.next().unwrap().to_string());
}
Ordering::Equal => {
o_peekable.next();
@ -30,10 +31,10 @@ pub(crate) fn union_ordered_iter<T: Ord + Debug>(
}
}
}
v.push(s_peekable.next().unwrap());
v.push(s_peekable.next().unwrap().to_string());
}
for o_i in o_peekable {
v.push(o_i);
v.push(o_i.to_string());
}
for w in v.windows(2) {
debug_assert!(w[1] > w[0]);
@ -207,11 +208,7 @@ pub trait NodeDepState<DepState = ()> {
/// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
pub trait State: Default + Clone {
#[doc(hidden)]
fn update<
'a,
T: Traversable<Node = Self, Id = RealNodeId>,
T2: Traversable<Node = NodeData, Id = RealNodeId>,
>(
fn update<'a, T: TreeView<Self>, T2: TreeView<NodeData>>(
dirty: &[(RealNodeId, NodeMask)],
state_tree: &'a mut T,
rdom: &'a T2,

View file

@ -7,7 +7,7 @@ use std::collections::VecDeque;
use std::marker::PhantomData;
use std::sync::Arc;
#[derive(PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord)]
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord)]
pub struct NodeId(pub usize);
#[derive(PartialEq, Eq, Clone, Debug)]
@ -23,6 +23,31 @@ pub struct Tree<T> {
root: NodeId,
}
impl<T> Tree<T> {
fn try_remove(&mut self, id: NodeId) -> Option<Node<T>> {
self.nodes.try_remove(id.0).map(|node| {
if let Some(parent) = node.parent {
self.nodes
.get_mut(parent.0)
.unwrap()
.children
.retain(|child| child != &id);
}
for child in &node.children {
self.remove_recursive(*child);
}
node
})
}
fn remove_recursive(&mut self, node: NodeId) {
let node = self.nodes.remove(node.0);
for child in node.children {
self.remove_recursive(child);
}
}
}
pub trait TreeView<T>: Sized {
type Iterator<'a>: Iterator<Item = &'a T>
where
@ -152,15 +177,19 @@ pub trait TreeView<T>: Sized {
pub trait TreeLike<T>: TreeView<T> {
fn new(root: T) -> Self;
fn add_child(&mut self, parent: NodeId, value: T) -> NodeId;
fn create_node(&mut self, value: T) -> NodeId;
fn add_child(&mut self, parent: NodeId, child: NodeId);
fn remove(&mut self, id: NodeId) -> Option<T>;
fn replace(&mut self, id: NodeId, value: T);
fn remove_all_children(&mut self, id: NodeId) -> Vec<T>;
fn insert_before(&mut self, id: NodeId, value: T) -> NodeId;
fn replace(&mut self, old: NodeId, new: NodeId);
fn insert_after(&mut self, id: NodeId, value: T) -> NodeId;
fn insert_before(&mut self, id: NodeId, new: NodeId);
fn insert_after(&mut self, id: NodeId, new: NodeId);
}
pub struct ChildNodeIterator<'a, T, Tr: TreeView<T>> {
@ -304,78 +333,75 @@ impl<T> TreeLike<T> for Tree<T> {
Self { nodes, root }
}
fn add_child(&mut self, parent: NodeId, value: T) -> NodeId {
let node = Node {
fn create_node(&mut self, value: T) -> NodeId {
NodeId(self.nodes.insert(Node {
value,
parent: Some(parent),
parent: None,
children: Vec::new(),
};
let id = self.nodes.insert(node);
self.nodes
.get_mut(parent.0)
.unwrap()
.children
.push(NodeId(id));
NodeId(id)
}))
}
fn add_child(&mut self, parent: NodeId, new: NodeId) {
self.nodes.get_mut(parent.0).unwrap().children.push(new);
self.nodes.get_mut(new.0).unwrap().parent = Some(parent);
}
fn remove(&mut self, id: NodeId) -> Option<T> {
self.nodes.try_remove(id.0).map(|node| {
if let Some(parent) = node.parent {
self.nodes
.get_mut(parent.0)
.unwrap()
.children
.retain(|child| child != &id);
self.try_remove(id).map(|node| node.value)
}
fn remove_all_children(&mut self, id: NodeId) -> Vec<T> {
let mut children = Vec::new();
let self_mut = self as *mut Self;
for child in self.children_ids(id).unwrap() {
unsafe {
// Safety: No node has itself as a child
children.push((*self_mut).remove(*child).unwrap());
}
node.value
})
}
children
}
fn replace(&mut self, id: NodeId, value: T) {
fn replace(&mut self, old_id: NodeId, new_id: NodeId) {
// remove the old node
let old = self
.nodes
.get_mut(id.0)
.try_remove(old_id)
.expect("tried to replace a node that doesn't exist");
old.value = value;
// update the parent's link to the child
if let Some(parent_id) = old.parent {
let parent = self.nodes.get_mut(parent_id.0).unwrap();
for id in &mut parent.children {
if *id == old_id {
*id = new_id;
}
}
}
}
fn insert_before(&mut self, id: NodeId, value: T) -> NodeId {
fn insert_before(&mut self, id: NodeId, new: NodeId) {
let node = self.nodes.get(id.0).unwrap();
let parent_id = node.parent.expect("tried to insert before root");
let new = Node {
value,
parent: Some(parent_id),
children: Vec::new(),
};
let new_id = NodeId(self.nodes.insert(new));
self.nodes.get_mut(new.0).unwrap().parent = Some(parent_id);
let parent = self.nodes.get_mut(parent_id.0).unwrap();
let index = parent
.children
.iter()
.position(|child| child == &id)
.unwrap();
parent.children.insert(index, new_id);
new_id
parent.children.insert(index, new);
}
fn insert_after(&mut self, id: NodeId, value: T) -> NodeId {
fn insert_after(&mut self, id: NodeId, new: NodeId) {
let node = self.nodes.get(id.0).unwrap();
let parent_id = node.parent.expect("tried to insert before root");
let new = Node {
value,
parent: Some(parent_id),
children: Vec::new(),
};
let new_id = NodeId(self.nodes.insert(new));
self.nodes.get_mut(new.0).unwrap().parent = Some(parent_id);
let parent = self.nodes.get_mut(parent_id.0).unwrap();
let index = parent
.children
.iter()
.position(|child| child == &id)
.unwrap();
parent.children.insert(index + 1, new_id);
new_id
parent.children.insert(index + 1, new);
}
}
@ -498,7 +524,7 @@ pub struct SharedView<'a, T, Tr: TreeView<T>> {
impl<'a, T, Tr: TreeView<T>> SharedView<'a, T, Tr> {
/// Checks if a node is currently locked. Returns None if the node does not exist.
pub fn check_lock(&self, id: NodeId) -> Option<bool> {
let mut locks = self.node_locks.read();
let locks = self.node_locks.read();
locks.get(id.0).map(|lock| lock.is_locked())
}
}
@ -616,7 +642,8 @@ impl<'a, T, Tr: TreeView<T>> TreeView<T> for SharedView<'a, T, Tr> {
fn creation() {
let mut tree = Tree::new(1);
let parent = tree.root();
let child = tree.add_child(parent, 0);
let child = tree.create_node(0);
tree.add_child(parent, child);
println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 2);
@ -631,9 +658,12 @@ fn creation() {
fn insertion() {
let mut tree = Tree::new(0);
let parent = tree.root();
let child = tree.add_child(parent, 2);
let before = tree.insert_before(child, 1);
let after = tree.insert_after(child, 3);
let child = tree.create_node(2);
tree.add_child(parent, child);
let before = tree.create_node(1);
tree.insert_before(child, before);
let after = tree.create_node(3);
tree.insert_after(child, after);
println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 4);
@ -651,9 +681,12 @@ fn insertion() {
fn deletion() {
let mut tree = Tree::new(0);
let parent = tree.root();
let child = tree.add_child(parent, 2);
let before = tree.insert_before(child, 1);
let after = tree.insert_after(child, 3);
let child = tree.create_node(2);
tree.add_child(parent, child);
let before = tree.create_node(1);
tree.insert_before(child, before);
let after = tree.create_node(3);
tree.insert_after(child, after);
println!("Tree: {:#?}", tree);
assert_eq!(tree.size(), 4);
@ -702,7 +735,8 @@ fn shared_view() {
use std::thread;
let mut tree = Tree::new(1);
let parent = tree.root();
let child = tree.add_child(parent, 0);
let child = tree.create_node(0);
tree.add_child(parent, child);
let shared = SharedView::new(&mut tree);
@ -737,7 +771,8 @@ fn map() {
}
let mut tree = Tree::new(Value::new(1));
let parent = tree.root();
let child = tree.add_child(parent, Value::new(0));
let child = tree.create_node(Value::new(0));
tree.add_child(parent, child);
let mut mapped = tree.map(|x| &x.value, |x| &mut x.value);
@ -752,10 +787,14 @@ fn map() {
fn traverse_depth_first() {
let mut tree = Tree::new(0);
let parent = tree.root();
let child1 = tree.add_child(parent, 1);
tree.add_child(child1, 2);
let child2 = tree.add_child(parent, 3);
tree.add_child(child2, 4);
let child1 = tree.create_node(1);
tree.add_child(parent, child1);
let grandchild1 = tree.create_node(2);
tree.add_child(child1, grandchild1);
let child2 = tree.create_node(3);
tree.add_child(parent, child2);
let grandchild2 = tree.create_node(4);
tree.add_child(child2, grandchild2);
let mut node_count = 0;
tree.traverse_depth_first(move |node| {
@ -768,10 +807,14 @@ fn traverse_depth_first() {
fn traverse_breadth_first() {
let mut tree = Tree::new(0);
let parent = tree.root();
let child1 = tree.add_child(parent, 1);
tree.add_child(child1, 3);
let child2 = tree.add_child(parent, 2);
tree.add_child(child2, 4);
let child1 = tree.create_node(1);
tree.add_child(parent, child1);
let grandchild1 = tree.create_node(3);
tree.add_child(child1, grandchild1);
let child2 = tree.create_node(2);
tree.add_child(parent, child2);
let grandchild2 = tree.create_node(4);
tree.add_child(child2, grandchild2);
let mut node_count = 0;
tree.traverse_breadth_first(move |node| {