Fixed some things, enable parsing from anything that impl Read
This commit is contained in:
+42
-35
@@ -6,7 +6,7 @@ pub mod mtl;
|
||||
use std::fmt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Error};
|
||||
use std::io::{BufReader, Error, Read};
|
||||
use math::vector::{Vector2, Vector3};
|
||||
use model::face::Face;
|
||||
use model::material::Material;
|
||||
@@ -112,31 +112,46 @@ pub enum ParserError {
|
||||
OtherError(String),
|
||||
}
|
||||
|
||||
/// Parses a content from a reader, guess the file type from path, and return the model.
|
||||
pub fn parse<R: Read>(reader: R, path: &str) -> Result<Model, ParserError> {
|
||||
let mut model = Model::new();
|
||||
parse_into_model(reader, path, &mut model)?;
|
||||
Ok(model)
|
||||
}
|
||||
|
||||
/// Parses a file and append the result to the model passed as parameter.
|
||||
pub fn parse_file_into_model(path: &str, model: &mut Model) -> Result<(), ParserError> {
|
||||
let file = match File::open(path) {
|
||||
Ok(file) => file,
|
||||
Err(e) => return Err(ParserError::IoError(path.to_owned(), e)),
|
||||
};
|
||||
|
||||
let bufreader = BufReader::new(file);
|
||||
parse_into_model(bufreader, path, model)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Detects the format from path name and parses it into the model.
|
||||
pub fn parse_into_model(path: &str, model: &mut Model) -> Result<(), ParserError> {
|
||||
pub fn parse_into_model<R: Read>(reader: R, path: &str, model: &mut Model) -> Result<(), ParserError> {
|
||||
let extension = Path::new(path).extension().unwrap().to_str().unwrap();
|
||||
|
||||
use self::obj::ObjParser;
|
||||
use self::mtl::MtlParser;
|
||||
|
||||
let mut parser: Option<Box<Parser>> = match extension {
|
||||
"obj" => Some(Box::new(ObjParser::new())),
|
||||
"mtl" => Some(Box::new(MtlParser::new())),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(parser) = parser.as_mut() {
|
||||
parser.parse_into_model(model, path)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ParserError::UnknownFormat(path.to_owned()))
|
||||
match extension {
|
||||
"obj" => ObjParser::new().parse_into_model(model, reader, path)?,
|
||||
"mtl" => MtlParser::new().parse_into_model(model, reader, path)?,
|
||||
_ => return Err(ParserError::UnknownFormat(path.to_owned())),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Detects the format from path name and parses it into a new model.
|
||||
pub fn parse(path: &str) -> Result<Model, ParserError> {
|
||||
pub fn parse_file(path: &str) -> Result<Model, ParserError> {
|
||||
let mut model = Model::new();
|
||||
parse_into_model(path, &mut model)?;
|
||||
parse_file_into_model(path, &mut model)?;
|
||||
Ok(model)
|
||||
}
|
||||
|
||||
@@ -171,22 +186,22 @@ impl fmt::Display for ParserError {
|
||||
pub trait Parser {
|
||||
|
||||
/// Parses a file and adds its content into an empty model and returns the model.
|
||||
fn parse(&mut self, path: &str) -> Result<Model, ParserError> {
|
||||
fn parse<R: Read>(&mut self, reader: R, path: &str) -> Result<Model, ParserError> {
|
||||
let mut model = Model::new();
|
||||
self.parse_into_model(&mut model, path)?;
|
||||
self.parse_into_model(&mut model, reader, path)?;
|
||||
Ok(model)
|
||||
}
|
||||
|
||||
/// Parses a file and adds its content to an already existing model.
|
||||
fn parse_into_model(&mut self, model: &mut Model, path: &str) -> Result<(), ParserError> {
|
||||
fn parse_into_model<R: Read>(&mut self, model: &mut Model, reader: R, path: &str) -> Result<(), ParserError> {
|
||||
logln!("Parsing {}...", path);
|
||||
self.priv_parse_into_model(model, path)
|
||||
self.priv_parse_into_model(model, reader, path)
|
||||
}
|
||||
|
||||
/// Parses a file and adds its content to an already existing model.
|
||||
///
|
||||
/// This is the method you should implement for you format parser.
|
||||
fn priv_parse_into_model(&mut self, model: &mut Model, path: &str) -> Result<(), ParserError>;
|
||||
fn priv_parse_into_model<R: Read>(&mut self, model: &mut Model, reader: R, path: &str) -> Result<(), ParserError>;
|
||||
}
|
||||
|
||||
/// Anything that can parse a 3D file line by line.
|
||||
@@ -200,16 +215,9 @@ pub trait LineParser {
|
||||
|
||||
impl<LP: LineParser> Parser for LP {
|
||||
|
||||
fn priv_parse_into_model(&mut self, model: &mut Model, path: &str) -> Result<(), ParserError> {
|
||||
fn priv_parse_into_model<R: Read>(&mut self, model: &mut Model, reader: R, path: &str) -> Result<(), ParserError> {
|
||||
|
||||
let file = File::open(path);
|
||||
|
||||
if file.is_err() {
|
||||
return Err(ParserError::IoError(path.to_owned(), file.err().unwrap()));
|
||||
}
|
||||
|
||||
let file = file.unwrap();
|
||||
let file = BufReader::new(&file);
|
||||
let file = BufReader::new(reader);
|
||||
|
||||
let mut current_material_name = None;
|
||||
|
||||
@@ -218,11 +226,10 @@ impl<LP: LineParser> Parser for LP {
|
||||
|
||||
let num = num + 1;
|
||||
|
||||
if line.is_err() {
|
||||
return Err(ParserError::OtherError(path.to_owned()));
|
||||
}
|
||||
|
||||
let line = line.unwrap();
|
||||
let line = match line {
|
||||
Ok(x) => x,
|
||||
Err(e) => return Err(ParserError::IoError(path.to_owned(), e)),
|
||||
};
|
||||
|
||||
let element = self.parse_line(num, &line, &path)?;
|
||||
|
||||
@@ -238,7 +245,7 @@ impl<LP: LineParser> Parser for LP {
|
||||
let mut path = PathBuf::from(path);
|
||||
path.pop();
|
||||
path.push(material_path);
|
||||
if let Err(err) = parse_into_model(path.to_str().unwrap(), model) {
|
||||
if let Err(err) = parse_file_into_model(path.to_str().unwrap(), model) {
|
||||
return Err(err);
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user