use fxhash::FxHashMap; use crate::innerlude::{VNode, VText}; /// A Patch encodes an operation that modifies a real DOM element. /// /// To update the real DOM that a user sees you'll want to first diff your /// old virtual dom and new virtual dom. /// /// This diff operation will generate `Vec` with zero or more patches that, when /// applied to your real DOM, will make your real DOM look like your new virtual dom. /// /// Each Patch has a u32 node index that helps us identify the real DOM node that it applies to. /// /// Our old virtual dom's nodes are indexed depth first, as shown in this illustration /// (0 being the root node, 1 being it's first child, 2 being it's first child's first child). /// /// ```text /// .─. /// ( 0 ) /// `┬' /// ┌────┴──────┐ /// │ │ /// ▼ ▼ /// .─. .─. /// ( 1 ) ( 4 ) /// `┬' `─' /// ┌────┴───┐ ├─────┬─────┐ /// │ │ │ │ │ /// ▼ ▼ ▼ ▼ ▼ /// .─. .─. .─. .─. .─. /// ( 2 ) ( 3 ) ( 5 ) ( 6 ) ( 7 ) /// `─' `─' `─' `─' `─' /// ``` /// /// The patching process is tested in a real browser in crates/virtual-dom-rs/tests/diff_patch.rs // #[derive(serde::Serialize, serde::Deserialize)] pub enum Patch<'a> { /// Append a vector of child nodes to a parent node id. AppendChildren(NodeIdx, Vec<&'a VNode<'a>>), /// For a `node_i32`, remove all children besides the first `len` TruncateChildren(NodeIdx, usize), /// Replace a node with another node. This typically happens when a node's tag changes. /// ex:
becomes Replace(NodeIdx, &'a VNode<'a>), /// Add attributes that the new node has that the old node does not AddAttributes(NodeIdx, FxHashMap<&'a str, &'a str>), /// Remove attributes that the old node had that the new node doesn't RemoveAttributes(NodeIdx, Vec<&'a str>), /// Change the text of a Text node. ChangeText(NodeIdx, &'a VText<'a>), } type NodeIdx = usize; impl<'a> Patch<'a> { /// Every Patch is meant to be applied to a specific node within the DOM. Get the /// index of the DOM node that this patch should apply to. DOM nodes are indexed /// depth first with the root node in the tree having index 0. pub fn node_idx(&self) -> usize { match self { Patch::AppendChildren(node_idx, _) => *node_idx, Patch::TruncateChildren(node_idx, _) => *node_idx, Patch::Replace(node_idx, _) => *node_idx, Patch::AddAttributes(node_idx, _) => *node_idx, Patch::RemoveAttributes(node_idx, _) => *node_idx, Patch::ChangeText(node_idx, _) => *node_idx, } } } pub struct PatchList<'a> { patches: Vec>, }