Skip to main content

lib3mf_core/parser/
beamlattice_parser.rs

1use crate::error::{Lib3mfError, Result};
2use crate::model::{Beam, BeamLattice, BeamSet, CapMode, ClippingMode};
3use crate::parser::xml_parser::{XmlParser, get_attribute, get_attribute_f32, get_attribute_u32};
4use quick_xml::events::Event;
5use std::io::BufRead;
6// parse_beam_lattice removed
7
8// Rewriting above thinking:
9// I will define `pub fn parse_beam_lattice_content<R>(parser, min_length, precision, clipping) -> Result<BeamLattice>`
10// And the caller will handle the attributes.
11
12/// Parses the content of a `<beamlattice>` element into a `BeamLattice`, given pre-parsed attributes.
13pub fn parse_beam_lattice_content<R: BufRead>(
14    parser: &mut XmlParser<R>,
15    radius: Option<f32>,
16    min_length: f32,
17    precision: f32,
18    clipping_mode: ClippingMode,
19) -> Result<BeamLattice> {
20    let mut beams = Vec::new();
21    let mut beam_sets = Vec::new();
22    let default_radius = radius.unwrap_or(0.0);
23
24    loop {
25        match parser.read_next_event()? {
26            Event::Start(e) => match e.local_name().as_ref() {
27                b"beams" => {
28                    beams = parse_beams(parser, default_radius)?;
29                }
30                b"beamsets" => {
31                    beam_sets = parse_beam_sets(parser)?;
32                }
33                _ => {}
34            },
35            Event::End(e) if e.local_name().as_ref() == b"beamlattice" => break,
36            Event::Eof => {
37                return Err(Lib3mfError::Validation(
38                    "Unexpected EOF in beamlattice".to_string(),
39                ));
40            }
41            _ => {}
42        }
43    }
44
45    Ok(BeamLattice {
46        radius,
47        min_length,
48        precision,
49        clipping_mode,
50        beams,
51        beam_sets,
52    })
53}
54
55fn parse_beams<R: BufRead>(parser: &mut XmlParser<R>, default_radius: f32) -> Result<Vec<Beam>> {
56    let mut beams = Vec::new();
57    loop {
58        match parser.read_next_event()? {
59            Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"beam" => {
60                let v1 = get_attribute_u32(&e, b"v1")?;
61                let v2 = get_attribute_u32(&e, b"v2")?;
62                let r1 = get_attribute_f32(&e, b"r1").unwrap_or(default_radius);
63                let r2 = get_attribute_f32(&e, b"r2").unwrap_or(r1);
64                let p1 = get_attribute_u32(&e, b"p1").ok();
65                let p2 = get_attribute_u32(&e, b"p2").ok();
66
67                let cap_mode = if let Some(s) = get_attribute(&e, b"cap") {
68                    match s.as_ref() {
69                        "sphere" => CapMode::Sphere,
70                        "hemisphere" => CapMode::Hemisphere,
71                        "butt" => CapMode::Butt,
72                        _ => CapMode::Sphere,
73                    }
74                } else {
75                    CapMode::Sphere
76                };
77
78                beams.push(Beam {
79                    v1,
80                    v2,
81                    r1,
82                    r2,
83                    p1,
84                    p2,
85                    cap_mode,
86                });
87            }
88            Event::End(e) if e.local_name().as_ref() == b"beams" => break,
89            Event::Eof => {
90                return Err(Lib3mfError::Validation(
91                    "Unexpected EOF in beams".to_string(),
92                ));
93            }
94            _ => {}
95        }
96    }
97    Ok(beams)
98}
99
100fn parse_beam_sets<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<BeamSet>> {
101    let mut sets = Vec::new();
102    loop {
103        let event = parser.read_next_event()?;
104        match event {
105            Event::Start(e) if e.local_name().as_ref() == b"beamset" => {
106                let name = get_attribute(&e, b"name").map(|s| s.into_owned());
107                let identifier = get_attribute(&e, b"identifier").map(|s| s.into_owned());
108                let refs = parse_refs(parser)?;
109                sets.push(BeamSet {
110                    name,
111                    identifier,
112                    refs,
113                });
114            }
115            Event::Empty(e) if e.local_name().as_ref() == b"beamset" => {
116                let name = get_attribute(&e, b"name").map(|s| s.into_owned());
117                let identifier = get_attribute(&e, b"identifier").map(|s| s.into_owned());
118                sets.push(BeamSet {
119                    name,
120                    identifier,
121                    refs: Vec::new(),
122                });
123            }
124            Event::End(e) if e.local_name().as_ref() == b"beamsets" => break,
125            Event::Eof => {
126                return Err(Lib3mfError::Validation(
127                    "Unexpected EOF in beamsets".to_string(),
128                ));
129            }
130            _ => {}
131        }
132    }
133    Ok(sets)
134}
135
136fn parse_refs<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<u32>> {
137    let mut refs = Vec::new();
138    loop {
139        match parser.read_next_event()? {
140            Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"ref" => {
141                let idx = get_attribute_u32(&e, b"index")?;
142                refs.push(idx);
143            }
144            Event::End(e) if e.local_name().as_ref() == b"beamset" => break,
145            Event::Eof => {
146                return Err(Lib3mfError::Validation(
147                    "Unexpected EOF in beamset".to_string(),
148                ));
149            }
150            _ => {}
151        }
152    }
153    Ok(refs)
154}