use std::collections::{HashMap, HashSet};
pub use apply_patches::patch;
use crate::event::{EventHandler, EventName};
use crate::{AttributeValue, VText, VirtualNode};
mod apply_patches;
type BreadthFirstNodeIdx = u32;
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
pub enum Patch<'a> {
#[allow(missing_docs)]
AppendChildren {
parent_old_node_idx: BreadthFirstNodeIdx,
new_nodes: Vec<&'a VirtualNode>,
},
#[allow(missing_docs)]
MoveToEndOfSiblings {
parent_old_node_idx: BreadthFirstNodeIdx,
siblings_to_move: Vec<BreadthFirstNodeIdx>,
},
RemoveChildren {
parent_old_node_idx: BreadthFirstNodeIdx,
to_remove: Vec<BreadthFirstNodeIdx>,
},
#[allow(missing_docs)]
Replace {
old_idx: BreadthFirstNodeIdx,
new_node: &'a VirtualNode,
},
#[allow(missing_docs)]
InsertBefore {
anchor_old_node_idx: BreadthFirstNodeIdx,
new_nodes: Vec<&'a VirtualNode>,
},
#[allow(missing_docs)]
MoveNodesBefore {
anchor_old_node_idx: BreadthFirstNodeIdx,
to_move: Vec<BreadthFirstNodeIdx>,
},
ValueAttributeUnchanged(BreadthFirstNodeIdx, &'a AttributeValue),
CheckedAttributeUnchanged(BreadthFirstNodeIdx, &'a AttributeValue),
AddAttributes(BreadthFirstNodeIdx, HashMap<&'a str, &'a AttributeValue>),
RemoveAttributes(BreadthFirstNodeIdx, Vec<&'a str>),
ChangeText(BreadthFirstNodeIdx, &'a VText),
SpecialAttribute(PatchSpecialAttribute<'a>),
AddEvents(
BreadthFirstNodeIdx,
HashMap<&'a EventName, &'a EventHandler>,
),
RemoveEvents(BreadthFirstNodeIdx, Vec<(&'a EventName, &'a EventHandler)>),
RemoveAllVirtualEventsWithNodeIdx(BreadthFirstNodeIdx),
}
#[derive(Debug, PartialEq)]
pub enum PatchSpecialAttribute<'a> {
CallOnCreateElemOnExistingNode(BreadthFirstNodeIdx, &'a VirtualNode),
CallOnRemoveElem(BreadthFirstNodeIdx, &'a VirtualNode),
SetDangerousInnerHtml(BreadthFirstNodeIdx, &'a VirtualNode),
RemoveDangerousInnerHtml(BreadthFirstNodeIdx),
}
impl<'a> Patch<'a> {
pub(crate) fn old_node_idx(&self) -> BreadthFirstNodeIdx {
match self {
Patch::AppendChildren {
parent_old_node_idx: old_idx,
..
} => *old_idx,
Patch::Replace { old_idx, .. } => *old_idx,
Patch::AddAttributes(node_idx, _) => *node_idx,
Patch::RemoveAttributes(node_idx, _) => *node_idx,
Patch::ChangeText(node_idx, _) => *node_idx,
Patch::ValueAttributeUnchanged(node_idx, _) => *node_idx,
Patch::CheckedAttributeUnchanged(node_idx, _) => *node_idx,
Patch::SpecialAttribute(special) => match special {
PatchSpecialAttribute::CallOnCreateElemOnExistingNode(node_idx, _) => *node_idx,
PatchSpecialAttribute::SetDangerousInnerHtml(node_idx, _) => *node_idx,
PatchSpecialAttribute::RemoveDangerousInnerHtml(node_idx) => *node_idx,
PatchSpecialAttribute::CallOnRemoveElem(node_idx, _) => *node_idx,
},
Patch::RemoveEvents(node_idx, _) => *node_idx,
Patch::AddEvents(node_idx, _) => *node_idx,
Patch::RemoveAllVirtualEventsWithNodeIdx(node_idx) => {
*node_idx
}
Patch::InsertBefore {
anchor_old_node_idx: old_idx,
..
} => *old_idx,
Patch::MoveNodesBefore {
anchor_old_node_idx,
..
} => *anchor_old_node_idx,
Patch::MoveToEndOfSiblings {
parent_old_node_idx,
..
} => *parent_old_node_idx,
Patch::RemoveChildren {
parent_old_node_idx: parent_old_idx,
..
} => *parent_old_idx,
}
}
pub(crate) fn insert_node_indices_to_find(&self, to_find: &mut HashSet<u32>) {
match self {
Patch::AppendChildren {
parent_old_node_idx: old_idx,
..
} => {
to_find.insert(*old_idx);
}
Patch::Replace { old_idx, .. } => {
to_find.insert(*old_idx);
}
Patch::AddAttributes(node_idx, _) => {
to_find.insert(*node_idx);
}
Patch::RemoveAttributes(node_idx, _) => {
to_find.insert(*node_idx);
}
Patch::ChangeText(node_idx, _) => {
to_find.insert(*node_idx);
}
Patch::ValueAttributeUnchanged(node_idx, _) => {
to_find.insert(*node_idx);
}
Patch::CheckedAttributeUnchanged(node_idx, _) => {
to_find.insert(*node_idx);
}
Patch::SpecialAttribute(special) => match special {
PatchSpecialAttribute::CallOnCreateElemOnExistingNode(node_idx, _) => {
to_find.insert(*node_idx);
}
PatchSpecialAttribute::SetDangerousInnerHtml(node_idx, _) => {
to_find.insert(*node_idx);
}
PatchSpecialAttribute::RemoveDangerousInnerHtml(node_idx) => {
to_find.insert(*node_idx);
}
PatchSpecialAttribute::CallOnRemoveElem(node_idx, _) => {
to_find.insert(*node_idx);
}
},
Patch::RemoveEvents(node_idx, _) => {
to_find.insert(*node_idx);
}
Patch::AddEvents(node_idx, _) => {
to_find.insert(*node_idx);
}
Patch::RemoveAllVirtualEventsWithNodeIdx(node_idx) => {
to_find.insert(*node_idx);
}
Patch::InsertBefore {
anchor_old_node_idx: old_idx,
..
} => {
to_find.insert(*old_idx);
}
Patch::MoveNodesBefore {
anchor_old_node_idx,
to_move,
} => {
to_find.insert(*anchor_old_node_idx);
for idx in to_move {
to_find.insert(*idx);
}
}
Patch::MoveToEndOfSiblings {
parent_old_node_idx,
siblings_to_move,
} => {
to_find.insert(*parent_old_node_idx);
for idx in siblings_to_move {
to_find.insert(*idx);
}
}
Patch::RemoveChildren {
parent_old_node_idx,
to_remove,
} => {
to_find.insert(*parent_old_node_idx);
for idx in to_remove {
to_find.insert(*idx);
}
}
}
}
}