diff --git a/src/lib.rs b/src/lib.rs index 220f59e..384075d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub mod zero_copy; pub use crate::names::consts; pub use crate::names::types; pub use zero_copy::Error; +use zero_copy::usize_from; #[derive (Debug, Default)] pub struct Mesh { @@ -38,8 +39,8 @@ pub struct VertexArray { } #[derive (Debug)] -pub struct Model <'a> { - data: &'a [u8], +pub struct Model <'data> { + zc: zero_copy::Model <'data>, pub header: Header, text: Vec , @@ -60,23 +61,17 @@ impl Header { } impl Mesh { - pub fn from_slice (input: &[u8]) -> Result { - let mut mesh = Mesh::default (); + pub fn from_zc (zc: &zero_copy::Mesh) -> Mesh { + use crate::names::consts::*; - let mut rdr = Cursor::new (input); - - for field in [ - &mut mesh.name, - &mut mesh.material, - &mut mesh.first_vertex, - &mut mesh.num_vertexes, - &mut mesh.first_triangle, - &mut mesh.num_triangles, - ].iter_mut () { - **field = rdr.read_u32:: ().map_err (|_| Error::ParseMeshFailed)?; + Mesh { + name: zc.field (MESH_NAME), + material: zc.field (MESH_MATERIAL), + first_vertex: zc.field (MESH_FIRST_VERTEX), + num_vertexes: zc.field (MESH_NUM_VERTEXES), + first_triangle: zc.field (MESH_FIRST_TRIANGLE), + num_triangles: zc.field (MESH_NUM_TRIANGLES), } - - Ok (mesh) } } @@ -98,6 +93,18 @@ impl VertexArray { Ok (va) } + + pub fn from_zc (zc: &zero_copy::VertexArray) -> VertexArray { + use crate::names::consts::*; + + VertexArray { + va_type: zc.field (VA_TYPE), + va_flags: zc.field (VA_FLAGS), + va_format: zc.field (VA_FORMAT), + va_size: zc.field (VA_SIZE), + va_offset: zc.field (VA_OFFSET), + } + } } impl <'a> Model <'a> { @@ -107,48 +114,21 @@ impl <'a> Model <'a> { let header = Header::from_zc (&zc); let text = { - let offset: usize = header.fields [consts::OFS_TEXT].try_into ().unwrap (); - let num: usize = header.fields [consts::NUM_TEXT].try_into ().unwrap (); + let offset = usize_from (zc.header_field (consts::OFS_TEXT)); + let num = usize_from (zc.header_field (consts::NUM_TEXT)); Vec::from (&data [offset..offset + num]) }; - let meshes = { - let num: usize = header.fields [consts::NUM_MESHES].try_into ().unwrap (); - let mut meshes = Vec::with_capacity (num); - let mesh_size = 6 * 4; - let meshes_offset: usize = header.fields [consts::OFS_MESHES].try_into ().unwrap (); - - for i in 0..num { - let offset = meshes_offset + i * mesh_size; - let mesh_slice = &data [offset..offset + mesh_size]; - - let mesh = Mesh::from_slice (mesh_slice)?; - - meshes.push (mesh); - } - meshes - }; + let meshes = zc.meshes ().map (|zc_mesh| { + Mesh::from_zc (&zc_mesh) + }).collect (); - let vertexarrays = { - let num: usize = header.fields [consts::NUM_VERTEXARRAYS].try_into ().unwrap (); - let mut vertexarrays = Vec::with_capacity (num); - let vertexarray_size = 5 * 4; - let vertexarrays_offset: usize = header.fields [consts::OFS_VERTEXARRAYS].try_into ().unwrap (); - - for i in 0..num { - let offset = vertexarrays_offset + i * vertexarray_size; - let vertexarray_slice = &data [offset..offset + vertexarray_size]; - - let vertexarray = VertexArray::from_slice (vertexarray_slice)?; - - vertexarrays.push (vertexarray); - } - - vertexarrays - }; + let vertexarrays = zc.vertexarrays ().map (|zc_va| { + VertexArray::from_zc (&zc_va) + }).collect (); Ok (Model { - data, + zc, header, text, @@ -157,19 +137,8 @@ impl <'a> Model <'a> { }) } - pub fn get_vertex_slice (&self, - vertexarray_index: usize - ) -> &[u8] - { - let vertexarray = &self.vertexarrays [vertexarray_index]; - let bytes_per_float = 4; - let stride = bytes_per_float * vertexarray.va_size; - //assert_eq! (stride, 12); - - let offset: usize = (vertexarray.va_offset).try_into ().unwrap (); - let num_bytes: usize = (stride * self.header.fields [consts::NUM_VERTEXES]).try_into ().unwrap (); - - &self.data [offset..offset + num_bytes] + pub fn get_vertex_slice (&self, idx: usize) -> &[u8] { + self.zc.vertexarray (idx).get_vertex_slice () } pub fn get_index_slice (&self, mesh_index: usize) -> &[u8] { @@ -182,7 +151,7 @@ impl <'a> Model <'a> { let num_bytes: usize = (stride * mesh.num_triangles).try_into ().unwrap (); - &self.data [offset..offset + num_bytes] + &self.zc.data [offset..offset + num_bytes] } pub fn get_all_indexes (&self) -> &[u8] { @@ -194,7 +163,7 @@ impl <'a> Model <'a> { let num_bytes: usize = (stride * self.header.fields [consts::NUM_TRIANGLES]).try_into ().unwrap (); - &self.data [offset..offset + num_bytes] + &self.zc.data [offset..offset + num_bytes] } // I don't think IQM makes any guarantees about UTF-8 @@ -207,7 +176,7 @@ impl <'a> Model <'a> { // There should be an easy way to do this with CString? let mut nul_index = None; - for (j, c) in self.data [ofs..].iter ().enumerate () { + for (j, c) in self.zc.data [ofs..].iter ().enumerate () { if *c == 0 { nul_index = Some (j); break; @@ -215,7 +184,51 @@ impl <'a> Model <'a> { } let nul_index = nul_index.unwrap (); - &self.data [ofs..ofs + nul_index] + &self.zc.data [ofs..ofs + nul_index] + } +} + +#[cfg (test)] +mod borrow_test { + struct Model <'data> { + data: &'data [u8], + } + + struct VertexArray <'model: 'data, 'data> { + model: &'model Model <'data>, + } + + impl <'data> Model <'data> { + pub fn va (&self) -> VertexArray { + VertexArray { + model: self, + } + } + + pub fn slice (&'data self) -> &'data [u8] { + let va = self.va (); + va.slice () + } + } + + impl <'model: 'data, 'data> VertexArray <'model, 'data> { + pub fn slice (&self) -> &'data [u8] { + self.model.data + } + } + + #[test] + fn nothing () { + let data = [1, 1, 2, 3, 5, 8]; + + let model = Model { + data: &data, + }; + + let va = model.va (); + + let slice = model.va ().slice (); + let slice = model.slice (); } } diff --git a/src/zero_copy.rs b/src/zero_copy.rs index 2722cb8..dda1df4 100644 --- a/src/zero_copy.rs +++ b/src/zero_copy.rs @@ -3,12 +3,13 @@ use std::mem::size_of; use byteorder::{ByteOrder, LittleEndian}; +#[derive (Debug)] pub struct Model <'data> { pub data: &'data [u8], } -pub struct VertexArray <'data> { - pub model: &'data Model <'data>, +pub struct VertexArray <'model: 'data, 'data> { + pub model: &'model Model <'data>, ofs: usize, } @@ -50,7 +51,7 @@ pub const HEADER_FIELD_COUNT: usize = 27; // If you are using IQM models on an 8-bit or 16-bit microcontroller // you're smarter than me anyway -fn usize_from (x: u32) -> usize { +pub fn usize_from (x: u32) -> usize { usize::try_from (x).unwrap () } @@ -67,10 +68,15 @@ impl <'data> Iterator for HeaderFields <'data> { self.idx += 1; Some (result) } + + fn size_hint (&self) -> (usize, Option ) { + let x = HEADER_FIELD_COUNT - self.idx; + (x, Some (x)) + } } impl <'data> Iterator for VertexArrays <'data> { - type Item = VertexArray <'data>; + type Item = VertexArray <'data, 'data>; fn next (&mut self) -> Option { if self.idx >= usize_from (self.model.header_field (crate::names::consts::NUM_VERTEXARRAYS)) { @@ -82,6 +88,11 @@ impl <'data> Iterator for VertexArrays <'data> { self.idx += 1; Some (result) } + + fn size_hint (&self) -> (usize, Option ) { + let x = usize_from (self.model.header_field (crate::names::consts::NUM_VERTEXARRAYS)) - self.idx; + (x, Some (x)) + } } impl <'data> Iterator for Meshes <'data> { @@ -97,6 +108,10 @@ impl <'data> Iterator for Meshes <'data> { self.idx += 1; Some (result) } + fn size_hint (&self) -> (usize, Option ) { + let x = usize_from (self.model.header_field (crate::names::consts::NUM_MESHES)) - self.idx; + (x, Some (x)) + } } impl <'data> Model <'data> { @@ -170,12 +185,12 @@ impl <'data> Model <'data> { } } -impl <'data> VertexArray <'data> { +impl <'model: 'data, 'data> VertexArray <'model, 'data> { pub fn field (&self, idx: usize) -> u32 { LittleEndian::read_u32 (&self.model.data [self.ofs + idx * size_of::()..]) } - pub fn get_vertex_slice (&self) -> &[u8] { + pub fn get_vertex_slice (&self) -> &'data [u8] { use names::consts::*; let stride = size_of:: () * usize_from (self.field (VA_SIZE));