lib3mf_core/parser/
streaming.rs1use crate::error::{Lib3mfError, Result};
2use crate::model::{BuildItem, ResourceId};
3use crate::parser::material_parser::{parse_base_materials, parse_color_group};
4use crate::parser::visitor::ModelVisitor;
5use crate::parser::xml_parser::{XmlParser, get_attribute, get_attribute_f32, get_attribute_u32};
6use glam::Mat4;
7use quick_xml::events::Event;
8use std::io::BufRead;
9
10pub fn parse_model_streaming<R: BufRead, V: ModelVisitor>(
13 reader: R,
14 visitor: &mut V,
15) -> Result<()> {
16 let mut parser = XmlParser::new(reader);
17
18 visitor.on_start_model()?;
19
20 loop {
21 match parser.read_next_event()? {
22 Event::Start(e) => {
23 match e.name().as_ref() {
24 b"model" => {
25 }
27 b"metadata" => {
28 let name = get_attribute(&e, b"name")
29 .ok_or(Lib3mfError::Validation("Metadata missing name".to_string()))?
30 .into_owned();
31 let content = parser.read_text_content()?;
32 visitor.on_metadata(&name, &content)?;
33 }
34 b"resources" => {
35 visitor.on_start_resources()?;
36 parse_resources_streaming(&mut parser, visitor)?;
37 visitor.on_end_resources()?;
38 }
39 b"build" => {
40 visitor.on_start_build()?;
41 parse_build_streaming(&mut parser, visitor)?;
42 visitor.on_end_build()?;
43 }
44 _ => {}
45 }
46 }
47 Event::Empty(e) => {
48 if e.name().as_ref() == b"metadata" {
49 let name = get_attribute(&e, b"name")
50 .ok_or(Lib3mfError::Validation("Metadata missing name".to_string()))?;
51 visitor.on_metadata(name.as_ref(), "")?;
52 }
53 }
54 Event::End(e) if e.name().as_ref() == b"model" => break,
55 Event::Eof => break,
56 _ => {}
57 }
58 }
59
60 visitor.on_end_model()?;
61 Ok(())
62}
63
64fn parse_resources_streaming<R: BufRead, V: ModelVisitor>(
65 parser: &mut XmlParser<R>,
66 visitor: &mut V,
67) -> Result<()> {
68 loop {
69 match parser.read_next_event()? {
70 Event::Start(e) => {
71 let local_name = e.local_name();
72 match local_name.as_ref() {
73 b"object" => {
74 let id = ResourceId(get_attribute_u32(&e, b"id")?);
75 parse_object_content_streaming(parser, visitor, id)?;
76 }
77 b"basematerials" => {
78 let id = ResourceId(get_attribute_u32(&e, b"id")?);
79 let group = parse_base_materials(parser, id)?;
80 visitor.on_base_materials(id, &group)?;
81 }
82 b"colorgroup" => {
83 let id = ResourceId(get_attribute_u32(&e, b"id")?);
84 let group = parse_color_group(parser, id)?;
85 visitor.on_color_group(id, &group)?;
86 }
87 _ => {}
88 }
89 }
90 Event::End(e) if e.name().as_ref() == b"resources" => break,
91 Event::Eof => {
92 return Err(Lib3mfError::Validation(
93 "Unexpected EOF in resources".to_string(),
94 ));
95 }
96 _ => {}
97 }
98 }
99 Ok(())
100}
101
102fn parse_object_content_streaming<R: BufRead, V: ModelVisitor>(
103 parser: &mut XmlParser<R>,
104 visitor: &mut V,
105 object_id: ResourceId,
106) -> Result<()> {
107 loop {
108 match parser.read_next_event()? {
109 Event::Start(e) => match e.name().as_ref() {
110 b"mesh" => {
111 visitor.on_start_mesh(object_id)?;
112 parse_mesh_streaming(parser, visitor)?;
113 visitor.on_end_mesh()?;
114 }
115 b"components" => {
116 }
118 _ => {}
119 },
120 Event::End(e) if e.name().as_ref() == b"object" => break,
121 Event::Eof => {
122 return Err(Lib3mfError::Validation(
123 "Unexpected EOF in object".to_string(),
124 ));
125 }
126 _ => {}
127 }
128 }
129 Ok(())
130}
131
132fn parse_mesh_streaming<R: BufRead, V: ModelVisitor>(
133 parser: &mut XmlParser<R>,
134 visitor: &mut V,
135) -> Result<()> {
136 loop {
137 match parser.read_next_event()? {
138 Event::Start(e) => match e.name().as_ref() {
139 b"vertices" => parse_vertices_streaming(parser, visitor)?,
140 b"triangles" => parse_triangles_streaming(parser, visitor)?,
141 _ => {}
142 },
143 Event::End(e) if e.name().as_ref() == b"mesh" => break,
144 Event::Eof => {
145 return Err(Lib3mfError::Validation(
146 "Unexpected EOF in mesh".to_string(),
147 ));
148 }
149 _ => {}
150 }
151 }
152 Ok(())
153}
154
155fn parse_vertices_streaming<R: BufRead, V: ModelVisitor>(
156 parser: &mut XmlParser<R>,
157 visitor: &mut V,
158) -> Result<()> {
159 loop {
160 match parser.read_next_event()? {
161 Event::Start(e) | Event::Empty(e) => {
162 if e.name().as_ref() == b"vertex" {
163 let x = get_attribute_f32(&e, b"x")?;
164 let y = get_attribute_f32(&e, b"y")?;
165 let z = get_attribute_f32(&e, b"z")?;
166 visitor.on_vertex(x, y, z)?;
167 }
168 }
169 Event::End(e) if e.name().as_ref() == b"vertices" => break,
170 Event::Eof => {
171 return Err(Lib3mfError::Validation(
172 "Unexpected EOF in vertices".to_string(),
173 ));
174 }
175 _ => {}
176 }
177 }
178 Ok(())
179}
180
181fn parse_triangles_streaming<R: BufRead, V: ModelVisitor>(
182 parser: &mut XmlParser<R>,
183 visitor: &mut V,
184) -> Result<()> {
185 loop {
186 match parser.read_next_event()? {
187 Event::Start(e) | Event::Empty(e) => {
188 if e.name().as_ref() == b"triangle" {
189 let v1 = get_attribute_u32(&e, b"v1")?;
190 let v2 = get_attribute_u32(&e, b"v2")?;
191 let v3 = get_attribute_u32(&e, b"v3")?;
192 visitor.on_triangle(v1, v2, v3)?;
193 }
194 }
195 Event::End(e) if e.name().as_ref() == b"triangles" => break,
196 Event::Eof => {
197 return Err(Lib3mfError::Validation(
198 "Unexpected EOF in triangles".to_string(),
199 ));
200 }
201 _ => {}
202 }
203 }
204 Ok(())
205}
206
207fn parse_build_streaming<R: BufRead, V: ModelVisitor>(
208 parser: &mut XmlParser<R>,
209 visitor: &mut V,
210) -> Result<()> {
211 loop {
212 match parser.read_next_event()? {
213 Event::Start(e) | Event::Empty(e) => {
214 if e.name().as_ref() == b"item" {
215 let object_id = ResourceId(get_attribute_u32(&e, b"objectid")?);
216 let item = BuildItem {
217 object_id,
218 transform: Mat4::IDENTITY,
219 part_number: None,
220 uuid: None,
221 path: None,
222 };
223 visitor.on_build_item(&item)?;
224 }
225 }
226 Event::End(e) if e.name().as_ref() == b"build" => break,
227 Event::Eof => {
228 return Err(Lib3mfError::Validation(
229 "Unexpected EOF in build".to_string(),
230 ));
231 }
232 _ => {}
233 }
234 }
235 Ok(())
236}