add node dependancy

This commit is contained in:
Evan Almloff committed 2022-04-16 12:27:52 -05:00
1 parent 0fb9aed273
commit 436c6a02f7
18 files changed
+1312 -575

No files matched your search

+71 -223
View File
@@ -1,7 +1,9 @@
use std::{any::TypeId, fmt::Debug};
use std::fmt::Debug;
use anymap::AnyMap;
use dioxus_core::{Attribute, ElementId, VElement, VNode, VText, VirtualDom};
use dioxus_core::VNode;
use crate::node_ref::{NodeMask, NodeView};
pub(crate) fn union_ordered_iter<T: Ord + Debug>(
s_iter: impl Iterator<Item = T>,
@@ -34,215 +36,6 @@ pub(crate) fn union_ordered_iter<T: Ord + Debug>(
v
}
#[derive(Debug)]
pub struct NodeView<'a> {
inner: &'a VNode<'a>,
mask: NodeMask,
}
impl<'a> NodeView<'a> {
pub fn new(mut vnode: &'a VNode<'a>, view: NodeMask, vdom: &'a VirtualDom) -> Self {
if let VNode::Component(sc) = vnode {
let scope = vdom.get_scope(sc.scope.get().unwrap()).unwrap();
vnode = scope.root_node();
}
Self {
inner: vnode,
mask: view,
}
}
pub fn id(&self) -> ElementId {
self.inner.mounted_id()
}
pub fn tag(&self) -> Option<&'a str> {
self.mask.tag.then(|| self.el().map(|el| el.tag)).flatten()
}
pub fn namespace(&self) -> Option<&'a str> {
self.mask
.namespace
.then(|| self.el().map(|el| el.namespace).flatten())
.flatten()
}
pub fn attributes(&self) -> impl Iterator<Item = &Attribute<'a>> {
self.el()
.map(|el| el.attributes)
.unwrap_or_default()
.iter()
.filter(|a| self.mask.attritutes.contains_attribute(&a.name))
}
pub fn text(&self) -> Option<&str> {
self.mask
.text
.then(|| self.txt().map(|txt| txt.text))
.flatten()
}
fn el(&self) -> Option<&'a VElement<'a>> {
if let VNode::Element(el) = &self.inner {
Some(el)
} else {
None
}
}
fn txt(&self) -> Option<&'a VText<'a>> {
if let VNode::Text(txt) = &self.inner {
Some(txt)
} else {
None
}
}
}
#[derive(PartialEq, Clone, Debug)]
pub enum AttributeMask {
All,
Dynamic(Vec<&'static str>),
Static(&'static [&'static str]),
}
impl AttributeMask {
pub const NONE: Self = Self::Static(&[]);
fn contains_attribute(&self, attr: &'static str) -> bool {
match self {
AttributeMask::All => true,
AttributeMask::Dynamic(l) => l.binary_search(&attr).is_ok(),
AttributeMask::Static(l) => l.binary_search(&attr).is_ok(),
}
}
pub fn single(new: &'static str) -> Self {
Self::Dynamic(vec![new])
}
pub fn verify(&self) {
match &self {
AttributeMask::Static(attrs) => debug_assert!(
attrs.windows(2).all(|w| w[0] < w[1]),
"attritutes must be increasing"
),
AttributeMask::Dynamic(attrs) => debug_assert!(
attrs.windows(2).all(|w| w[0] < w[1]),
"attritutes must be increasing"
),
_ => (),
}
}
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::Static(s), AttributeMask::Static(o)) => AttributeMask::Dynamic(
union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
),
_ => AttributeMask::All,
};
new.verify();
new
}
fn overlaps(&self, other: &Self) -> bool {
fn overlaps_iter(
mut self_iter: impl Iterator<Item = &'static str>,
mut other_iter: impl Iterator<Item = &'static str>,
) -> bool {
if let Some(mut other_attr) = other_iter.next() {
while let Some(self_attr) = self_iter.next() {
while other_attr < self_attr {
if let Some(attr) = other_iter.next() {
other_attr = attr;
} else {
return false;
}
}
if other_attr == self_attr {
return true;
}
}
}
false
}
match (self, other) {
(AttributeMask::All, AttributeMask::All) => true,
(AttributeMask::All, AttributeMask::Dynamic(v)) => !v.is_empty(),
(AttributeMask::All, AttributeMask::Static(s)) => !s.is_empty(),
(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())
}
(AttributeMask::Dynamic(v), AttributeMask::Static(s)) => {
overlaps_iter(v.iter().copied(), s.iter().copied())
}
(AttributeMask::Static(s), AttributeMask::Dynamic(v)) => {
overlaps_iter(v.iter().copied(), s.iter().copied())
}
(AttributeMask::Static(s1), AttributeMask::Static(s2)) => {
overlaps_iter(s1.iter().copied(), s2.iter().copied())
}
}
}
}
impl Default for AttributeMask {
fn default() -> Self {
AttributeMask::Static(&[])
}
}
#[derive(Default, PartialEq, Clone, Debug)]
pub struct NodeMask {
// must be sorted
attritutes: AttributeMask,
tag: bool,
namespace: bool,
text: bool,
}
impl NodeMask {
pub const NONE: Self = Self::new(AttributeMask::Static(&[]), false, false, false);
pub const ALL: Self = Self::new(AttributeMask::All, true, true, true);
/// attritutes must be sorted!
pub const fn new(attritutes: AttributeMask, tag: bool, namespace: bool, text: bool) -> Self {
Self {
attritutes,
tag,
namespace,
text,
}
}
pub fn overlaps(&self, other: &Self) -> bool {
(self.tag && other.tag)
|| (self.namespace && other.namespace)
|| self.attritutes.overlaps(&other.attritutes)
|| (self.text && other.text)
}
pub fn union(&self, other: &Self) -> Self {
Self {
attritutes: self.attritutes.union(&other.attritutes),
tag: self.tag | other.tag,
namespace: self.namespace | other.namespace,
text: self.text | other.text,
}
}
}
/// This state is derived from children. For example a node's size could be derived from the size of children.
/// Called when the current node's node properties are modified, a child's [BubbledUpState] is modified or a child is removed.
/// Called at most once per update.
@@ -250,7 +43,8 @@ pub trait ChildDepState {
/// The context is passed to the [PushedDownState::reduce] when it is pushed down.
/// This is sometimes nessisary for lifetime purposes.
type Ctx;
type DepState: ChildDepState;
/// This must be either a [ChildDepState] or [NodeDepState]
type DepState;
const NODE_MASK: NodeMask = NodeMask::NONE;
fn reduce<'a>(
&mut self,
@@ -269,7 +63,8 @@ pub trait ParentDepState {
/// The context is passed to the [PushedDownState::reduce] when it is pushed down.
/// This is sometimes nessisary for lifetime purposes.
type Ctx;
type DepState: ParentDepState;
/// This must be either a [ParentDepState] or [NodeDepState]
type DepState;
const NODE_MASK: NodeMask = NodeMask::NONE;
fn reduce(&mut self, node: NodeView, parent: Option<&Self::DepState>, ctx: &Self::Ctx) -> bool;
}
@@ -279,40 +74,93 @@ pub trait ParentDepState {
/// Called at most once per update.
pub trait NodeDepState {
type Ctx;
type DepState: NodeDepState;
const NODE_MASK: NodeMask = NodeMask::NONE;
fn reduce(&mut self, node: NodeView, ctx: &Self::Ctx) -> bool;
fn reduce(&mut self, node: NodeView, sibling: &Self::DepState, ctx: &Self::Ctx) -> bool;
}
#[derive(Debug)]
pub struct ChildStatesChanged {
pub node_dep: &'static [MemberId],
pub child_dep: &'static [MemberId],
}
#[derive(Debug)]
pub struct ParentStatesChanged {
pub node_dep: &'static [MemberId],
pub parent_dep: &'static [MemberId],
}
#[derive(Debug)]
pub struct NodeStatesChanged {
pub node_dep: &'static [MemberId],
}
pub trait State: Default + Clone {
fn update_node_dep_state<'a>(
&'a mut self,
ty: TypeId,
ty: MemberId,
node: &'a VNode<'a>,
vdom: &'a dioxus_core::VirtualDom,
ctx: &AnyMap,
) -> bool;
) -> Option<NodeStatesChanged>;
/// This must be a valid resolution order. (no nodes updated before a state they rely on)
fn child_dep_types(&self, mask: &NodeMask) -> Vec<TypeId>;
fn child_dep_types(&self, mask: &NodeMask) -> Vec<MemberId>;
fn update_parent_dep_state<'a>(
&'a mut self,
ty: TypeId,
ty: MemberId,
node: &'a VNode<'a>,
vdom: &'a dioxus_core::VirtualDom,
parent: Option<&Self>,
ctx: &AnyMap,
) -> bool;
) -> Option<ParentStatesChanged>;
/// This must be a valid resolution order. (no nodes updated before a state they rely on)
fn parent_dep_types(&self, mask: &NodeMask) -> Vec<TypeId>;
fn parent_dep_types(&self, mask: &NodeMask) -> Vec<MemberId>;
fn update_child_dep_state<'a>(
&'a mut self,
ty: TypeId,
ty: MemberId,
node: &'a VNode<'a>,
vdom: &'a dioxus_core::VirtualDom,
children: &[&Self],
ctx: &AnyMap,
) -> bool;
) -> Option<ChildStatesChanged>;
/// This must be a valid resolution order. (no nodes updated before a state they rely on)
fn node_dep_types(&self, mask: &NodeMask) -> Vec<TypeId>;
fn node_dep_types(&self, mask: &NodeMask) -> Vec<MemberId>;
}
impl ChildDepState for () {
type Ctx = ();
type DepState = ();
fn reduce<'a>(
&mut self,
_: NodeView,
_: impl Iterator<Item = &'a Self::DepState>,
_: &Self::Ctx,
) -> bool
where
Self::DepState: 'a,
{
false
}
}
impl ParentDepState for () {
type Ctx = ();
type DepState = ();
fn reduce(&mut self, _: NodeView, _: Option<&Self::DepState>, _: &Self::Ctx) -> bool {
false
}
}
impl NodeDepState for () {
type Ctx = ();
type DepState = ();
fn reduce(&mut self, _: NodeView, _sibling: &Self::DepState, _: &Self::Ctx) -> bool {
false
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct MemberId(pub usize);