lib3mf_core/parser/
slice_parser.rs

1use crate::error::{Lib3mfError, Result};
2use crate::model::{Polygon, Segment, Slice, SliceRef, SliceStack, Vertex2D};
3use crate::parser::xml_parser::{XmlParser, get_attribute, get_attribute_f32, get_attribute_u32};
4use quick_xml::events::Event;
5use std::borrow::Cow;
6use std::io::BufRead;
7
8// parse_slice_stack removed (used content version directly)
9
10pub fn parse_slice_stack_content<R: BufRead>(
11    parser: &mut XmlParser<R>,
12    id: crate::model::ResourceId,
13    z_bottom: f32,
14) -> Result<SliceStack> {
15    let mut slices = Vec::new();
16    let mut refs = Vec::new();
17
18    loop {
19        match parser.read_next_event()? {
20            Event::Start(e) => match e.local_name().as_ref() {
21                b"slice" => {
22                    let z_top = get_attribute_f32(&e, b"ztop")?;
23                    let slice = parse_slice(parser, z_top)?;
24                    slices.push(slice);
25                }
26                b"sliceref" => {
27                    // Usually empty element <sliceref ... />?
28                    // Start or Empty.
29                    let stack_id =
30                        crate::model::ResourceId(get_attribute_u32(&e, b"slicestackid")?);
31                    let path = get_attribute(&e, b"slicepath")
32                        .map(|s: Cow<str>| s.into_owned())
33                        .unwrap_or_default();
34                    refs.push(SliceRef {
35                        slice_stack_id: stack_id,
36                        slice_path: path,
37                    });
38                }
39                _ => {}
40            },
41            Event::Empty(e) => {
42                if e.local_name().as_ref() == b"sliceref" {
43                    let stack_id =
44                        crate::model::ResourceId(get_attribute_u32(&e, b"slicestackid")?);
45                    let path = get_attribute(&e, b"slicepath")
46                        .map(|s: Cow<str>| s.into_owned())
47                        .unwrap_or_default();
48                    refs.push(SliceRef {
49                        slice_stack_id: stack_id,
50                        slice_path: path,
51                    });
52                }
53            }
54            Event::End(e) if e.local_name().as_ref() == b"slicestack" => break,
55            Event::Eof => {
56                return Err(Lib3mfError::Validation(
57                    "Unexpected EOF in slicestack".to_string(),
58                ));
59            }
60            _ => {}
61        }
62    }
63
64    Ok(SliceStack {
65        id,
66        z_bottom,
67        slices,
68        refs,
69    })
70}
71
72fn parse_slice<R: BufRead>(parser: &mut XmlParser<R>, z_top: f32) -> Result<Slice> {
73    let mut vertices = Vec::new();
74    let mut polygons = Vec::new();
75
76    loop {
77        match parser.read_next_event()? {
78            Event::Start(e) => match e.local_name().as_ref() {
79                b"vertices" => {
80                    vertices = parse_slice_vertices(parser)?;
81                }
82                b"polygon" => {
83                    // Polygon has attributes? "start"
84                    // Wait, polygon has `start` attribute indicating start vertex index?
85                    // "startsegment" is my field name. Spec says "start".
86                    let start = get_attribute_u32(&e, b"start").unwrap_or(0);
87                    let segments = parse_polygon_segments(parser)?;
88                    polygons.push(Polygon {
89                        start_segment: start,
90                        segments,
91                    });
92                }
93                _ => {}
94            },
95            Event::End(e) if e.local_name().as_ref() == b"slice" => break,
96            Event::Eof => {
97                return Err(Lib3mfError::Validation(
98                    "Unexpected EOF in slice".to_string(),
99                ));
100            }
101            _ => {}
102        }
103    }
104
105    Ok(Slice {
106        z_top,
107        vertices,
108        polygons,
109    })
110}
111
112fn parse_slice_vertices<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<Vertex2D>> {
113    let mut vertices = Vec::new();
114    loop {
115        match parser.read_next_event()? {
116            Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"vertex" => {
117                let x = get_attribute_f32(&e, b"x")?;
118                let y = get_attribute_f32(&e, b"y")?;
119                vertices.push(Vertex2D { x, y });
120            }
121            Event::End(e) if e.local_name().as_ref() == b"vertices" => break,
122            Event::Eof => {
123                return Err(Lib3mfError::Validation(
124                    "Unexpected EOF in slice vertices".to_string(),
125                ));
126            }
127            _ => {}
128        }
129    }
130    Ok(vertices)
131}
132
133fn parse_polygon_segments<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<Segment>> {
134    let mut segments = Vec::new();
135    loop {
136        match parser.read_next_event()? {
137            Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"segment" => {
138                let v2 = get_attribute_u32(&e, b"v2")?;
139                let p1 = get_attribute_u32(&e, b"p1").ok();
140                let p2 = get_attribute_u32(&e, b"p2").ok();
141                let pid = get_attribute_u32(&e, b"pid")
142                    .map(crate::model::ResourceId)
143                    .ok();
144
145                segments.push(Segment { v2, p1, p2, pid });
146            }
147            Event::End(e) if e.local_name().as_ref() == b"polygon" => break,
148            Event::Eof => {
149                return Err(Lib3mfError::Validation(
150                    "Unexpected EOF in polygon segments".to_string(),
151                ));
152            }
153            _ => {}
154        }
155    }
156    Ok(segments)
157}