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