Function flatten

Source
pub fn flatten<'a, I>(nodes: I) -> IndexMap<String, FlatNode>
where I: IntoIterator<Item = &'a IfcxNode>,
Expand description

Merges input nodes into one FlatNode per path.

This borrows the nodes, so every attribute value is copied into the result. When the nodes are not needed afterwards, flatten_owned gives the same result without copying them, which is several times faster on large models.

nodes must be in layer order, weakest first: the nodes of one file in file order, and for a layer stack the nodes of each layer after those of the layers it overrides. Later nodes win, as described on FlatNode::merge.

The result is keyed by path, in order of each path’s first appearance. Every map keeps insertion order. Upstream stores these maps in JavaScript objects, which list integer-like keys such as "2" first; that ordering quirk is not reproduced, the content is the same. Paths are compared as plain strings, so a/b is a node of its own here; composition applies it to child b of a.

use openbim_ifcx::{flatten, IfcxNode};

let layers: Vec<IfcxNode> = serde_json::from_str(r#"[
    {"path": "w", "children": {"Body": "b1"}, "inherits": {"Type": "t"},
     "attributes": {"x::height": 2.5}},
    {"path": "w", "children": {"Body": null}, "inherits": {"Type": null},
     "attributes": {"x::height": 3.0}}
]"#)?;
let flat = flatten(&layers);
let wall = &flat["w"];
assert_eq!(wall.children["Body"], None);
assert!(wall.inherits.is_empty());
assert_eq!(*wall.attributes["x::height"], 3.0);