use crate::TriangleIterator;
use crate::types::{Normal, Triangle, Vertex};
use std::io::{BufReader, Read, Result};
pub struct BinaryStlReader<'a> {
reader: Box<dyn Read + 'a>,
index: usize,
size: usize,
}
impl<'a> BinaryStlReader<'a> {
pub fn create_triangle_iterator(
read: &'a mut dyn Read,
) -> Result<Box<dyn TriangleIterator<Item = Result<Triangle>> + 'a>> {
let mut reader = Box::new(BufReader::new(read));
let mut header = [0u8; 80];
reader.read_exact(&mut header)?;
let mut count_buf = [0u8; 4];
reader.read_exact(&mut count_buf)?;
let num_faces = u32::from_le_bytes(count_buf) as usize;
Ok(Box::new(BinaryStlReader {
reader,
index: 0,
size: num_faces,
})
as Box<dyn TriangleIterator<Item = Result<Triangle>>>)
}
fn next_face(&mut self) -> Result<Triangle> {
let mut buf = [0u8; 50];
self.reader.read_exact(&mut buf)?;
let f = |offset: usize| -> f32 {
f32::from_le_bytes([
buf[offset],
buf[offset + 1],
buf[offset + 2],
buf[offset + 3],
])
};
let normal = Normal::new([f(0), f(4), f(8)]);
let vertices = [
Vertex::new([f(12), f(16), f(20)]),
Vertex::new([f(24), f(28), f(32)]),
Vertex::new([f(36), f(40), f(44)]),
];
Ok(Triangle { normal, vertices })
}
}
impl<'a> Iterator for BinaryStlReader<'a> {
type Item = Result<Triangle>;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.size {
self.index += 1;
return Some(self.next_face());
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.size - self.index, Some(self.size - self.index))
}
}
impl<'a> TriangleIterator for BinaryStlReader<'a> {}