From dcad2fe8a2c8d74f890e3ef5f0fa1fd9311ec5c0 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 24 Nov 2022 15:05:15 -0600 Subject: [PATCH] intial update to new mutations --- packages/native-core/src/lib.rs | 2 - packages/native-core/src/node.rs | 28 +- packages/native-core/src/node_ref.rs | 52 +- packages/native-core/src/real_dom.rs | 917 +++++++++------------------ packages/native-core/src/state.rs | 23 +- packages/native-core/src/tree.rs | 173 +++-- 6 files changed, 440 insertions(+), 755 deletions(-) diff --git a/packages/native-core/src/lib.rs b/packages/native-core/src/lib.rs index bdd7e24be..895bb7dc9 100644 --- a/packages/native-core/src/lib.rs +++ b/packages/native-core/src/lib.rs @@ -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; diff --git a/packages/native-core/src/node.rs b/packages/native-core/src/node.rs index 5d6285071..09dd03e71 100644 --- a/packages/native-core/src/node.rs +++ b/packages/native-core/src/node.rs @@ -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 { #[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, /// 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, attributes: FxHashMap, listeners: FxHashSet, }, @@ -44,29 +47,12 @@ impl Node { 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 { self.node_data.element_id diff --git a/packages/native-core/src/node_ref.rs b/packages/native-core/src/node_ref.rs index 671d85663..759cc5ffb 100644 --- a/packages/native-core/src/node_ref.rs +++ b/packages/native-core/src/node_ref.rs @@ -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), /// 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, - mut other_iter: impl Iterator, + fn overlaps_iter<'a>( + self_iter: impl Iterator, + mut other_iter: impl Iterator, ) -> 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()) diff --git a/packages/native-core/src/real_dom.rs b/packages/native-core/src/real_dom.rs index 53547de68..cbeb80f2b 100644 --- a/packages/native-core/src/real_dom.rs +++ b/packages/native-core/src/real_dom.rs @@ -1,13 +1,11 @@ use anymap::AnyMap; -use dioxus_core::{ElementId, Mutations, VNode}; +use dioxus_core::{ElementId, Mutations}; use rustc_hash::{FxHashMap, FxHashSet}; -use slab::Slab; -use std::ops::{Index, IndexMut}; +use std::ops::{Deref, DerefMut, Index, IndexMut}; -use crate::node::{Node, NodeType}; +use crate::node::{Node, NodeData, NodeType, OwnedAttributeDiscription}; use crate::node_ref::{AttributeMask, NodeMask}; use crate::state::State; -use crate::traversable::Traversable; use crate::tree::{NodeId, Tree, TreeLike, TreeView}; use crate::RealNodeId; @@ -18,8 +16,10 @@ use crate::RealNodeId; pub struct RealDom { tree: Tree>, /// a map from element id to real node id - node_id_mapping: Vec, - nodes_listening: FxHashMap<&'static str, FxHashSet>, + node_id_mapping: Vec>, + nodes_listening: FxHashMap>, + stack: Vec, + templates: FxHashMap>, } impl Default for RealDom { @@ -32,369 +32,307 @@ impl RealDom { pub fn new() -> RealDom { let mut root = Node::new(NodeType::Element { tag: "Root".to_string(), - namespace: Some("Root"), + namespace: Some("Root".to_string()), attributes: FxHashMap::default(), listeners: FxHashSet::default(), - children: Vec::new(), }); root.node_data.element_id = Some(ElementId(0)); - let tree = Tree::new(root); + let mut tree = Tree::new(root); let root_id = tree.root(); - tree.get_mut(root_id).unwrap().node_data.id = root_id; + tree.get_mut(root_id).unwrap().node_data.node_id = root_id; RealDom { tree, node_id_mapping: Vec::new(), nodes_listening: FxHashMap::default(), + stack: vec![root_id], + templates: FxHashMap::default(), } } + fn element_to_node_id(&self, element_id: ElementId) -> RealNodeId { + self.node_id_mapping.get(element_id.0).unwrap().unwrap() + } + + fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) { + let node = self.tree.get_mut(node_id).unwrap(); + let node_id = node.node_data.node_id; + node.node_data.element_id = Some(element_id); + if self.node_id_mapping.len() <= element_id.0 { + self.node_id_mapping.resize(element_id.0 + 1, None); + } + self.node_id_mapping[element_id.0] = Some(node_id); + } + + fn load_child(&self, path: &[u8]) -> RealNodeId { + let mut current = *self.stack.last().unwrap(); + for i in path { + current = self.tree.children_ids(current).unwrap()[*i as usize]; + } + current + } + + fn create_node(&mut self, node: Node) -> RealNodeId { + let node_id = self.tree.create_node(node); + let node = self.tree.get_mut(node_id).unwrap(); + node.node_data.node_id = node_id; + node_id + } + /// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state. - pub fn apply_mutations( + pub fn apply_mutations<'a>( &mut self, - mutations_vec: Vec, + mutations_vec: Vec>, ) -> Vec<(RealNodeId, NodeMask)> { - let mut nodes_updated = Vec::new(); - nodes_updated.push((RealNodeId::ElementId(ElementId(0)), NodeMask::ALL)); + let mut nodes_updated: Vec<(RealNodeId, NodeMask)> = Vec::new(); for mutations in mutations_vec { for e in mutations.edits { use dioxus_core::Mutation::*; match e { - AppendChildren { root, children } => { - let target = self.resolve_maybe_id(root); - for id in children { - let id = RealNodeId::ElementId(ElementId(id as usize)); - self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated); - self.link_child(id, target).unwrap(); + AppendChildren { m } => { + let data = self.stack.split_off(m); + let (parent, children) = data.split_first().unwrap(); + for child in children { + self.tree.add_child(*parent, *child); + nodes_updated.push((*parent, NodeMask::ALL)); } } - ReplaceWith { root, nodes } => { - let id_to_replace = self.resolve_maybe_id(root); - let target = self[id_to_replace].node_data.parent.unwrap(); - for id in nodes { - let id = RealNodeId::ElementId(ElementId(id as usize)); - self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated); - self.link_child_before(id, target, id_to_replace).unwrap(); - } - self.remove(id_to_replace).unwrap(); + AssignId { path, id } => { + self.set_element_id(self.load_child(&path), id); } - InsertAfter { root, nodes } => { - let root = self.resolve_maybe_id(root); - let target = self.parent(root).unwrap(); - for id in nodes { - let id = RealNodeId::ElementId(ElementId(id as usize)); - self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated); - self.link_child_after(id, target, root).unwrap(); - } - } - InsertBefore { root, nodes } => { - let root = self.resolve_maybe_id(root); - let target = self.parent(root).unwrap(); - for id in nodes { - let id = RealNodeId::ElementId(ElementId(id as usize)); - self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated); - self.link_child_before(id, target, root).unwrap(); - } - } - Remove { root } => { - let id = self.resolve_maybe_id(root); - if let Some(parent) = self.parent(id) { - self.mark_dirty(parent, NodeMask::NONE, &mut nodes_updated); - } - self.remove(id).unwrap(); - } - CreateTextNode { root, text } => { - let n = Node::new(NodeType::Text { - text: text.to_string(), - }); - let id = self.insert(n, root, &mut nodes_updated); - self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated); - if let Some((parent, remaining)) = self.parents_queued.last_mut() { - *remaining -= 1; - let parent = *parent; - if *remaining == 0 { - self.parents_queued.pop(); - } - self.link_child(id, parent).unwrap(); - } - self.last = Some(id); - } - CreateElement { - root, - tag, - children, - } => { - let n = Node::new(NodeType::Element { - tag: tag.to_string(), + CreateElement { name } => { + let node = Node::new(NodeType::Element { + tag: name.to_string(), namespace: None, attributes: FxHashMap::default(), listeners: FxHashSet::default(), - children: Vec::new(), }); - let id = self.insert(n, root, &mut nodes_updated); - self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated); - if let Some((parent, remaining)) = self.parents_queued.last_mut() { - *remaining -= 1; - let parent = *parent; - if *remaining == 0 { - self.parents_queued.pop(); - } - self.link_child(id, parent).unwrap(); - } - self.last = Some(id); - if children > 0 { - self.parents_queued.push((id, children)); - } + let id = self.create_node(node); + self.stack.push(id); + nodes_updated.push((id, NodeMask::ALL)); } - CreateElementNs { - root, - tag, - ns, - children, - } => { - let n = Node::new(NodeType::Element { - tag: tag.to_string(), - namespace: Some(ns), + CreateElementNamespace { name, namespace } => { + let node = Node::new(NodeType::Element { + tag: name.to_string(), + namespace: Some(namespace.to_string()), attributes: FxHashMap::default(), listeners: FxHashSet::default(), - children: Vec::new(), }); - let id = self.insert(n, root, &mut nodes_updated); - self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated); - if let Some((parent, remaining)) = self.parents_queued.last_mut() { - *remaining -= 1; - let parent = *parent; - if *remaining == 0 { - self.parents_queued.pop(); - } - self.link_child(id, parent).unwrap(); + let id = self.create_node(node); + self.stack.push(id); + nodes_updated.push((id, NodeMask::ALL)); + } + CreatePlaceholder { id } => { + let node = Node::new(NodeType::Placeholder); + let node_id = self.create_node(node); + self.set_element_id(node_id, id); + self.stack.push(node_id); + nodes_updated.push((node_id, NodeMask::ALL)); + } + CreateStaticPlaceholder => { + let node = Node::new(NodeType::Placeholder); + let id = self.create_node(node); + self.stack.push(id); + nodes_updated.push((id, NodeMask::ALL)); + } + CreateStaticText { value } => { + let node = Node::new(NodeType::Text { + text: value.to_string(), + }); + let id = self.create_node(node); + self.stack.push(id); + nodes_updated.push((id, NodeMask::new().with_text())); + } + CreateTextNode { value, id } => { + let node = Node::new(NodeType::Text { + text: value.to_string(), + }); + let node_id = self.create_node(node); + let node = self.tree.get_mut(node_id).unwrap(); + node.node_data.element_id = Some(id); + self.stack.push(node_id); + nodes_updated.push((node_id, NodeMask::new().with_text())); + } + HydrateText { path, value, id } => { + let node_id = self.load_child(path); + self.set_element_id(node_id, id); + let node = self.tree.get_mut(node_id).unwrap(); + if let NodeType::Text { text } = &mut node.node_data.node_type { + *text = value.to_string(); } - self.last = Some(id); - if children > 0 { - self.parents_queued.push((id, children)); + nodes_updated.push((node_id, NodeMask::new().with_text())); + } + LoadTemplate { name, index, id } => { + let template_id = self.templates[name][index]; + let clone_id = self.clone_node(template_id); + self.set_element_id(clone_id, id); + } + ReplaceWith { id, m } => { + let new_nodes = self.stack.split_off(m); + let old_node_id = self.element_to_node_id(id); + for new in new_nodes { + self.tree.insert_after(old_node_id, new); + nodes_updated.push((new, NodeMask::ALL)); + } + self.tree.remove(old_node_id); + } + ReplacePlaceholder { path, m } => { + let new_nodes = self.stack.split_off(m); + let old_node_id = self.load_child(path); + for new in new_nodes { + self.tree.insert_after(old_node_id, new); + nodes_updated.push((new, NodeMask::ALL)); + } + self.tree.remove(old_node_id); + } + InsertAfter { id, m } => { + let new_nodes = self.stack.split_off(m); + let old_node_id = self.element_to_node_id(id); + for new in new_nodes { + self.tree.insert_after(old_node_id, new); + nodes_updated.push((new, NodeMask::ALL)); } } - CreatePlaceholder { root } => { - let n = Node::new(NodeType::Placeholder); - let id = self.insert(n, root, &mut nodes_updated); - self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated); - if let Some((parent, remaining)) = self.parents_queued.last_mut() { - *remaining -= 1; - let parent = *parent; - if *remaining == 0 { - self.parents_queued.pop(); - } - self.link_child(id, parent).unwrap(); + InsertBefore { id, m } => { + let new_nodes = self.stack.split_off(m); + let old_node_id = self.element_to_node_id(id); + for new in new_nodes { + self.tree.insert_before(old_node_id, new); + nodes_updated.push((new, NodeMask::ALL)); } - self.last = Some(id); + } + SaveTemplate { name, m } => { + let template = self.stack.split_off(m); + self.templates.insert(name.to_string(), template); + } + SetAttribute { + name, + value, + id, + ns, + } => { + let node_id = self.element_to_node_id(id); + let node = self.tree.get_mut(node_id).unwrap(); + if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type + { + attributes.insert( + OwnedAttributeDiscription { + name: name.to_string(), + namespace: ns.map(|s| s.to_string()), + volatile: false, + }, + crate::node::OwnedAttributeValue::Text(value.to_string()), + ); + nodes_updated.push(( + node_id, + NodeMask::new_with_attrs(AttributeMask::single(name)), + )); + } + } + SetStaticAttribute { name, value, ns } => { + let node_id = self.stack.last().unwrap(); + let node = self.tree.get_mut(*node_id).unwrap(); + if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type + { + attributes.insert( + OwnedAttributeDiscription { + name: name.to_string(), + namespace: ns.map(|s| s.to_string()), + volatile: false, + }, + crate::node::OwnedAttributeValue::Text(value.to_string()), + ); + nodes_updated.push(( + *node_id, + NodeMask::new_with_attrs(AttributeMask::single(name)), + )); + } + } + SetBoolAttribute { name, value, id } => { + let node_id = self.element_to_node_id(id); + let node = self.tree.get_mut(node_id).unwrap(); + if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type + { + attributes.insert( + OwnedAttributeDiscription { + name: name.to_string(), + namespace: None, + volatile: false, + }, + crate::node::OwnedAttributeValue::Bool(value), + ); + nodes_updated.push(( + node_id, + NodeMask::new_with_attrs(AttributeMask::single(name)), + )); + } + } + SetInnerText { value } => { + let node_id = *self.stack.last().unwrap(); + let node = self.tree.get_mut(node_id).unwrap(); + if let NodeType::Element { .. } = &mut node.node_data.node_type { + self.tree.remove_all_children(node_id); + let text_node = Node::new(NodeType::Text { + text: value.to_string(), + }); + let text_node_id = self.create_node(text_node); + self.tree.add_child(node_id, text_node_id); + } + } + SetText { value, id } => { + let node_id = self.element_to_node_id(id); + let node = self.tree.get_mut(node_id).unwrap(); + if let NodeType::Text { text } = &mut node.node_data.node_type { + *text = value.to_string(); + } + nodes_updated.push((node_id, NodeMask::new().with_text())); } NewEventListener { event_name, scope: _, - root, + id, } => { - let id = self.resolve_maybe_id(root); - self.mark_dirty(id, NodeMask::new().with_listeners(), &mut nodes_updated); - match &mut self[id].node_data.node_type { - NodeType::Text { .. } => panic!("Text nodes cannot have listeners"), - NodeType::Element { listeners, .. } => { - listeners.insert(event_name.to_string()); + let node_id = self.element_to_node_id(id); + let node = self.tree.get_mut(node_id).unwrap(); + if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type { + match self.nodes_listening.get_mut(event_name) { + Some(hs) => { + hs.insert(node_id); + } + None => { + let mut hs = FxHashSet::default(); + hs.insert(node_id); + self.nodes_listening.insert(event_name.to_string(), hs); + } } - NodeType::Placeholder => panic!("Placeholder cannot have listeners"), - } - if let Some(v) = self.nodes_listening.get_mut(event_name) { - v.insert(id); - } else { - let mut hs = FxHashSet::default(); - hs.insert(id); - self.nodes_listening.insert(event_name, hs); + listeners.insert(event_name.to_string()); } } - RemoveEventListener { root, event } => { - let id = self.resolve_maybe_id(root); - self.mark_dirty(id, NodeMask::new().with_listeners(), &mut nodes_updated); - let v = self.nodes_listening.get_mut(event).unwrap(); - v.remove(&id); - } - SetText { - root, - text: new_text, - } => { - let id = self.resolve_maybe_id(root); - self.mark_dirty(id, NodeMask::new().with_text(), &mut nodes_updated); - let target = &mut self[id]; - match &mut target.node_data.node_type { - NodeType::Text { text } => { - *text = new_text.to_string(); - } - _ => unreachable!(), + RemoveEventListener { id, event } => { + let node_id = self.element_to_node_id(id); + let node = self.tree.get_mut(node_id).unwrap(); + if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type { + listeners.remove(event); } + self.nodes_listening + .get_mut(event) + .unwrap() + .remove(&node_id); } - SetAttribute { - root, - field, - ns, - value, - } => { - let id = self.resolve_maybe_id(root); - if let NodeType::Element { attributes, .. } = - &mut self[id].node_data.node_type - { - attributes.insert( - OwnedAttributeDiscription { - name: field.to_owned(), - namespace: ns.map(|a| a.to_owned()), - volatile: false, - }, - value.into(), - ); - } else { - panic!("tried to call set attribute on a non element"); - } - self.mark_dirty( - id, - NodeMask::new_with_attrs(AttributeMask::single(field)), - &mut nodes_updated, - ); - } - RemoveAttribute { - root, name: field, .. - } => { - let id = self.resolve_maybe_id(root); - self.mark_dirty( - id, - NodeMask::new_with_attrs(AttributeMask::single(field)), - &mut nodes_updated, - ); - } - CloneNode { id, new_id } => { - let id = self.resolve_maybe_id(id); - self.clone_node_into(id, &mut nodes_updated, Some(new_id)); - } - CloneNodeChildren { id, new_ids } => { - let id = self.resolve_maybe_id(id); - let bounded_self: &mut Self = self; - let unbounded_self: &mut Self = - unsafe { std::mem::transmute(bounded_self) }; - if let NodeType::Element { children, .. } = &self[id].node_data.node_type { - for (old_id, new_id) in children.iter().zip(new_ids) { - let child_id = unbounded_self.clone_node_into( - *old_id, - &mut nodes_updated, - Some(new_id), - ); - unbounded_self[child_id].node_data.parent = None; - } - } - } - FirstChild {} => { - if let NodeType::Element { children, .. } = - &self[self.last.unwrap()].node_data.node_type - { - self.last = Some(children[0]); - } else { - panic!("tried to call first child on a non element"); - } - } - NextSibling {} => { - let id = self.last.unwrap(); - if let Some(parent) = self.parent(id) { - if let NodeType::Element { children, .. } = - &self[parent].node_data.node_type - { - let index = children.iter().position(|a| *a == id).unwrap(); - self.last = Some(children[index + 1]); - } - } else { - panic!("tried to call next sibling on a non element"); - } - } - ParentNode {} => { - if let Some(parent) = self.parent(self.last.unwrap()) { - self.last = Some(parent); - } else { - panic!("tried to call parent node on a non element"); - } - } - StoreWithId { id } => { - let old_id = self.last.unwrap(); - let node = self.internal_nodes.remove(old_id.as_unaccessable_id()); - let new_id = self.insert(*node, Some(id), &mut nodes_updated); - self.update_id(old_id, new_id, &mut nodes_updated); - } - SetLastNode { id } => { - self.last = - Some(RealNodeId::ElementId(dioxus_core::ElementId(id as usize))); + Remove { id } => { + let node_id = self.element_to_node_id(id); + self.remove(node_id); } } } } // remove any nodes that were created and then removed in the same mutations from the dirty nodes list - nodes_updated.retain(|n| match n.0 { - RealNodeId::ElementId(id) => self.nodes.get(id.0).and_then(|o| o.as_ref()).is_some(), - RealNodeId::UnaccessableId(id) => self.internal_nodes.get(id).is_some(), - }); + nodes_updated.retain(|n| self.tree.get(n.0).is_some()); nodes_updated } - /// Update refrences to an old node id to a new node id - fn update_id( - &mut self, - old_id: RealNodeId, - new_id: RealNodeId, - nodes_updated: &mut Vec<(RealNodeId, NodeMask)>, - ) { - // this is safe because a node cannot have itself as a child or parent - let unbouned_self = unsafe { &mut *(self as *mut Self) }; - // update parent's link to child id - if let Some(parent) = self[new_id].node_data.parent { - if let NodeType::Element { children, .. } = &mut self[parent].node_data.node_type { - for c in children { - if *c == old_id { - *c = new_id; - break; - } - } - } - } - // update child's link to parent id - if let NodeType::Element { children, .. } = &self[new_id].node_data.node_type { - for child_id in children { - unbouned_self[*child_id].node_data.parent = Some(new_id); - } - } - // update dirty nodes - for (node, _) in nodes_updated { - if *node == old_id { - *node = new_id; - } - } - // update nodes listening - for v in self.nodes_listening.values_mut() { - if v.contains(&old_id) { - v.remove(&old_id); - v.insert(new_id); - } - } - // update last - if let Some(last) = self.last { - if last == old_id { - self.last = Some(new_id); - } - } - } - - fn mark_dirty( - &self, - gid: RealNodeId, - mask: NodeMask, - dirty_nodes: &mut Vec<(RealNodeId, NodeMask)>, - ) { - dirty_nodes.push((gid, mask)); - } - /// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts. pub fn update_state( &mut self, @@ -405,140 +343,6 @@ impl RealDom { S::update(&nodes_updated, &mut state_tree, &node_tree, &ctx) } - /// Link a child and parent together - fn link_child(&mut self, child_id: RealNodeId, parent_id: RealNodeId) -> Option<()> { - let parent = &mut self[parent_id]; - parent.add_child(child_id); - let parent_height = parent.node_data.height; - self[child_id].set_parent(parent_id); - self.set_height(child_id, parent_height + 1); - - Some(()) - } - - /// Link a child and parent together with the child inserted before a marker - fn link_child_before( - &mut self, - child_id: RealNodeId, - parent_id: RealNodeId, - marker: RealNodeId, - ) -> Option<()> { - let parent = &mut self[parent_id]; - if let NodeType::Element { children, .. } = &mut parent.node_data.node_type { - let index = children.iter().position(|a| *a == marker)?; - children.insert(index, child_id); - } - let parent_height = parent.node_data.height; - self[child_id].set_parent(parent_id); - self.set_height(child_id, parent_height + 1); - - Some(()) - } - - /// Link a child and parent together with the child inserted after a marker - fn link_child_after( - &mut self, - child_id: RealNodeId, - parent_id: RealNodeId, - marker: RealNodeId, - ) -> Option<()> { - let parent = &mut self[parent_id]; - if let NodeType::Element { children, .. } = &mut parent.node_data.node_type { - let index = children.iter().position(|a| *a == marker)?; - children.insert(index + 1, child_id); - } - let parent_height = parent.node_data.height; - self[child_id].set_parent(parent_id); - self.set_height(child_id, parent_height + 1); - - Some(()) - } - - /// Recursively increase the height of a node and its children - fn set_height(&mut self, id: RealNodeId, height: u16) { - let node = &mut self[id]; - node.node_data.height = height; - if let NodeType::Element { children, .. } = &node.node_data.node_type { - for c in children.clone() { - self.set_height(c, height + 1); - } - } - } - - // remove a node and it's children from the dom. - fn remove(&mut self, id: RealNodeId) -> Option> { - // We do not need to remove the node from the parent's children list for children. - fn inner(dom: &mut RealDom, id: RealNodeId) -> Option> { - let mut node = match id { - RealNodeId::ElementId(id) => *dom.nodes[id.0].take()?, - RealNodeId::UnaccessableId(id) => *dom.internal_nodes.remove(id), - }; - if let NodeType::Element { children, .. } = &mut node.node_data.node_type { - for c in children { - inner(dom, *c); - } - } - Some(node) - } - let mut node = match id { - RealNodeId::ElementId(id) => *self.nodes[id.0].take()?, - RealNodeId::UnaccessableId(id) => *self.internal_nodes.remove(id), - }; - if let Some(parent) = node.node_data.parent { - let parent = &mut self[parent]; - parent.remove_child(id); - } - if let NodeType::Element { children, .. } = &mut node.node_data.node_type { - for c in children { - inner(self, *c)?; - } - } - Some(node) - } - - fn resize_to(&mut self, id: usize) { - let current_len = self.nodes.len(); - if current_len - 1 < id { - self.nodes.extend((0..1 + id - current_len).map(|_| None)); - } - } - - fn insert( - &mut self, - mut node: Node, - id: Option, - nodes_updated: &mut Vec<(RealNodeId, NodeMask)>, - ) -> RealNodeId { - match id { - Some(id) => { - let id = id as usize; - self.resize_to(id); - let real_id = RealNodeId::ElementId(ElementId(id)); - node.node_data.id = Some(real_id); - // move the old node to a new unaccessable id - if let Some(mut old) = self.nodes[id].take() { - let old_id = old.node_data.id.unwrap(); - let entry = self.internal_nodes.vacant_entry(); - let id = entry.key(); - let new_id = RealNodeId::UnaccessableId(id); - old.node_data.id = Some(real_id); - entry.insert(old); - self.update_id(old_id, new_id, nodes_updated); - } - self.nodes[id] = Some(Box::new(node)); - real_id - } - None => { - let entry = self.internal_nodes.vacant_entry(); - let id = entry.key(); - let real_id = RealNodeId::UnaccessableId(id); - node.node_data.id = Some(real_id); - entry.insert(Box::new(node)); - real_id - } - } - } - /// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up. /// This can be useful to avoid creating duplicate events. pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node> { @@ -551,162 +355,37 @@ impl RealDom { } } - /// Check if the dom contains a node and its children. - pub fn contains_node(&self, node: &VNode) -> bool { - match node { - VNode::Component(_) => { - todo!() - } - VNode::Element(e) => { - if let Some(id) = e.id.get() { - let dom_node = &self[id]; - match &dom_node.node_data.node_type { - NodeType::Element { - tag, - namespace, - children, - attributes, - listeners, - } => { - tag == e.tag - && namespace == &e.namespace - && children - .iter() - .zip( - e.children - .iter() - .map(|c| RealNodeId::ElementId(c.mounted_id())), - ) - .all(|(c1, c2)| *c1 == c2) - && e.children.iter().all(|c| { - self.contains_node(c) - && self[RealNodeId::ElementId(c.mounted_id())] - .node_data - .parent - == e.id.get().map(RealNodeId::ElementId) - }) - && attributes - .iter() - .zip(e.attributes.iter()) - .all(|((disc, val), b)| *disc == b.attribute && *val == b.value) - && listeners - .iter() - .zip(e.listeners.iter()) - .all(|(a, b)| *a == b.event) - } - _ => false, - } - } else { - true - } - } - VNode::Fragment(f) => f.children.iter().all(|c| self.contains_node(c)), - VNode::Placeholder(_) => true, - VNode::Text(t) => { - if let Some(id) = t.id.get() { - let dom_node = &self[RealNodeId::ElementId(id)]; - match &dom_node.node_data.node_type { - NodeType::Text { text } => t.text == text, - _ => false, - } - } else { - true - } - } - VNode::TemplateRef(_) => todo!(), - } - } - /// Return the number of nodes in the dom. pub fn size(&self) -> usize { // The dom has a root node, ignore it. - self.nodes.iter().filter(|n| n.is_some()).count() - 1 + self.tree.size() - 1 } /// Returns the id of the root node. - pub fn root_id(&self) -> usize { - self.root + pub fn root_id(&self) -> NodeId { + self.tree.root() } - /// Call a function for each node in the dom, depth first. - pub fn traverse_depth_first(&self, mut f: impl FnMut(&Node)) { - fn inner(dom: &RealDom, id: RealNodeId, f: &mut impl FnMut(&Node)) { - let node = &dom[id]; - f(node); - if let NodeType::Element { children, .. } = &node.node_data.node_type { - for c in children { - inner(dom, *c, f); - } - } - } - if let NodeType::Element { children, .. } = &self - [RealNodeId::ElementId(ElementId(self.root))] - .node_data - .node_type - { - for c in children { - inner(self, *c, &mut f); - } - } - } - - /// Call a function for each node in the dom, depth first. - pub fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(&mut Node)) { - fn inner(dom: &mut RealDom, id: RealNodeId, f: &mut impl FnMut(&mut Node)) { - let node = &mut dom[id]; - f(node); - if let NodeType::Element { children, .. } = &mut node.node_data.node_type { - for c in children.clone() { - inner(dom, c, f); - } - } - } - let root = self.root; - if let NodeType::Element { children, .. } = &mut self - [RealNodeId::ElementId(ElementId(root))] - .node_data - .node_type - { - for c in children.clone() { - inner(self, c, &mut f); - } - } - } - - pub fn split( - &mut self, - ) -> ( - impl Traversable + '_, - impl Traversable + '_, - ) { + pub fn split(&mut self) -> (impl TreeView + '_, impl TreeView + '_) { let raw = self as *mut Self; - // this is safe beacuse the traversable trait does not allow mutation of the position of elements, and within elements the access is disjoint. + // this is safe beacuse the treeview trait does not allow mutation of the position of elements, and within elements the access is disjoint. ( unsafe { &mut *raw }.map(|n| &n.state, |n| &mut n.state), unsafe { &mut *raw }.map(|n| &n.node_data, |n| &mut n.node_data), ) } - /// Recurively clones a node and marks it and it's children as dirty. - fn clone_node_into( - &mut self, - id: RealNodeId, - nodes_updated: &mut Vec<(RealNodeId, NodeMask)>, - new_id: Option, - ) -> RealNodeId { - let new_id = self.insert(self[id].clone(), new_id, nodes_updated); - nodes_updated.push((new_id, NodeMask::ALL)); - // this is safe because no node has itself as a child. - let unbounded_self = unsafe { &mut *(self as *mut Self) }; - let mut node = &mut self[new_id]; - node.node_data.height = 0; - if let NodeType::Element { children, .. } = &mut node.node_data.node_type { - for c in children { - let child_id = unbounded_self.clone_node_into(*c, nodes_updated, None); - *c = child_id; - let parent_height = node.node_data.height; - unbounded_self[child_id].set_parent(new_id); - unbounded_self.set_height(child_id, parent_height + 1); + fn clone_node(&mut self, node_id: NodeId) -> RealNodeId { + let node = self.tree.get(node_id).unwrap(); + let new_node = node.clone(); + let new_id = self.create_node(new_node); + let self_ptr = self as *mut Self; + for child in self.tree.children_ids(node_id).unwrap() { + unsafe { + // this is safe because no node has itself as a child + let self_mut = &mut *self_ptr; + let child_id = self_mut.clone_node(*child); + self_mut.tree.add_child(new_id, child_id); } } new_id @@ -716,8 +395,8 @@ impl RealDom { impl Index for RealDom { type Output = Node; - fn index(&self, idx: ElementId) -> &Self::Output { - self.get(RealNodeId::ElementId(idx)).unwrap() + fn index(&self, id: ElementId) -> &Self::Output { + self.tree.get(self.element_to_node_id(id)).unwrap() } } @@ -725,62 +404,32 @@ impl Index for RealDom { type Output = Node; fn index(&self, idx: RealNodeId) -> &Self::Output { - self.get(idx).unwrap() + self.tree.get(idx).unwrap() } } impl IndexMut for RealDom { - fn index_mut(&mut self, idx: ElementId) -> &mut Self::Output { - self.get_mut(RealNodeId::ElementId(idx)).unwrap() + fn index_mut(&mut self, id: ElementId) -> &mut Self::Output { + self.tree.get_mut(self.element_to_node_id(id)).unwrap() } } impl IndexMut for RealDom { fn index_mut(&mut self, idx: RealNodeId) -> &mut Self::Output { - self.get_mut(idx).unwrap() + self.tree.get_mut(idx).unwrap() } } -impl Traversable for RealDom { - type Id = RealNodeId; - type Node = Node; +impl Deref for RealDom { + type Target = Tree>; - fn height(&self, id: Self::Id) -> Option { - let node = ::get(self, id); - Some(node?.node_data.height) + fn deref(&self) -> &Self::Target { + &self.tree } +} - fn get(&self, id: Self::Id) -> Option<&Self::Node> { - match id { - RealNodeId::ElementId(id) => { - self.nodes.get(id.0).and_then(|b| b.as_ref().map(|b| &**b)) - } - RealNodeId::UnaccessableId(id) => self.internal_nodes.get(id).map(|b| &**b), - } - } - - fn get_mut(&mut self, id: Self::Id) -> Option<&mut Self::Node> { - match id { - RealNodeId::ElementId(id) => self - .nodes - .get_mut(id.0) - .and_then(|b| b.as_mut().map(|b| &mut **b)), - RealNodeId::UnaccessableId(id) => self.internal_nodes.get_mut(id).map(|b| &mut **b), - } - } - - fn children(&self, id: Self::Id) -> &[Self::Id] { - if let Some(node) = ::get(self, id) { - match &node.node_data.node_type { - NodeType::Element { children, .. } => children, - _ => &[], - } - } else { - &[] - } - } - - fn parent(&self, id: Self::Id) -> Option { - self.get(id).and_then(|n| n.node_data.parent) +impl DerefMut for RealDom { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.tree } } diff --git a/packages/native-core/src/state.rs b/packages/native-core/src/state.rs index d858a2a78..9657a1c21 100644 --- a/packages/native-core/src/state.rs +++ b/packages/native-core/src/state.rs @@ -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( - s_iter: impl Iterator, - o_iter: impl Iterator, +pub(crate) fn union_ordered_iter<'a>( + s_iter: impl Iterator, + o_iter: impl Iterator, new_len_guess: usize, -) -> Vec { +) -> Vec { 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( 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( } } } - 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 { /// 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, - T2: Traversable, - >( + fn update<'a, T: TreeView, T2: TreeView>( dirty: &[(RealNodeId, NodeMask)], state_tree: &'a mut T, rdom: &'a T2, diff --git a/packages/native-core/src/tree.rs b/packages/native-core/src/tree.rs index 76769ee54..6931d2e23 100644 --- a/packages/native-core/src/tree.rs +++ b/packages/native-core/src/tree.rs @@ -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 { root: NodeId, } +impl Tree { + fn try_remove(&mut self, id: NodeId) -> Option> { + 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: Sized { type Iterator<'a>: Iterator where @@ -152,15 +177,19 @@ pub trait TreeView: Sized { pub trait TreeLike: TreeView { 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; - fn replace(&mut self, id: NodeId, value: T); + fn remove_all_children(&mut self, id: NodeId) -> Vec; - 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> { @@ -304,78 +333,75 @@ impl TreeLike for Tree { 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 { - 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 { + 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> { impl<'a, T, Tr: TreeView> 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 { - 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> TreeView 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| {