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