make the real dom generic over custom types

This commit is contained in:
Evan Almloff committed 2023-01-03 12:35:48 -06:00
1 parent dde4fb31b2
commit bf20b66b38
5 files changed
+99 -44

No files matched your search

+3 -3
View File
@@ -5,7 +5,7 @@ use std::fmt::Debug;
/// The node is stored client side and stores only basic data about the node.
#[derive(Debug, Clone)]
pub struct Node<S: State, V: FromAnyValue = ()> {
pub struct Node<S: State<V>, V: FromAnyValue + 'static = ()> {
/// The transformed state of the node.
pub state: S,
/// The raw data for the node
@@ -37,7 +37,7 @@ pub enum NodeType<V: FromAnyValue = ()> {
Placeholder,
}
impl<S: State, V: FromAnyValue> Node<S, V> {
impl<S: State<V>, V: FromAnyValue> Node<S, V> {
pub(crate) fn new(node_type: NodeType<V>) -> Self {
Node {
state: S::default(),
@@ -83,7 +83,7 @@ pub enum OwnedAttributeValue<V: FromAnyValue = ()> {
None,
}
pub trait FromAnyValue {
pub trait FromAnyValue: Clone {
fn from_any_value(value: &dyn AnyValue) -> Self;
}
+22 -19
View File
@@ -3,7 +3,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
use std::fmt::Debug;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use crate::node::{Node, NodeType, OwnedAttributeDiscription, OwnedAttributeValue};
use crate::node::{FromAnyValue, Node, NodeType, OwnedAttributeDiscription, OwnedAttributeValue};
use crate::node_ref::{AttributeMask, NodeMask};
use crate::passes::DirtyNodeStates;
use crate::state::State;
@@ -25,9 +25,12 @@ fn mark_dirty(
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
/// The render state passes from parent to children and or accumulates state from children to parents.
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
///
/// # 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.
#[derive(Debug)]
pub struct RealDom<S: State> {
pub tree: Tree<Node<S>>,
pub struct RealDom<S: State<V>, V: FromAnyValue + 'static = ()> {
pub tree: Tree<Node<S, V>>,
/// a map from element id to real node id
node_id_mapping: Vec<Option<RealNodeId>>,
nodes_listening: FxHashMap<String, FxHashSet<RealNodeId>>,
@@ -36,14 +39,14 @@ pub struct RealDom<S: State> {
root_initialized: bool,
}
impl<S: State> Default for RealDom<S> {
impl<S: State<V>, V: FromAnyValue> Default for RealDom<S, V> {
fn default() -> Self {
Self::new()
}
}
impl<S: State> RealDom<S> {
pub fn new() -> RealDom<S> {
impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
pub fn new() -> RealDom<S, V> {
let mut root = Node::new(NodeType::Element {
tag: "Root".to_string(),
namespace: Some("Root".to_string()),
@@ -91,7 +94,7 @@ impl<S: State> RealDom<S> {
current
}
fn create_node(&mut self, node: Node<S>) -> RealNodeId {
fn create_node(&mut self, node: Node<S, V>) -> 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;
@@ -349,7 +352,7 @@ impl<S: State> RealDom<S> {
/// 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<S>> {
pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node<S, V>> {
if let Some(nodes) = self.nodes_listening.get(event) {
let mut listening: Vec<_> = nodes.iter().map(|id| &self[*id]).collect();
listening.sort_by(|n1, n2| {
@@ -396,9 +399,9 @@ impl<S: State> RealDom<S> {
}
}
impl<S: State + Sync> RealDom<S>
impl<S: State<V> + Sync, V: FromAnyValue> RealDom<S, V>
where
Tree<Node<S>>: Sync + Send,
Tree<Node<S, V>>: Sync + Send,
{
/// 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.
/// This will resolve the state in parallel
@@ -411,43 +414,43 @@ where
}
}
impl<S: State> Deref for RealDom<S> {
type Target = Tree<Node<S>>;
impl<S: State<V>, V: FromAnyValue> Deref for RealDom<S, V> {
type Target = Tree<Node<S, V>>;
fn deref(&self) -> &Self::Target {
&self.tree
}
}
impl<S: State> DerefMut for RealDom<S> {
impl<S: State<V>, V: FromAnyValue> DerefMut for RealDom<S, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.tree
}
}
impl<S: State> Index<ElementId> for RealDom<S> {
type Output = Node<S>;
impl<S: State<V>, V: FromAnyValue> Index<ElementId> for RealDom<S, V> {
type Output = Node<S, V>;
fn index(&self, id: ElementId) -> &Self::Output {
self.tree.get(self.element_to_node_id(id)).unwrap()
}
}
impl<S: State> Index<RealNodeId> for RealDom<S> {
type Output = Node<S>;
impl<S: State<V>, V: FromAnyValue> Index<RealNodeId> for RealDom<S, V> {
type Output = Node<S, V>;
fn index(&self, idx: RealNodeId) -> &Self::Output {
self.tree.get(idx).unwrap()
}
}
impl<S: State> IndexMut<ElementId> for RealDom<S> {
impl<S: State<V>, V: FromAnyValue> IndexMut<ElementId> for RealDom<S, V> {
fn index_mut(&mut self, id: ElementId) -> &mut Self::Output {
self.tree.get_mut(self.element_to_node_id(id)).unwrap()
}
}
impl<S: State> IndexMut<RealNodeId> for RealDom<S> {
impl<S: State<V>, V: FromAnyValue> IndexMut<RealNodeId> for RealDom<S, V> {
fn index_mut(&mut self, idx: RealNodeId) -> &mut Self::Output {
self.tree.get_mut(idx).unwrap()
}
+4 -4
View File
@@ -210,14 +210,14 @@ pub trait NodeDepState<V: FromAnyValue = ()> {
}
/// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
pub trait State: Default + Clone + 'static {
pub trait State<V: FromAnyValue + 'static>: Default + Clone + 'static {
#[doc(hidden)]
const PASSES: &'static [AnyPass<Node<Self>>];
const PASSES: &'static [AnyPass<Node<Self, V>>];
#[doc(hidden)]
const MASKS: &'static [NodeMask];
#[doc(hidden)]
fn update<T: TreeView<Node<Self>> + Sync + Send>(
fn update<T: TreeView<Node<Self, V>> + Sync + Send>(
dirty: DirtyNodeStates,
tree: &mut T,
ctx: SendAnyMap,
@@ -227,7 +227,7 @@ pub trait State: Default + Clone + 'static {
}
#[doc(hidden)]
fn update_single_threaded<T: TreeView<Node<Self>>>(
fn update_single_threaded<T: TreeView<Node<Self, V>>>(
dirty: DirtyNodeStates,
tree: &mut T,
ctx: SendAnyMap,
@@ -1,4 +1,10 @@
use crate::{node::NodeType, real_dom::RealDom, state::State, tree::TreeView, NodeId, RealNodeId};
use crate::{
node::{FromAnyValue, NodeType},
real_dom::RealDom,
state::State,
tree::TreeView,
NodeId, RealNodeId,
};
use dioxus_core::{Mutation, Mutations};
use std::fmt::Debug;
@@ -67,7 +73,11 @@ impl PersistantElementIter {
/// remove stale element refreneces
/// returns true if the focused element is removed
pub fn prune<S: State>(&mut self, mutations: &Mutations, rdom: &RealDom<S>) -> bool {
pub fn prune<S: State<V>, V: FromAnyValue>(
&mut self,
mutations: &Mutations,
rdom: &RealDom<S, V>,
) -> bool {
let mut changed = false;
let ids_removed: Vec<_> = mutations
.edits
@@ -124,7 +134,7 @@ impl PersistantElementIter {
}
/// get the next element
pub fn next<S: State>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
pub fn next<S: State<V>, V: FromAnyValue>(&mut self, rdom: &RealDom<S, V>) -> ElementProduced {
if self.stack.is_empty() {
let id = NodeId(0);
let new = (id, NodePosition::AtNode);
@@ -160,12 +170,12 @@ impl PersistantElementIter {
}
/// get the previous element
pub fn prev<S: State>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
pub fn prev<S: State<V>, V: FromAnyValue>(&mut self, rdom: &RealDom<S, V>) -> ElementProduced {
// recursively add the last child element to the stack
fn push_back<S: State>(
fn push_back<S: State<V>, V: FromAnyValue>(
stack: &mut smallvec::SmallVec<[(RealNodeId, NodePosition); 5]>,
new_node: RealNodeId,
rdom: &RealDom<S>,
rdom: &RealDom<S, V>,
) -> RealNodeId {
match &rdom[new_node].node_data.node_type {
NodeType::Element { .. } => {
@@ -228,7 +238,7 @@ impl PersistantElementIter {
#[derive(Default, Clone, Debug)]
struct Empty {}
impl State for Empty {
impl State<()> for Empty {
const PASSES: &'static [crate::AnyPass<crate::node::Node<Self, ()>>] = &[];
const MASKS: &'static [crate::NodeMask] = &[];