use super::{Element, Node, Text};
pub struct KeyedFor {
nodes: Vec<(u64, Node)>,
}
#[allow(clippy::new_without_default)]
impl KeyedFor {
pub fn new() -> Self {
Self { nodes: Vec::new() }
}
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
pub fn get(&self, index: usize) -> Option<&Node> {
self.nodes.get(index).as_ref().map(|node| &node.1)
}
pub fn remove_if_key_mismatch(&mut self, index: usize, key: u64, real_parent: &web_sys::Node) {
if index >= self.nodes.len() {
return;
}
let ckey = unsafe { self.nodes.get_unchecked(index).0 };
if ckey != key {
let mut node = self.nodes.remove(index).1;
node.remove_real_node(real_parent);
}
}
pub fn add_text_if_key_mismatch(
&mut self,
index: usize,
key: u64,
value: &impl ToString,
) -> Option<(&Text, Option<&web_sys::Node>)> {
if index >= self.nodes.len() {
let text = Node::TextExpression(Text::new(value.to_string()));
self.nodes.push((key, text));
} else {
let ckey = unsafe { self.nodes.get_unchecked(index).0 };
if ckey != key {
let text = Node::TextExpression(Text::new(value.to_string()));
self.nodes.insert(index, (key, text));
} else {
return None;
}
}
let (p1, p2) = self.nodes.split_at(index + 1);
let text = match p1.last().expect("Node at given index").1 {
Node::TextExpression(ref text) => text,
_ => panic!("Expected Node::TextExpression"),
};
let next_sibling = p2
.first()
.map(|n| n.1.get_first_real_node())
.unwrap_or_else(|| None);
Some((text, next_sibling))
}
pub fn add_element_if_key_mismatch(
&mut self,
index: usize,
key: u64,
tag: &str,
) -> Option<(&mut Element, bool, Option<&web_sys::Node>)> {
let len = self.nodes.len();
let new = if len == 0 {
self.nodes.push((key, Node::Element(Element::new(tag))));
true
} else if index >= len {
let new = self.nodes[0].1.start_clone();
self.nodes.push((key, new));
false
} else {
let ckey = unsafe { self.nodes.get_unchecked_mut(index).0 };
if ckey != key {
let new = self.nodes[0].1.start_clone();
self.nodes.insert(index, (key, new));
false
} else {
return None;
}
};
let (p1, p2) = self.nodes.split_at_mut(index + 1);
let element = match p1.last_mut().expect("Node at given index").1 {
Node::Element(ref mut e) => e,
_ => panic!("Expect Node::Element"),
};
let next_sibling = p2
.first()
.map(|n| n.1.get_first_real_node())
.unwrap_or_else(|| None);
Some((element, new, next_sibling))
}
pub fn text(&mut self, index: usize, key: u64, value: &impl ToString) -> Option<&Text> {
if index >= self.nodes.len() {
let text = Node::TextExpression(Text::new(value.to_string()));
self.nodes.push((key, text));
} else {
let (ckey, text) = unsafe { self.nodes.get_unchecked_mut(index) };
if *ckey != key {
*ckey = key;
}
match text {
Node::TextExpression(text) => text.update_text(value.to_string()),
_ => panic!("Expected Node::TextExpression"),
}
return None;
}
debug_assert_eq!(index + 1, self.nodes.len(), "Item must be the last");
match self.nodes.get(index).expect("Node at given index").1 {
Node::TextExpression(ref text) => Some(text),
_ => panic!("Expected Node::TextExpression"),
}
}
pub fn element(&mut self, index: usize, key: u64, tag: &str) -> (&mut Element, bool, bool) {
let len = self.nodes.len();
let (new, need_insert) = if len == 0 {
self.nodes.push((key, Node::Element(Element::new(tag))));
(true, true)
} else if index >= len {
let new = self.nodes[0].1.start_clone();
self.nodes.push((key, new));
(false, true)
} else {
let (ckey, node) = unsafe { self.nodes.get_unchecked_mut(index) };
if *ckey != key {
*ckey = key;
}
match node {
Node::Element(e) => return (e, false, false),
_ => panic!("Expect a Node::Element at the given index"),
}
};
let (ckey, node) = self.nodes.get_mut(index).expect("Element added");
debug_assert_eq!(*ckey, key, "Key mismatch");
match node {
Node::Element(e) => (e, new, need_insert),
_ => panic!("Expect a Node::Element at the given index"),
}
}
pub(crate) fn remove_and_get_next_sibling(
&mut self,
real_parent: &web_sys::Node,
) -> Option<web_sys::Node> {
if self.nodes.is_empty() {
return None;
}
let mut last = self.nodes.pop().expect("Simi bug: Arm must not be empty").1;
let next_sibling = last.remove_and_get_next_sibling(real_parent);
self.remove_real_node(real_parent);
next_sibling
}
pub(crate) fn remove_real_node(&mut self, real_parent: &web_sys::Node) {
while let Some(mut node) = self.nodes.pop() {
node.1.remove_real_node(real_parent);
}
}
pub fn truncate(&mut self, size_after_removal: usize, real_parent: &web_sys::Node) {
if size_after_removal == 0 {
real_parent.set_text_content(None);
self.nodes.truncate(0);
return;
}
while self.nodes.len() > size_after_removal {
let mut node = self.nodes.pop().expect("No more node to remove");
node.1.remove_real_node(real_parent);
}
}
pub fn get_next_sibling(&self) -> Option<web_sys::Node> {
self.nodes
.last()
.map(|node| node.1.get_next_sibling())
.unwrap_or_else(|| None)
}
pub fn get_first_real_node(&self) -> Option<&web_sys::Node> {
self.nodes
.first()
.map(|node| node.1.get_first_real_node())
.unwrap_or_else(|| None)
}
pub fn get_first_real_node_at(&self, index: usize) -> Option<web_sys::Node> {
self.nodes
.get(index)
.map(|node| node.1.get_first_real_node())
.unwrap_or_else(|| None)
.cloned()
}
pub(super) fn clone(&self, _real_parent: &web_sys::Node) -> Self {
Self { nodes: Vec::new() }
}
pub(super) fn start_clone(&self) -> Self {
Self { nodes: Vec::new() }
}
}