finish shipyard migration in native-core

This commit is contained in:
Evan Almloff committed 2023-03-07 16:00:43 -06:00
1 parent b91e010ac7
commit a8566b4e71
7 files changed
+414 -307

No files matched your search

+1
View File
@@ -17,6 +17,7 @@ members = [
"packages/rsx",
"packages/tui",
"packages/native-core",
"packages/native-core-macro",
"packages/rsx-rosetta",
"packages/signals",
"packages/hot-reload",
+116 -12
View File
@@ -1,22 +1,126 @@
extern crate proc_macro;
mod sorted_slice;
use std::collections::HashSet;
use proc_macro::TokenStream;
use quote::{quote, ToTokens, __private::Span};
use sorted_slice::StrSlice;
use syn::parenthesized;
use syn::parse::ParseBuffer;
use syn::punctuated::Punctuated;
use syn::{
self,
parse::{Parse, ParseStream, Result},
parse_macro_input, parse_quote, Error, Field, Ident, Token, Type,
};
use quote::quote;
use syn::Type;
/// A helper attribute for deriving `State` for a struct.
#[proc_macro_attribute]
pub fn my_attribute(_: TokenStream, input: TokenStream) -> TokenStream {
pub fn partial_derive_pass(_: TokenStream, input: TokenStream) -> TokenStream {
let impl_block: syn::ItemImpl = syn::parse(input).unwrap();
let parent_dependencies = impl_block
.items
.iter()
.find_map(|item| {
if let syn::ImplItem::Type(syn::ImplItemType {
attrs, ident, ty, ..
}) = item
{
(ident == "ParentDependencies").then_some(ty)
} else {
None
}
})
.unwrap();
let child_dependencies = impl_block
.items
.iter()
.find_map(|item| {
if let syn::ImplItem::Type(syn::ImplItemType {
attrs, ident, ty, ..
}) = item
{
(ident == "ChildDependencies").then_some(ty)
} else {
None
}
})
.unwrap();
let node_dependencies = impl_block
.items
.iter()
.find_map(|item| {
if let syn::ImplItem::Type(syn::ImplItemType {
attrs, ident, ty, ..
}) = item
{
(ident == "NodeDependencies").then_some(ty)
} else {
None
}
})
.unwrap();
let this_type = &impl_block.self_ty;
let mut combined_dependencies = HashSet::new();
match parent_dependencies {
Type::Tuple(tuple) => {
for type_ in &tuple.elems {
combined_dependencies.insert(type_.clone());
}
}
_ => panic!("ParentDependencies must be a tuple"),
}
match child_dependencies {
Type::Tuple(tuple) => {
for type_ in &tuple.elems {
combined_dependencies.insert(type_.clone());
}
}
_ => panic!("ChildDependencies must be a tuple"),
}
match node_dependencies {
Type::Tuple(tuple) => {
for type_ in &tuple.elems {
combined_dependencies.insert(type_.clone());
}
}
_ => panic!("NodeDependencies must be a tuple"),
}
combined_dependencies.insert(*this_type.clone());
let combined_dependencies = combined_dependencies.into_iter();
let combined_dependencies = quote!((#(#combined_dependencies),*));
quote!(#impl_block).into()
}
// pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
// /// This is a tuple of (T: Pass, ..) of states read from the parent required to run this pass
// type ParentDependencies: Dependancy;
// /// This is a tuple of (T: Pass, ..) of states read from the children required to run this pass
// type ChildDependencies: Dependancy;
// /// This is a tuple of (T: Pass, ..) of states read from the node required to run this pass
// type NodeDependencies: Dependancy;
// /// A tuple of all the dependencies combined
// type CombinedDependencies: Dependancy;
// /// This is a mask of what aspects of the node are required to run this pass
// const NODE_MASK: NodeMaskBuilder<'static>;
//
// /// Update this state in a node, returns if the state was updated
// fn update<'a>(
// &mut self,
// node_view: NodeView<V>,
// node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
// parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
// children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
// context: &SendAnyMap,
// ) -> bool;
//
// /// Create a new instance of this state
// fn create<'a>(
// node_view: NodeView<V>,
// node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
// parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
// children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
// context: &SendAnyMap,
// ) -> Self;
//
// /// Create a workload system for this state
// fn workload_system(dependants: FxHashSet<TypeId>) -> WorkloadSystem;
// }
+1
View File
@@ -29,6 +29,7 @@ lightningcss = "1.0.0-alpha.39"
rayon = "1.6.1"
shipyard = "0.6.2"
shipyard_hierarchy = "0.6.0"
[dev-dependencies]
+2 -1
View File
@@ -1,3 +1,4 @@
use crate::tree::TreeMut;
use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
use rustc_hash::{FxHashMap, FxHashSet};
use shipyard::Component;
@@ -155,7 +156,7 @@ impl DioxusState {
let new_nodes = self.stack.split_off(self.stack.len() - m);
let old_node_id = self.element_to_node_id(id);
for new in new_nodes {
rdom.tree.insert_before(old_node_id, new);
rdom.tree_mut().insert_before(old_node_id, new);
}
}
SetAttribute {
+96 -140
View File
@@ -1,7 +1,10 @@
use anymap::AnyMap;
use parking_lot::RwLock;
use rustc_hash::{FxHashMap, FxHashSet};
use shipyard::{Component, IntoBorrow, Unique, View, WorkloadSystem};
use shipyard::{
BorrowInfo, Component, IntoBorrow, IntoWorkloadSystem, Unique, UniqueView, View,
WorkloadSystem, World,
};
use std::any::{Any, TypeId};
use std::collections::BTreeMap;
use std::marker::PhantomData;
@@ -9,7 +12,9 @@ use std::sync::Arc;
use crate::node::FromAnyValue;
use crate::node_ref::{NodeMaskBuilder, NodeView};
use crate::SendAnyMap;
use crate::real_dom::{DirtyNodesResult, SendAnyMapWrapper};
use crate::tree::{TreeMut, TreeRef, TreeRefView};
use crate::{FxDashSet, SendAnyMap};
use crate::{NodeId, NodeMask};
#[derive(Default)]
@@ -108,6 +113,7 @@ pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
type ChildDependencies: Dependancy;
/// This is a tuple of (T: Pass, ..) of states read from the node required to run this pass
type NodeDependencies: Dependancy;
/// A tuple of all the dependencies combined
type CombinedDependencies: Dependancy;
/// This is a mask of what aspects of the node are required to run this pass
const NODE_MASK: NodeMaskBuilder<'static>;
@@ -130,39 +136,93 @@ pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
context: &SendAnyMap,
) -> Self;
/// Create a workload system for this state
fn workload_system(dependants: FxHashSet<TypeId>) -> WorkloadSystem;
}
pub struct RunPassView<'a> {
type_id: TypeId,
dependants: FxHashSet<TypeId>,
pass_direction: PassDirection,
tree: TreeRefView<'a>,
nodes_updated: UniqueView<'a, DirtyNodesResult>,
dirty: UniqueView<'a, DirtyNodeStates>,
ctx: UniqueView<'a, SendAnyMapWrapper>,
}
impl<'a> RunPassView<'a> {
pub fn borrow(
type_id: TypeId,
dependants: FxHashSet<TypeId>,
pass_direction: PassDirection,
world: &'a World,
) -> Self {
Self {
type_id,
dependants,
pass_direction,
tree: world.borrow().unwrap(),
nodes_updated: world.borrow().unwrap(),
dirty: world.borrow().unwrap(),
ctx: world.borrow().unwrap(),
}
}
}
pub fn run_pass(view: RunPassView, mut update_node: impl FnMut(NodeId, &SendAnyMap) -> bool) {
let RunPassView {
type_id,
dependants,
pass_direction,
tree,
nodes_updated,
dirty,
ctx,
} = view;
let ctx = ctx.as_ref();
match pass_direction {
PassDirection::ParentToChild => {
while let Some((height, id)) = dirty.pop_front(type_id) {
let id = tree.id_at(id).unwrap();
if (update_node)(id, ctx) {
nodes_updated.insert(id);
for id in tree.children_ids(id).unwrap() {
for dependant in &dependants {
dirty.insert(*dependant, id, height + 1);
}
}
}
}
}
PassDirection::ChildToParent => {
while let Some((height, id)) = dirty.pop_back(type_id) {
let id = tree.id_at(id).unwrap();
if (update_node)(id, ctx) {
nodes_updated.insert(id);
if let Some(id) = tree.parent_id(id) {
for dependant in &dependants {
dirty.insert(*dependant, id, height - 1);
}
}
}
}
}
PassDirection::AnyOrder => {
while let Some((height, id)) = dirty.pop_back(type_id) {
let id = tree.id_at(id).unwrap();
if (update_node)(id, ctx) {
nodes_updated.insert(id);
for dependant in &dependants {
dirty.insert(*dependant, id, height);
}
}
}
}
}
}
pub trait AnyState<V: FromAnyValue + Send + Sync = ()>: State<V> {
fn workload_system() -> WorkloadSystem;
// Box::new(
// move |node_id: NodeId, tree: &mut TreeStateView, context: &SendAnyMap| {
// debug_assert!(!Self::NodeDependencies::type_ids()
// .iter()
// .any(|id| *id == TypeId::of::<Self>()));
// // get all of the states from the tree view
// // Safety: No node has itself as a parent or child.
// let myself: SlabEntry<'static, Self> = unsafe {
// std::mem::transmute(tree.get_slab_mut::<Self>().unwrap().entry(node_id))
// };
// let node_data = tree.get_single::<NodeType<V>>(node_id).unwrap();
// let node = tree.get::<Self::NodeDependencies>(node_id).unwrap();
// let children = tree.children::<Self::ChildDependencies>(node_id);
// let parent = tree.parent::<Self::ParentDependencies>(node_id);
// let view = NodeView::new(node_id, node_data, &node_mask);
// if myself.value.is_none() {
// *myself.value = Some(Self::create(view, node, parent, children, context));
// true
// } else {
// myself
// .value
// .as_mut()
// .unwrap()
// .update(view, node, parent, children, context)
// }
// },
// ) as PassCallback
fn to_type_erased() -> TypeErasedPass<V>
where
Self: Sized,
@@ -174,9 +234,9 @@ pub trait AnyState<V: FromAnyValue + Send + Sync = ()>: State<V> {
parent_dependant: !Self::parent_type_ids().is_empty(),
child_dependant: !Self::child_type_ids().is_empty(),
dependants: FxHashSet::default(),
mask: node_mask.clone(),
mask: node_mask,
pass_direction: Self::pass_direction(),
workload: Some(Self::workload_system()),
workload: Self::workload_system,
phantom: PhantomData,
}
}
@@ -224,58 +284,11 @@ pub struct TypeErasedPass<V: FromAnyValue + Send = ()> {
pub(crate) combined_dependancy_type_ids: FxHashSet<TypeId>,
pub(crate) dependants: FxHashSet<TypeId>,
pub(crate) mask: NodeMask,
pub(crate) workload: Option<WorkloadSystem>,
pub(crate) workload: fn(FxHashSet<TypeId>) -> WorkloadSystem,
pub(crate) pass_direction: PassDirection,
phantom: PhantomData<V>,
}
// impl<V: FromAnyValue + Send> TypeErasedPass<V> {
// fn resolve(
// &self,
// mut tree: TreeStateView,
// dirty: &DirtyNodeStates,
// nodes_updated: &FxDashSet<NodeId>,
// ctx: &SendAnyMap,
// ) {
// match self.pass_direction {
// PassDirection::ParentToChild => {
// while let Some((height, id)) = dirty.pop_front(self.this_type_id) {
// if (self.pass)(id, &mut tree, ctx) {
// nodes_updated.insert(id);
// for id in tree.children_ids(id).unwrap() {
// for dependant in &self.dependants {
// dirty.insert(*dependant, *id, height + 1);
// }
// }
// }
// }
// }
// PassDirection::ChildToParent => {
// while let Some((height, id)) = dirty.pop_back(self.this_type_id) {
// if (self.pass)(id, &mut tree, ctx) {
// nodes_updated.insert(id);
// if let Some(id) = tree.parent_id(id) {
// for dependant in &self.dependants {
// dirty.insert(*dependant, id, height - 1);
// }
// }
// }
// }
// }
// PassDirection::AnyOrder => {
// while let Some((height, id)) = dirty.pop_back(self.this_type_id) {
// if (self.pass)(id, &mut tree, ctx) {
// nodes_updated.insert(id);
// for dependant in &self.dependants {
// dirty.insert(*dependant, id, height);
// }
// }
// }
// }
// }
// }
// }
#[derive(Debug)]
pub enum PassDirection {
ParentToChild,
@@ -300,7 +313,7 @@ impl<'a> AnyMapLike<'a> for &'a SendAnyMap {
}
pub trait Dependancy {
type ElementBorrowed<'a>: IntoBorrow;
type ElementBorrowed<'a>: IntoBorrow + BorrowInfo;
fn type_ids() -> Box<[TypeId]> {
Box::new([])
@@ -330,60 +343,3 @@ impl_dependancy!(A, B, C, D, E, F, G);
impl_dependancy!(A, B, C, D, E, F, G, H);
impl_dependancy!(A, B, C, D, E, F, G, H, I);
impl_dependancy!(A, B, C, D, E, F, G, H, I, J);
// pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
// dom: &mut RealDom<V>,
// dirty_nodes: DirtyNodeStates,
// ctx: SendAnyMap,
// parallel: bool,
// ) -> FxDashSet<NodeId> {
// let passes = &dom.dirty_nodes.passes;
// let mut resolved_passes: FxHashSet<TypeId> = FxHashSet::default();
// let mut resolving = Vec::new();
// let nodes_updated = Arc::new(FxDashSet::default());
// let ctx = Arc::new(ctx);
// let mut pass_indexes_remaining: Vec<_> = (0..passes.len()).collect::<Vec<_>>();
// while !pass_indexes_remaining.is_empty() {
// let mut currently_in_use = FxHashSet::<TypeId>::default();
// let dynamically_borrowed_tree = dom.tree.dynamically_borrowed();
// rayon::in_place_scope(|s| {
// let mut i = 0;
// while i < pass_indexes_remaining.len() {
// let passes_idx = pass_indexes_remaining[i];
// let pass = &passes[passes_idx];
// let pass_id = pass.this_type_id;
// // check if the pass is ready to be run
// if pass.combined_dependancy_type_ids.iter().all(|d| {
// (resolved_passes.contains(d) || *d == pass_id) && !currently_in_use.contains(d)
// }) {
// pass_indexes_remaining.remove(i);
// resolving.push(pass_id);
// currently_in_use.insert(pass.this_type_id);
// let tree_view = dynamically_borrowed_tree.view(
// pass.combined_dependancy_type_ids
// .iter()
// .filter(|id| **id != pass.this_type_id)
// .copied()
// .chain(std::iter::once(TypeId::of::<NodeType<V>>())),
// [pass.this_type_id],
// );
// let dirty_nodes = dirty_nodes.clone();
// let nodes_updated = nodes_updated.clone();
// let ctx = ctx.clone();
// if parallel {
// s.spawn(move |_| {
// pass.resolve(tree_view, &dirty_nodes, &nodes_updated, &ctx);
// });
// } else {
// pass.resolve(tree_view, &dirty_nodes, &nodes_updated, &ctx);
// }
// } else {
// i += 1;
// }
// }
// });
// resolved_passes.extend(resolving.iter().copied());
// resolving.clear()
// }
// std::sync::Arc::try_unwrap(nodes_updated).unwrap()
// }
+129 -65
View File
@@ -1,10 +1,8 @@
use rustc_hash::{FxHashMap, FxHashSet};
use shipyard::error::GetStorage;
use shipyard::track::Untracked;
use shipyard::{
Component, Get, IntoBorrow, ScheduledWorkload, System, Unique, View, ViewMut, Workload,
WorkloadSystem,
};
use shipyard::{Component, Get, IntoBorrow, ScheduledWorkload, Unique, View, ViewMut, Workload};
use shipyard::{SystemModificator, World};
use std::any::TypeId;
use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};
@@ -17,17 +15,33 @@ use crate::node_ref::{NodeMask, NodeMaskBuilder};
use crate::node_watcher::NodeWatcher;
use crate::passes::{DirtyNodeStates, TypeErasedPass};
use crate::prelude::AttributeMaskBuilder;
use crate::tree::Tree;
use crate::tree::{TreeMut, TreeMutView, TreeRef, TreeRefView};
use crate::NodeId;
use crate::{FxDashSet, SendAnyMap};
#[derive(Unique)]
struct SendAnyMapWrapper(SendAnyMap);
pub struct SendAnyMapWrapper(SendAnyMap);
impl Deref for SendAnyMapWrapper {
type Target = SendAnyMap;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Unique, Default)]
struct DirtyNodes(FxDashSet<NodeId>);
pub struct DirtyNodesResult(FxDashSet<NodeId>);
pub(crate) struct NodesDirty<V: FromAnyValue + Send + Sync> {
impl Deref for DirtyNodesResult {
type Target = FxDashSet<NodeId>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct NodesDirty<V: FromAnyValue + Send + Sync> {
passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
nodes_updated: FxHashMap<NodeId, NodeMask>,
pub(crate) passes: Box<[TypeErasedPass<V>]>,
@@ -76,31 +90,27 @@ type NodeWatchers<V> = Arc<RwLock<Vec<Box<dyn NodeWatcher<V> + Send + Sync>>>>;
/// # Custom values
/// To allow custom values to be passed into attributes implement FromAnyValue on a type that can represent your custom value and specify the V generic to be that type. If you have many different custom values, it can be useful to use a enum type to represent the varients.
pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
pub(crate) tree: Tree,
pub(crate) world: World,
nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
pub(crate) dirty_nodes: NodesDirty<V>,
node_watchers: NodeWatchers<V>,
workload: ScheduledWorkload,
root_id: NodeId,
phantom: std::marker::PhantomData<V>,
}
impl<V: FromAnyValue + Send + Sync> RealDom<V> {
pub fn new(mut passes: Box<[TypeErasedPass<V>]>) -> RealDom<V> {
let mut tree = Tree::new();
let mut workload = Workload::new("Main Workload");
for pass in &mut *passes {
let system = pass.workload.take().unwrap();
workload = workload.with_system(system);
}
let workload = construct_workload(&mut passes);
let (workload, _) = workload.build().unwrap();
let root_id = tree.root();
let mut world = World::new();
let root_node: NodeType<V> = NodeType::Element(ElementNode {
tag: "Root".to_string(),
namespace: Some("Root".to_string()),
attributes: FxHashMap::default(),
listeners: FxHashSet::default(),
});
tree.insert(root_id, root_node);
let root_id = world.add_entity(root_node);
// resolve dependants for each pass
for i in 1..passes.len() {
@@ -122,7 +132,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
nodes_updated.insert(root_id, NodeMaskBuilder::ALL.build());
RealDom {
tree,
world,
nodes_listening: FxHashMap::default(),
dirty_nodes: NodesDirty {
passes_updated,
@@ -131,19 +141,27 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
},
node_watchers: Default::default(),
workload,
root_id,
phantom: std::marker::PhantomData,
}
}
pub fn tree_mut(&self) -> TreeMutView {
self.world.borrow().unwrap()
}
pub fn tree_ref(&self) -> TreeRefView {
self.world.borrow().unwrap()
}
pub fn create_node(&mut self, node: NodeType<V>) -> NodeMut<'_, V> {
let mut node_entry = self.tree.create_node();
let id = node_entry.id();
let id = self.world.add_entity(node);
self.tree_mut().create_node(id);
self.dirty_nodes
.passes_updated
.entry(id)
.or_default()
.extend(self.dirty_nodes.passes.iter().map(|x| x.this_type_id));
node_entry.insert(node);
let watchers = self.node_watchers.clone();
for watcher in &*watchers.read().unwrap() {
watcher.on_node_added(NodeMut::new(id, self));
@@ -157,7 +175,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
if let Some(nodes) = self.nodes_listening.get(event) {
let mut listening: Vec<_> = nodes
.iter()
.map(|id| (*id, self.tree.height(*id).unwrap()))
.map(|id| (*id, self.tree_ref().height(*id).unwrap()))
.collect();
listening.sort_by(|(_, h1), (_, h2)| h1.cmp(h2).reverse());
listening
@@ -171,26 +189,29 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
/// Returns the id of the root node.
pub fn root_id(&self) -> NodeId {
self.tree.root()
self.root_id
}
pub fn get(&self, id: NodeId) -> Option<NodeRef<'_, V>> {
self.tree.contains(id).then_some(NodeRef { id, dom: self })
self.tree_ref()
.contains(id)
.then_some(NodeRef { id, dom: self })
}
pub fn get_mut(&mut self, id: NodeId) -> Option<NodeMut<'_, V>> {
self.tree.contains(id).then(|| NodeMut::new(id, self))
let contains = { self.tree_ref().contains(id) };
contains.then(|| NodeMut::new(id, self))
}
fn borrow_raw<'a, B: IntoBorrow>(&'a self) -> Result<B, GetStorage>
where
B::Borrow: shipyard::Borrow<'a, View = B>,
{
self.tree.nodes.borrow()
self.world.borrow()
}
fn borrow_node_type_mut(&self) -> Result<ViewMut<NodeType<V>>, GetStorage> {
self.tree.nodes.borrow()
self.world.borrow()
}
/// 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.
@@ -202,34 +223,36 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
let nodes_updated = std::mem::take(&mut self.dirty_nodes.nodes_updated);
let dirty_nodes =
DirtyNodeStates::with_passes(self.dirty_nodes.passes.iter().map(|p| p.this_type_id));
let tree = self.tree_ref();
for (node_id, passes) in passes {
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if let Some(height) = self.tree.height(node_id) {
if let Some(height) = tree.height(node_id) {
for pass in passes {
dirty_nodes.insert(pass, node_id, height);
}
}
}
let _ = self.tree.remove_unique::<DirtyNodeStates>();
let _ = self.tree.remove_unique::<SendAnyMapWrapper>();
self.tree.add_unique(dirty_nodes);
self.tree.add_unique(SendAnyMapWrapper(ctx));
self.tree.add_unique(DirtyNodes::default());
let _ = self.world.remove_unique::<DirtyNodeStates>();
let _ = self.world.remove_unique::<SendAnyMapWrapper>();
self.world.add_unique(dirty_nodes);
self.world.add_unique(SendAnyMapWrapper(ctx));
self.world.add_unique(DirtyNodesResult::default());
self.workload.run_with_world(&self.tree.nodes).unwrap();
self.workload.run_with_world(&self.world).unwrap();
let dirty = self.tree.remove_unique::<DirtyNodes>().unwrap();
let dirty = self.world.remove_unique::<DirtyNodesResult>().unwrap();
(dirty.0, nodes_updated)
}
pub fn traverse_depth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
let mut stack = vec![self.root_id()];
let tree = self.tree_ref();
while let Some(id) = stack.pop() {
if let Some(node) = self.get(id) {
f(node);
if let Some(children) = self.tree.children_ids(id) {
if let Some(children) = tree.children_ids(id) {
stack.extend(children.iter().copied().rev());
}
}
@@ -239,10 +262,11 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
pub fn traverse_breadth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
let mut queue = VecDeque::new();
queue.push_back(self.root_id());
let tree = self.tree_ref();
while let Some(id) = queue.pop_front() {
if let Some(node) = self.get(id) {
f(node);
if let Some(children) = self.tree.children_ids(id) {
if let Some(children) = tree.children_ids(id) {
for id in children {
queue.push_back(id);
}
@@ -254,8 +278,10 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
pub fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
let mut stack = vec![self.root_id()];
while let Some(id) = stack.pop() {
if let Some(children) = self.tree.children_ids(id) {
let children = children.iter().copied().rev().collect::<Vec<_>>();
let tree = self.tree_ref();
if let Some(mut children) = tree.children_ids(id) {
drop(tree);
children.reverse();
if let Some(node) = self.get_mut(id) {
let node = node;
f(node);
@@ -269,8 +295,9 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
let mut queue = VecDeque::new();
queue.push_back(self.root_id());
while let Some(id) = queue.pop_front() {
if let Some(children) = self.tree.children_ids(id) {
let children = children.to_vec();
let tree = self.tree_ref();
if let Some(children) = tree.children_ids(id) {
drop(tree);
if let Some(node) = self.get_mut(id) {
f(node);
for id in children {
@@ -349,7 +376,7 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
#[inline]
fn child_ids(&self) -> Option<Vec<NodeId>> {
self.real_dom().tree.children_ids(self.id())
self.real_dom().tree_ref().children_ids(self.id())
}
#[inline]
@@ -368,7 +395,7 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
#[inline]
fn parent_id(&self) -> Option<NodeId> {
self.real_dom().tree.parent_id(self.id())
self.real_dom().tree_ref().parent_id(self.id())
}
#[inline]
@@ -382,7 +409,7 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
#[inline]
fn next(&self) -> Option<NodeRef<V>> {
let parent = self.parent_id()?;
let children = self.real_dom().tree.children_ids(parent)?;
let children = self.real_dom().tree_ref().children_ids(parent)?;
let index = children.iter().position(|id| *id == self.id())?;
if index + 1 < children.len() {
Some(NodeRef {
@@ -397,7 +424,7 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
#[inline]
fn prev(&self) -> Option<NodeRef<V>> {
let parent = self.parent_id()?;
let children = self.real_dom().tree.children_ids(parent)?;
let children = self.real_dom().tree_ref().children_ids(parent)?;
let index = children.iter().position(|id| *id == self.id())?;
if index > 0 {
Some(NodeRef {
@@ -411,7 +438,7 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
#[inline]
fn height(&self) -> u16 {
self.real_dom().tree.height(self.id()).unwrap()
self.real_dom().tree_ref().height(self.id()).unwrap()
}
}
@@ -501,13 +528,13 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
.entry(self.id)
.or_default()
.insert(TypeId::of::<T>());
self.dom.tree.insert(self.id, value);
self.dom.world.add_component(self.id, value);
}
#[inline]
pub fn next_mut(self) -> Option<NodeMut<'a, V>> {
let parent = self.parent_id()?;
let children = self.dom.tree.children_ids(parent)?;
let children = self.dom.tree_mut().children_ids(parent)?;
let index = children.iter().position(|id| *id == self.id)?;
if index + 1 < children.len() {
Some(NodeMut::new(children[index + 1], self.dom))
@@ -519,7 +546,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
#[inline]
pub fn prev_mut(self) -> Option<NodeMut<'a, V>> {
let parent = self.parent_id()?;
let children = self.dom.tree.children_ids(parent)?;
let children = self.dom.tree_ref().children_ids(parent)?;
let index = children.iter().position(|id| *id == self.id)?;
if index > 0 {
Some(NodeMut::new(children[index - 1], self.dom))
@@ -532,29 +559,31 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
pub fn add_child(&mut self, child: NodeId) {
self.dom.dirty_nodes.mark_child_changed(self.id);
self.dom.dirty_nodes.mark_parent_added_or_removed(child);
self.dom.tree.add_child(self.id, child);
self.dom.tree_mut().add_child(self.id, child);
NodeMut::new(child, self.dom).mark_moved();
}
#[inline]
pub fn insert_after(&mut self, old: NodeId) {
let id = self.id();
if let Some(parent_id) = self.dom.tree.parent_id(old) {
let parent_id = { self.dom.tree_ref().parent_id(old) };
if let Some(parent_id) = parent_id {
self.dom.dirty_nodes.mark_child_changed(parent_id);
self.dom.dirty_nodes.mark_parent_added_or_removed(id);
}
self.dom.tree.insert_after(old, id);
self.dom.tree_mut().insert_after(old, id);
self.mark_moved();
}
#[inline]
pub fn insert_before(&mut self, old: NodeId) {
let id = self.id();
if let Some(parent_id) = self.dom.tree.parent_id(old) {
let parent_id = { self.dom.tree_ref().parent_id(old) };
if let Some(parent_id) = parent_id {
self.dom.dirty_nodes.mark_child_changed(parent_id);
self.dom.dirty_nodes.mark_parent_added_or_removed(id);
}
self.dom.tree.insert_before(old, id);
self.dom.tree_mut().insert_before(old, id);
self.mark_moved();
}
@@ -563,11 +592,11 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
let id = self.id();
{
let RealDom {
tree,
world,
nodes_listening,
..
} = &mut self.dom;
let mut view: ViewMut<NodeType<V>> = tree.nodes.borrow().unwrap();
let mut view: ViewMut<NodeType<V>> = world.borrow().unwrap();
if let NodeType::Element(ElementNode { listeners, .. })
| NodeType::Text(TextNode { listeners, .. }) = (&mut view).get(id).unwrap()
{
@@ -578,7 +607,8 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
}
}
self.mark_removed();
if let Some(parent_id) = self.real_dom_mut().tree.parent_id(id) {
let parent_id = { self.dom.tree_ref().parent_id(id) };
if let Some(parent_id) = parent_id {
self.real_dom_mut()
.dirty_nodes
.mark_child_changed(parent_id);
@@ -589,7 +619,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
self.dom.get_mut(child).unwrap().remove();
}
}
self.dom.tree.remove_single(id);
self.dom.tree_mut().remove_single(id);
}
#[inline]
@@ -604,19 +634,19 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
.mark_parent_added_or_removed(new);
}
let id = self.id();
self.dom.tree.replace(id, new);
self.dom.tree_mut().replace(id, new);
}
#[inline]
pub fn add_event_listener(&mut self, event: &str) {
let id = self.id();
let RealDom {
tree,
world,
dirty_nodes,
nodes_listening,
..
} = &mut self.dom;
let mut view: ViewMut<NodeType<V>> = tree.nodes.borrow().unwrap();
let mut view: ViewMut<NodeType<V>> = world.borrow().unwrap();
let node_type: &mut NodeType<V> = (&mut view).get(self.id).unwrap();
if let NodeType::Element(ElementNode { listeners, .. })
| NodeType::Text(TextNode { listeners, .. }) = node_type
@@ -640,12 +670,12 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
pub fn remove_event_listener(&mut self, event: &str) {
let id = self.id();
let RealDom {
tree,
world,
dirty_nodes,
nodes_listening,
..
} = &mut self.dom;
let mut view: ViewMut<NodeType<V>> = tree.nodes.borrow().unwrap();
let mut view: ViewMut<NodeType<V>> = world.borrow().unwrap();
let node_type: &mut NodeType<V> = (&mut view).get(self.id).unwrap();
if let NodeType::Element(ElementNode { listeners, .. })
| NodeType::Text(TextNode { listeners, .. }) = node_type
@@ -674,9 +704,9 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
let id = self.id();
let RealDom {
tree, dirty_nodes, ..
world, dirty_nodes, ..
} = &mut self.dom;
let view: ViewMut<NodeType<V>> = tree.nodes.borrow().unwrap();
let view: ViewMut<NodeType<V>> = world.borrow().unwrap();
let node_type = ViewEntryMut::new(view, id);
match &*node_type {
NodeType::Element(_) => NodeTypeMut::Element(ElementNodeMut {
@@ -857,3 +887,37 @@ impl<V: FromAnyValue + Send + Sync> ElementNodeMut<'_, V> {
&self.element().listeners
}
}
fn construct_workload<V: FromAnyValue + Send + Sync>(passes: &mut [TypeErasedPass<V>]) -> Workload {
let mut workload = Workload::new("Main Workload");
let mut unresloved_workloads = passes
.iter_mut()
.enumerate()
.map(|(i, pass)| {
let workload = Some((pass.workload)(pass.dependants.clone()));
(i, pass, workload)
})
.collect::<Vec<_>>();
// set all the labels
for (id, _, workload) in &mut unresloved_workloads {
*workload = Some(workload.take().unwrap().tag(id.to_string()));
}
// mark any dependancies
for i in 0..unresloved_workloads.len() {
let (_, pass, _) = &unresloved_workloads[i];
for ty_id in pass.combined_dependancy_type_ids.clone() {
let &(dependancy_id, _, _) = unresloved_workloads
.iter()
.find(|(_, pass, _)| pass.this_type_id == ty_id)
.unwrap();
let (_, _, workload) = &mut unresloved_workloads[i];
*workload = workload
.take()
.map(|workload| workload.tag(dependancy_id.to_string()));
}
}
for (_, _, mut workload_system) in unresloved_workloads {
workload = workload.with_system(workload_system.take().unwrap());
}
workload
}
+69 -89
View File
@@ -1,63 +1,65 @@
use crate::NodeId;
use shipyard::{Component, EntitiesView, EntityId, Get, Unique, View, ViewMut, World};
use shipyard::{Component, EntitiesViewMut, Get, View, ViewMut};
use std::fmt::Debug;
#[derive(PartialEq, Eq, Clone, Debug, Component)]
pub(crate) struct Node {
pub struct Node {
parent: Option<NodeId>,
children: Vec<NodeId>,
height: u16,
}
#[derive(Debug)]
pub(crate) struct Tree {
pub(crate) nodes: World,
root: NodeId,
pub type TreeRefView<'a> = View<'a, Node>;
pub type TreeMutView<'a> = (EntitiesViewMut<'a>, ViewMut<'a, Node>);
pub trait TreeRef {
fn parent_id(&self, id: NodeId) -> Option<NodeId>;
fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>>;
fn height(&self, id: NodeId) -> Option<u16>;
fn contains(&self, id: NodeId) -> bool;
}
impl Tree {
pub fn new() -> Self {
let mut nodes = World::default();
let node = Node {
parent: None,
children: Vec::new(),
height: 0,
};
let root = nodes.add_entity((node,));
Self { nodes, root }
pub trait TreeMut: TreeRef {
fn remove(&mut self, id: NodeId);
fn remove_single(&mut self, id: NodeId);
fn set_height(&mut self, node: NodeId, height: u16);
fn create_node(&mut self, id: NodeId);
fn add_child(&mut self, parent: NodeId, new: NodeId);
fn replace(&mut self, old_id: NodeId, new_id: NodeId);
fn insert_before(&mut self, old_id: NodeId, new_id: NodeId);
fn insert_after(&mut self, old_id: NodeId, new_id: NodeId);
}
impl<'a> TreeRef for TreeRefView<'a> {
fn parent_id(&self, id: NodeId) -> Option<NodeId> {
self.get(id).unwrap().parent
}
pub fn add_unique<T: Unique + Send + Sync>(&mut self, data: T) {
self.nodes.add_unique(data);
fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> {
Some(self.get(id).unwrap().children.clone())
}
pub fn remove_unique<T: Unique + Send + Sync>(
&mut self,
) -> Result<T, shipyard::error::UniqueRemove> {
self.nodes.remove_unique::<T>()
fn height(&self, id: NodeId) -> Option<u16> {
Some(self.get(id).unwrap().height)
}
fn node_data(&self) -> View<Node> {
self.nodes.borrow().unwrap()
fn contains(&self, id: NodeId) -> bool {
self.get(id).is_ok()
}
}
fn node_data_mut(&self) -> ViewMut<Node> {
self.nodes.borrow().unwrap()
}
pub fn remove(&mut self, id: NodeId) {
fn recurse(tree: &mut Tree, id: NodeId) {
impl<'a> TreeMut for TreeMutView<'a> {
fn remove(&mut self, id: NodeId) {
fn recurse<'a>(tree: &mut TreeMutView<'a>, id: NodeId) {
let children = tree.children_ids(id);
if let Some(children) = children {
for child in children {
recurse(tree, child);
}
}
tree.nodes.delete_entity(id);
}
{
let mut node_data_mut = self.node_data_mut();
let mut node_data_mut = &mut self.1;
if let Some(parent) = node_data_mut.get(id).unwrap().parent {
let parent = (&mut node_data_mut).get(parent).unwrap();
parent.children.retain(|&child| child != id);
@@ -67,21 +69,19 @@ impl Tree {
recurse(self, id);
}
pub fn remove_single(&mut self, id: NodeId) {
fn remove_single(&mut self, id: NodeId) {
{
let mut node_data_mut = self.node_data_mut();
let mut node_data_mut = &mut self.1;
if let Some(parent) = node_data_mut.get(id).unwrap().parent {
let parent = (&mut node_data_mut).get(parent).unwrap();
parent.children.retain(|&child| child != id);
}
}
self.nodes.delete_entity(id);
}
fn set_height(&mut self, node: NodeId, height: u16) {
let children = {
let mut node_data_mut = self.node_data_mut();
let mut node_data_mut = &mut self.1;
let mut node = (&mut node_data_mut).get(node).unwrap();
node.height = height;
node.children.clone()
@@ -91,19 +91,23 @@ impl Tree {
}
}
pub fn create_node(&mut self) -> NodeBuilder<'_> {
let node = self.nodes.add_entity((Node {
parent: None,
children: Vec::new(),
height: 0,
},));
NodeBuilder { tree: self, node }
fn create_node(&mut self, id: NodeId) {
let (entities, node_data_mut) = self;
entities.add_component(
id,
node_data_mut,
Node {
parent: None,
children: Vec::new(),
height: 0,
},
);
}
pub fn add_child(&mut self, parent: NodeId, new: NodeId) {
fn add_child(&mut self, parent: NodeId, new: NodeId) {
let height;
{
let mut node_state = self.node_data_mut();
let mut node_state = &mut self.1;
(&mut node_state).get(new).unwrap().parent = Some(parent);
let parent = (&mut node_state).get(parent).unwrap();
parent.children.push(new);
@@ -112,9 +116,9 @@ impl Tree {
self.set_height(new, height);
}
pub fn replace(&mut self, old_id: NodeId, new_id: NodeId) {
fn replace(&mut self, old_id: NodeId, new_id: NodeId) {
{
let mut node_state = self.node_data_mut();
let mut node_state = &mut self.1;
// update the parent's link to the child
if let Some(parent_id) = node_state.get(old_id).unwrap().parent {
let parent = (&mut node_state).get(parent_id).unwrap();
@@ -125,7 +129,6 @@ impl Tree {
}
}
let height = parent.height + 1;
drop(node_state);
self.set_height(new_id, height);
}
}
@@ -133,8 +136,8 @@ impl Tree {
self.remove(old_id);
}
pub fn insert_before(&mut self, old_id: NodeId, new_id: NodeId) {
let mut node_state = self.node_data_mut();
fn insert_before(&mut self, old_id: NodeId, new_id: NodeId) {
let mut node_state = &mut self.1;
let old_node = node_state.get(old_id).unwrap();
let parent_id = old_node.parent.expect("tried to insert before root");
(&mut node_state).get(new_id).unwrap().parent = Some(parent_id);
@@ -146,12 +149,11 @@ impl Tree {
.unwrap();
parent.children.insert(index, new_id);
let height = parent.height + 1;
drop(node_state);
self.set_height(new_id, height);
}
pub fn insert_after(&mut self, old_id: NodeId, new_id: NodeId) {
let mut node_state = self.node_data_mut();
fn insert_after(&mut self, old_id: NodeId, new_id: NodeId) {
let mut node_state = &mut self.1;
let old_node = node_state.get(old_id).unwrap();
let parent_id = old_node.parent.expect("tried to insert before root");
(&mut node_state).get(new_id).unwrap().parent = Some(parent_id);
@@ -163,36 +165,29 @@ impl Tree {
.unwrap();
parent.children.insert(index + 1, new_id);
let height = parent.height + 1;
drop(node_state);
self.set_height(new_id, height);
}
}
pub fn insert<T: Component + Sync + Send>(&mut self, id: NodeId, value: T) {
self.nodes.add_component(id, value);
}
pub fn contains(&self, id: NodeId) -> bool {
self.nodes.borrow::<EntitiesView>().unwrap().is_alive(id)
}
pub fn root(&self) -> NodeId {
self.root
}
pub fn parent_id(&self, id: NodeId) -> Option<NodeId> {
let node_data = self.node_data();
impl<'a> TreeRef for TreeMutView<'a> {
fn parent_id(&self, id: NodeId) -> Option<NodeId> {
let node_data = &self.1;
node_data.get(id).unwrap().parent
}
pub fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> {
let node_data = self.node_data();
fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> {
let node_data = &self.1;
node_data.get(id).map(|node| node.children.clone()).ok()
}
pub fn height(&self, id: NodeId) -> Option<u16> {
let node_data = self.node_data();
fn height(&self, id: NodeId) -> Option<u16> {
let node_data = &self.1;
node_data.get(id).map(|node| node.height).ok()
}
fn contains(&self, id: NodeId) -> bool {
self.1.get(id).is_ok()
}
}
#[test]
@@ -326,18 +321,3 @@ fn deletion() {
assert_eq!(*tree.get::<i32>(parent).unwrap(), 0);
assert_eq!(tree.get::<i32>(after), None);
}
pub struct NodeBuilder<'a> {
tree: &'a mut Tree,
node: EntityId,
}
impl<'a> NodeBuilder<'a> {
pub fn insert<T: Component + Send + Sync>(&mut self, component: T) {
self.tree.insert(self.node, component);
}
pub fn id(&self) -> EntityId {
self.node
}
}