Skip to main content

lib3mf_core/parser/
build_parser.rs

1use crate::error::{Lib3mfError, Result};
2use crate::model::{Build, BuildItem};
3use crate::parser::component_parser::parse_transform;
4use crate::parser::xml_parser::{XmlParser, get_attribute, get_attribute_u32};
5
6use glam::Mat4;
7use quick_xml::events::Event;
8use std::borrow::Cow;
9use std::io::BufRead;
10
11/// Parses a `<build>` element and its `<item>` children into a `Build`.
12pub fn parse_build<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Build> {
13    let mut build = Build::default();
14
15    loop {
16        match parser.read_next_event()? {
17            Event::Start(e) | Event::Empty(e) if e.name().as_ref() == b"item" => {
18                let object_id = crate::model::ResourceId(get_attribute_u32(&e, b"objectid")?);
19                let transform = if let Some(s) = get_attribute(&e, b"transform") {
20                    parse_transform(&s)?
21                } else {
22                    Mat4::IDENTITY
23                };
24
25                let part_number =
26                    get_attribute(&e, b"partnumber").map(|s: Cow<str>| s.into_owned());
27                let uuid = crate::parser::xml_parser::get_attribute_uuid(&e)?;
28                // Try "path" or "p:path"
29                let path = get_attribute(&e, b"path")
30                    .or_else(|| get_attribute(&e, b"p:path"))
31                    .map(|s: Cow<str>| s.into_owned());
32
33                let printable = get_attribute(&e, b"printable").and_then(|s| match s.as_ref() {
34                    "1" => Some(true),
35                    "0" => Some(false),
36                    _ => None,
37                });
38
39                build.items.push(BuildItem {
40                    object_id,
41                    part_number,
42                    uuid,
43                    path,
44                    transform,
45                    printable,
46                });
47            }
48            Event::End(e) if e.name().as_ref() == b"build" => break,
49            Event::Eof => {
50                return Err(Lib3mfError::Validation(
51                    "Unexpected EOF in build".to_string(),
52                ));
53            }
54            _ => {}
55        }
56    }
57
58    Ok(build)
59}