feat: add FlatVDom round-trip conversion tests
This commit is contained in:
@@ -233,6 +233,7 @@ pub struct VNode<'a> {
|
||||
pub struct FlatVDom<'a> {
|
||||
pub nodes: Vec<VNode<'a>>,
|
||||
pub properties: Vec<(String, String)>,
|
||||
root_indices: Vec<NodeIdx>,
|
||||
}
|
||||
|
||||
impl<'a> FlatVDom<'a> {
|
||||
@@ -240,19 +241,22 @@ impl<'a> FlatVDom<'a> {
|
||||
Self {
|
||||
nodes: Vec::new(),
|
||||
properties: Vec::new(),
|
||||
root_indices: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_elements(elements: &[Element<'a>]) -> Self {
|
||||
let mut fv = FlatVDom::new();
|
||||
fv.append_elements(elements);
|
||||
fv.append_elements(elements, true);
|
||||
fv
|
||||
}
|
||||
|
||||
fn append_elements(&mut self, elements: &[Element<'a>]) -> Range<NodeIdx> {
|
||||
let start = self.nodes.len();
|
||||
fn append_elements(&mut self, elements: &[Element<'a>], is_root: bool) {
|
||||
for el in elements {
|
||||
let node_idx = self.nodes.len();
|
||||
if is_root {
|
||||
self.root_indices.push(node_idx);
|
||||
}
|
||||
let prop_start = self.properties.len();
|
||||
for (k, v) in &el.properties {
|
||||
self.properties.push((k.clone().into_owned(), v.clone().into_owned()));
|
||||
@@ -265,36 +269,41 @@ impl<'a> FlatVDom<'a> {
|
||||
computed_style: el.computed_style,
|
||||
element_id: el.element_id,
|
||||
});
|
||||
let child_range = self.append_elements(&el.children);
|
||||
self.nodes[node_idx].children_range = child_range;
|
||||
let child_start = self.nodes.len();
|
||||
self.append_elements(&el.children, false);
|
||||
self.nodes[node_idx].children_range = child_start..self.nodes.len();
|
||||
}
|
||||
start..self.nodes.len()
|
||||
}
|
||||
|
||||
pub fn into_elements(self) -> Vec<Element<'a>> {
|
||||
Self::nodes_to_elements(&self.nodes, &self.properties, 0..self.nodes.len())
|
||||
}
|
||||
|
||||
fn nodes_to_elements(nodes: &[VNode<'a>], props: &[(String, String)], range: Range<NodeIdx>) -> Vec<Element<'a>> {
|
||||
let mut result = Vec::with_capacity(range.len());
|
||||
for idx in range {
|
||||
let vn = &nodes[idx];
|
||||
let mut el = Element::new(vn.type_name);
|
||||
el.element_id = vn.element_id;
|
||||
el.computed_style = vn.computed_style;
|
||||
for i in vn.properties.clone() {
|
||||
if i < props.len() {
|
||||
let (k, v) = &props[i];
|
||||
el.push_prop(k.clone(), v.clone());
|
||||
}
|
||||
let mut result = Vec::with_capacity(self.root_indices.len());
|
||||
for &root_idx in &self.root_indices {
|
||||
if let Some(el) = Self::node_to_element(&self.nodes, &self.properties, root_idx) {
|
||||
result.push(el);
|
||||
}
|
||||
let child_range = vn.children_range.clone();
|
||||
el.children = Self::nodes_to_elements(nodes, props, child_range);
|
||||
result.push(el);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn node_to_element(nodes: &[VNode<'a>], props: &[(String, String)], idx: NodeIdx) -> Option<Element<'a>> {
|
||||
let vn = nodes.get(idx)?;
|
||||
let mut el = Element::new(vn.type_name);
|
||||
el.element_id = vn.element_id;
|
||||
el.computed_style = vn.computed_style;
|
||||
for i in vn.properties.clone() {
|
||||
if i < props.len() {
|
||||
let (k, v) = &props[i];
|
||||
el.push_prop(k.clone(), v.clone());
|
||||
}
|
||||
}
|
||||
for child_idx in vn.children_range.clone() {
|
||||
if let Some(child) = Self::node_to_element(nodes, props, child_idx) {
|
||||
el.children.push(child);
|
||||
}
|
||||
}
|
||||
Some(el)
|
||||
}
|
||||
|
||||
pub fn get_node(&self, idx: NodeIdx) -> Option<&VNode<'a>> {
|
||||
self.nodes.get(idx)
|
||||
}
|
||||
@@ -302,6 +311,14 @@ impl<'a> FlatVDom<'a> {
|
||||
pub fn node_count(&self) -> usize {
|
||||
self.nodes.len()
|
||||
}
|
||||
|
||||
pub fn root_count(&self) -> usize {
|
||||
self.root_indices.len()
|
||||
}
|
||||
|
||||
pub fn root_indices(&self) -> &[NodeIdx] {
|
||||
&self.root_indices
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
Reference in New Issue
Block a user