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