1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use std::io::{Error, Read};
3
4pub trait STLObject: Sized {
5 fn parse(reader: &mut dyn Read) -> Result<Self, Error>;
6 fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<(), Error>;
7}
8
9impl STLObject for cgmath::Point3<f32> {
10 fn parse(reader: &mut dyn Read) -> Result<Self, Error> {
11 Ok(Self {
12 x: reader.read_f32::<LittleEndian>()?,
13 y: reader.read_f32::<LittleEndian>()?,
14 z: reader.read_f32::<LittleEndian>()?,
15 })
16 }
17
18 fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<(), Error> {
19 writer.write_f32::<LittleEndian>(self.x)?;
20 writer.write_f32::<LittleEndian>(self.y)?;
21 writer.write_f32::<LittleEndian>(self.z)?;
22 Ok(())
23 }
24}
25
26#[derive(PartialEq, Debug)]
27pub struct Triangle {
28 pub normal: cgmath::Point3<f32>,
29 pub vertices: [cgmath::Point3<f32>; 3],
30}
31
32impl STLObject for Triangle {
33 fn parse(reader: &mut dyn Read) -> Result<Self, Error> {
34 let triangle = Ok(Triangle {
35 normal: cgmath::Point3::parse(reader)?,
36 vertices: [
37 cgmath::Point3::parse(reader)?,
38 cgmath::Point3::parse(reader)?,
39 cgmath::Point3::parse(reader)?,
40 ],
41 });
42
43 reader.read_u16::<LittleEndian>()?;
44
45 triangle
46 }
47
48 fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<(), Error> {
49 self.normal.serialize(writer)?;
50 for vertex in self.vertices.iter() {
51 vertex.serialize(writer)?;
52 }
53 writer.write_u16::<LittleEndian>(0)?;
54 Ok(())
55 }
56}
57
58#[derive(Debug)]
59pub struct STL {
60 pub header: [u8; 80],
61 pub n_triangles: u32,
62 pub triangles: Vec<Triangle>,
63}
64
65impl STLObject for STL {
66 fn parse(reader: &mut dyn Read) -> Result<Self, Error> {
67 let mut header = [0u8; 80];
68 reader.read_exact(&mut header)?;
69 let n_triangles = reader.read_u32::<LittleEndian>()?;
70 match (0..n_triangles).map(|_| Triangle::parse(reader)).collect() {
71 Ok(triangles) => Ok(STL {
72 header,
73 n_triangles,
74 triangles,
75 }),
76 Err(e) => Err(e),
77 }
78 }
79
80 fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<(), Error> {
81 writer.write(&self.header)?;
82 writer.write_u32::<LittleEndian>(self.n_triangles)?;
83 for triangle in self.triangles.iter() {
84 triangle.serialize(writer)?;
85 }
86 Ok(())
87 }
88}
89
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn parse_one_face() -> Result<(), Box<dyn std::error::Error>> {
97 let mut stl_bytes = [0u8; 80 + 4 + 3 * 4 + 3 * 3 * 4 + 2];
99
100 stl_bytes[80] = 1;
102
103 let stl = STL::parse(&mut stl_bytes.as_slice())?;
105
106 assert_eq!(
107 Triangle {
108 normal: Normal {
109 x: 0.0,
110 y: 0.0,
111 z: 0.0
112 },
113 vertices: [
114 Vertex {
115 x: 0.0,
116 y: 0.0,
117 z: 0.0
118 },
119 Vertex {
120 x: 0.0,
121 y: 0.0,
122 z: 0.0
123 },
124 Vertex {
125 x: 0.0,
126 y: 0.0,
127 z: 0.0
128 },
129 ]
130 },
131 stl.triangles[0]
132 );
133
134 Ok(())
135 }
136}
137