Skip to main content

lib3mf_core/parser/
volumetric_parser.rs

1use crate::error::{Lib3mfError, Result};
2use crate::model::{ResourceId, VolumetricLayer, VolumetricRef, VolumetricStack};
3use crate::parser::xml_parser::{XmlParser, get_attribute, get_attribute_f32, get_attribute_u32};
4use quick_xml::events::Event;
5use std::io::BufRead;
6
7/// Parses the content of a `<volumestack>` element into a `VolumetricStack`.
8pub fn parse_volumetric_stack_content<R: BufRead>(
9    parser: &mut XmlParser<R>,
10    id: ResourceId,
11    _z_bottom: f32, // Unused in stack def usually? Or can be base. SliceStack uses it.
12) -> Result<VolumetricStack> {
13    let mut stack = VolumetricStack {
14        id,
15        ..Default::default()
16    };
17
18    loop {
19        match parser.read_next_event()? {
20            Event::Start(e) => {
21                let local_name = e.local_name();
22                match local_name.as_ref() {
23                    b"layer" => {
24                        let z = get_attribute_f32(&e, b"z").unwrap_or(0.0);
25                        // Content path: usually "path" or "src" attribute
26                        // Or implicitly the content? Spec usually uses "path".
27                        let path = get_attribute(&e, b"path").unwrap_or_default();
28
29                        let end_tag = e.name().as_ref().to_vec();
30                        stack.layers.push(VolumetricLayer {
31                            z_height: z,
32                            content_path: path.into_owned(),
33                        });
34                        parser.read_to_end(&end_tag)?;
35                    }
36                    b"volumetricref" => {
37                        let stack_id =
38                            get_attribute_u32(&e, b"volumetricstackid").map(ResourceId)?;
39                        let path = get_attribute(&e, b"path").unwrap_or_default();
40                        let end_tag = e.name().as_ref().to_vec();
41                        stack.refs.push(VolumetricRef {
42                            stack_id,
43                            path: path.into_owned(),
44                        });
45                        parser.read_to_end(&end_tag)?;
46                    }
47                    _ => {}
48                }
49            }
50            Event::End(e) if e.local_name().as_ref() == b"volumetricstack" => break,
51            Event::Eof => {
52                return Err(Lib3mfError::Validation(
53                    "Unexpected EOF in volumetricstack".to_string(),
54                ));
55            }
56            _ => {}
57        }
58    }
59
60    Ok(stack)
61}