lib3mf_core/writer/
volumetric_writer.rs

1use crate::error::Result;
2use crate::model::{VolumetricLayer, VolumetricRef, VolumetricStack};
3use crate::writer::xml_writer::XmlWriter;
4use std::io::Write;
5
6/// Writes a `<volumetricstack>` element with its child layers and volumetricrefs.
7///
8/// Element names are unqualified (no namespace prefix) because the volumetric
9/// namespace URI is declared on the root model element as `xmlns:v`.
10///
11/// Note: The `version` field of `VolumetricStack` is intentionally NOT emitted.
12/// The parser never reads it from XML, so writing it would break roundtrip symmetry.
13pub fn write_volumetric_stack<W: Write>(
14    writer: &mut XmlWriter<W>,
15    stack: &VolumetricStack,
16) -> Result<()> {
17    writer
18        .start_element("volumetricstack")
19        .attr("id", &stack.id.0.to_string())
20        .write_start()?;
21
22    // Write layers first, then refs (matches parser storage order)
23    for layer in &stack.layers {
24        write_layer(writer, layer)?;
25    }
26
27    for vref in &stack.refs {
28        write_volumetricref(writer, vref)?;
29    }
30
31    writer.end_element("volumetricstack")?;
32    Ok(())
33}
34
35/// Writes a `<layer>` element with z and path attributes.
36fn write_layer<W: Write>(writer: &mut XmlWriter<W>, layer: &VolumetricLayer) -> Result<()> {
37    writer
38        .start_element("layer")
39        .attr("z", &layer.z_height.to_string())
40        .attr("path", &layer.content_path)
41        .write_empty()?;
42    Ok(())
43}
44
45/// Writes a `<volumetricref>` element with volumetricstackid and path attributes.
46fn write_volumetricref<W: Write>(writer: &mut XmlWriter<W>, vref: &VolumetricRef) -> Result<()> {
47    writer
48        .start_element("volumetricref")
49        .attr("volumetricstackid", &vref.stack_id.0.to_string())
50        .attr("path", &vref.path)
51        .write_empty()?;
52    Ok(())
53}