lib3mf_core/parser/
component_parser.rs1use crate::error::{Lib3mfError, Result};
2use crate::model::{Component, Components};
3use crate::parser::xml_parser::{XmlParser, get_attribute, get_attribute_u32};
4use glam::Mat4;
5use quick_xml::events::Event;
6use std::io::BufRead;
7use std::str::FromStr;
8
9pub fn parse_components<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Components> {
10 let mut components = Vec::new();
11
12 loop {
13 match parser.read_next_event()? {
14 Event::Start(e) | Event::Empty(e) if e.name().as_ref() == b"component" => {
15 let object_id = crate::model::ResourceId(get_attribute_u32(&e, b"objectid")?);
16 let path = get_attribute(&e, b"path")
17 .or_else(|| get_attribute(&e, b"p:path"))
18 .map(|s| s.into_owned());
19 let uuid = crate::parser::xml_parser::get_attribute_uuid(&e)?;
20 let transform = if let Some(s) = get_attribute(&e, b"transform") {
21 parse_transform(&s)?
22 } else {
23 Mat4::IDENTITY
24 };
25 components.push(Component {
26 object_id,
27 path,
28 uuid,
29 transform,
30 });
31 }
32 Event::End(e) if e.name().as_ref() == b"components" => break,
33 Event::Eof => {
34 return Err(Lib3mfError::Validation(
35 "Unexpected EOF in components".to_string(),
36 ));
37 }
38 _ => {}
39 }
40 }
41
42 Ok(Components { components })
43}
44
45pub fn parse_transform(s: &str) -> Result<Mat4> {
46 let parts: Vec<&str> = s.split_whitespace().collect();
47 if parts.len() != 12 {
48 return Err(Lib3mfError::Validation(format!(
49 "Invalid transform matrix: expected 12 values, got {}",
50 parts.len()
51 )));
52 }
53
54 let p: Result<Vec<f32>> = parts
55 .iter()
56 .map(|v| {
57 f32::from_str(v)
58 .map_err(|_| Lib3mfError::Validation(format!("Invalid float in transform: {}", v)))
59 })
60 .collect();
61 let p = p?;
62
63 Ok(Mat4::from_cols_array(&[
65 p[0], p[1], p[2], 0.0, p[3], p[4], p[5], 0.0, p[6], p[7], p[8], 0.0, p[9], p[10], p[11],
66 1.0,
67 ]))
68}