Skip to content

Commit

Permalink
add Model::from_slice
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewhickman committed Jan 12, 2018
1 parent 33981de commit 5ead863
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 28 deletions.
41 changes: 17 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,38 @@ extern crate memchr;

mod de;
mod model;
mod read;

pub use model::*;
pub use failure::Error;

use read::{Read, IoReader, SliceReader};

use memchr::memchr;

use std::io::Read;
use std::io;
use std::{mem, ptr, str, u8};
use std::path::PathBuf;

pub type Result<T> = std::result::Result<T, Error>;

/// Read an ms3d model file from a reader.
pub fn from_reader<R: Read>(rdr: R) -> Result<Model> {
Reader::new(rdr).read_model()
}

struct Reader<R: Read> {
rdr: R,
buf: Vec<u8>,
}

impl<R: Read> Reader<R> {
fn new(rdr: R) -> Self {
Reader {
rdr,
buf: Vec::new(),
}
impl<R: io::Read> Reader<IoReader<R>> {
fn from_io_reader(rdr: R) -> Self {
Reader { rdr: IoReader::new(rdr) }
}
}

impl<'a> Reader<SliceReader<'a>> {
fn from_slice(slice: &'a [u8]) -> Self {
Reader { rdr: SliceReader::new(slice) }
}
}

impl<R: Read> Reader<R> {
fn read_model(&mut self) -> Result<Model> {
let header = self.read_header()?;
let vertices = self.read_vertices()?;
Expand Down Expand Up @@ -372,7 +374,7 @@ impl<R: Read> Reader<R> {
}

fn read_string(&mut self, len: usize) -> Result<String> {
Ok(str::from_utf8(self.read(len)?)?.to_owned())
Ok(str::from_utf8(self.rdr.read(len)?)?.to_owned())
}

fn read_vec<T, F>(&mut self, len: usize, f: F) -> Result<Vec<T>>
Expand All @@ -396,18 +398,9 @@ impl<R: Read> Reader<R> {

unsafe fn read_type<T>(&mut self) -> Result<T> {
Ok(ptr::read_unaligned(
self.read(mem::size_of::<T>())? as *const [u8] as *const T,
self.rdr.read(mem::size_of::<T>())? as *const [u8] as *const T,
))
}

fn read(&mut self, len: usize) -> Result<&[u8]> {
unsafe {
self.buf.reserve(len);
let slice = self.buf.get_unchecked_mut(..len);
self.rdr.read_exact(slice)?;
Ok(slice)
}
}
}

fn convert_string(bytes: &[u8]) -> Result<String> {
Expand Down
11 changes: 8 additions & 3 deletions src/model.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::path::PathBuf;
use std::io::Read;
use std::io;

use super::{Reader, Result};

Expand All @@ -21,8 +21,13 @@ pub struct Model {

impl Model {
/// Read an ms3d model file from a reader.
pub fn from_reader<R: Read>(rdr: R) -> Result<Self> {
Reader::new(rdr).read_model()
pub fn from_reader<R: io::Read>(rdr: R) -> Result<Self> {
Reader::from_io_reader(rdr).read_model()
}

/// Read an ms3d model file from a slice of bytes.
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
Reader::from_slice(bytes).read_model()
}
}

Expand Down
48 changes: 48 additions & 0 deletions src/read.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::io;

pub(crate) trait Read {
fn read(&mut self, len: usize) -> io::Result<&[u8]>;
}

pub(crate) struct IoReader<R: io::Read> {
rdr: R,
buf: Vec<u8>,
}

impl<R: io::Read> IoReader<R> {
pub fn new(rdr: R) -> Self {
IoReader { rdr, buf: Vec::new() }
}
}

impl<R: io::Read> Read for IoReader<R> {
fn read(&mut self, len: usize) -> io::Result<&[u8]> {
unsafe {
self.buf.reserve(len);
let slice = self.buf.get_unchecked_mut(..len);
self.rdr.read_exact(slice)?;
Ok(slice)
}
}
}

pub(crate) struct SliceReader<'a> {
slice: &'a [u8],
}

impl<'a> SliceReader<'a> {
pub fn new(slice: &'a [u8]) -> Self {
SliceReader { slice }
}
}

impl<'a> Read for SliceReader<'a> {
fn read(&mut self, len: usize) -> io::Result<&[u8]> {
if len > self.slice.len() {
return Err(io::ErrorKind::UnexpectedEof.into())
}
let (head, tail) = self.slice.split_at(len);
self.slice = tail;
Ok(head)
}
}
9 changes: 8 additions & 1 deletion tests/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ extern crate ms3d;
use std::fs::File;
use ms3d::Model;

const BYTES: &[u8] = include_bytes!("POA.ms3d");

#[test]
fn main() {
fn test_reader() {
Model::from_reader(File::open("tests/POA.ms3d").unwrap()).unwrap();
}

#[test]
fn test_slice() {
Model::from_bytes(BYTES).unwrap();
}

0 comments on commit 5ead863

Please # to comment.