Improved .psy file parsing error messages.
Biggest improvement: it gives you line numbers. But also progress on better descriptions.
This commit is contained in:
parent
f46e72b0ca
commit
6623443e2e
|
@ -140,7 +140,6 @@ struct LightTreeBuilder {
|
||||||
nodes: Vec<Node>,
|
nodes: Vec<Node>,
|
||||||
bounds: Vec<BBox>,
|
bounds: Vec<BBox>,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
bounds_cache: Vec<BBox>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightTreeBuilder {
|
impl LightTreeBuilder {
|
||||||
|
@ -149,7 +148,6 @@ impl LightTreeBuilder {
|
||||||
nodes: Vec::new(),
|
nodes: Vec::new(),
|
||||||
bounds: Vec::new(),
|
bounds: Vec::new(),
|
||||||
depth: 0,
|
depth: 0,
|
||||||
bounds_cache: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -117,12 +117,12 @@ fn main() {
|
||||||
// Parse data tree of scene file
|
// Parse data tree of scene file
|
||||||
println!("Parsing scene file...");
|
println!("Parsing scene file...");
|
||||||
t.tick();
|
t.tick();
|
||||||
let mut s = String::new();
|
let mut psy_contents = String::new();
|
||||||
let dt = if let Some(fp) = args.flag_input {
|
let dt = if let Some(fp) = args.flag_input {
|
||||||
let mut f = io::BufReader::new(File::open(fp).unwrap());
|
let mut f = io::BufReader::new(File::open(fp).unwrap());
|
||||||
let _ = f.read_to_string(&mut s);
|
let _ = f.read_to_string(&mut psy_contents);
|
||||||
|
|
||||||
DataTree::from_str(&s).unwrap()
|
DataTree::from_str(&psy_contents).unwrap()
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
};
|
};
|
||||||
|
@ -137,7 +137,10 @@ fn main() {
|
||||||
println!("Building scene...");
|
println!("Building scene...");
|
||||||
|
|
||||||
let mut arena = MemArena::new();
|
let mut arena = MemArena::new();
|
||||||
let mut r = parse_scene(&mut arena, child).unwrap();
|
let mut r = parse_scene(&mut arena, child).unwrap_or_else(|e| {
|
||||||
|
e.print(&psy_contents);
|
||||||
|
panic!("Parse error.");
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(spp) = args.flag_spp {
|
if let Some(spp) = args.flag_spp {
|
||||||
println!("\tOverriding scene spp: {}", spp);
|
println!("\tOverriding scene spp: {}", spp);
|
||||||
|
|
|
@ -11,11 +11,13 @@ pub enum DataTree<'a> {
|
||||||
type_name: &'a str,
|
type_name: &'a str,
|
||||||
ident: Option<&'a str>,
|
ident: Option<&'a str>,
|
||||||
children: Vec<DataTree<'a>>,
|
children: Vec<DataTree<'a>>,
|
||||||
|
byte_offset: usize,
|
||||||
},
|
},
|
||||||
|
|
||||||
Leaf {
|
Leaf {
|
||||||
type_name: &'a str,
|
type_name: &'a str,
|
||||||
contents: &'a str,
|
contents: &'a str,
|
||||||
|
byte_offset: usize,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +39,7 @@ impl<'a> DataTree<'a> {
|
||||||
type_name: "ROOT",
|
type_name: "ROOT",
|
||||||
ident: None,
|
ident: None,
|
||||||
children: items,
|
children: items,
|
||||||
|
byte_offset: 0,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// If the whole text wasn't parsed, something went wrong.
|
// If the whole text wasn't parsed, something went wrong.
|
||||||
|
@ -51,6 +54,13 @@ impl<'a> DataTree<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn byte_offset(&'a self) -> usize {
|
||||||
|
match self {
|
||||||
|
&DataTree::Internal { byte_offset, .. } => byte_offset,
|
||||||
|
&DataTree::Leaf { byte_offset, .. } => byte_offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_internal(&self) -> bool {
|
pub fn is_internal(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&DataTree::Internal { .. } => true,
|
&DataTree::Internal { .. } => true,
|
||||||
|
@ -128,14 +138,14 @@ impl<'a> DataTree<'a> {
|
||||||
|
|
||||||
// For unit tests
|
// For unit tests
|
||||||
fn internal_data_or_panic(&'a self) -> (&'a str, Option<&'a str>, &'a Vec<DataTree<'a>>) {
|
fn internal_data_or_panic(&'a self) -> (&'a str, Option<&'a str>, &'a Vec<DataTree<'a>>) {
|
||||||
if let DataTree::Internal { type_name, ident, ref children } = *self {
|
if let DataTree::Internal { type_name, ident, ref children, byte_offset: _ } = *self {
|
||||||
(type_name, ident, children)
|
(type_name, ident, children)
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected DataTree::Internal, found DataTree::Leaf")
|
panic!("Expected DataTree::Internal, found DataTree::Leaf")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn leaf_data_or_panic(&'a self) -> (&'a str, &'a str) {
|
fn leaf_data_or_panic(&'a self) -> (&'a str, &'a str) {
|
||||||
if let DataTree::Leaf { type_name, contents } = *self {
|
if let DataTree::Leaf { type_name, contents, byte_offset: _ } = *self {
|
||||||
(type_name, contents)
|
(type_name, contents)
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected DataTree::Leaf, found DataTree::Internal")
|
panic!("Expected DataTree::Leaf, found DataTree::Internal")
|
||||||
|
@ -179,14 +189,14 @@ pub struct DataTreeFilterInternalIter<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for DataTreeFilterInternalIter<'a> {
|
impl<'a> Iterator for DataTreeFilterInternalIter<'a> {
|
||||||
type Item = (&'a str, Option<&'a str>, &'a Vec<DataTree<'a>>);
|
type Item = (&'a str, Option<&'a str>, &'a Vec<DataTree<'a>>, usize);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<(&'a str, Option<&'a str>, &'a Vec<DataTree<'a>>)> {
|
fn next(&mut self) -> Option<(&'a str, Option<&'a str>, &'a Vec<DataTree<'a>>, usize)> {
|
||||||
loop {
|
loop {
|
||||||
match self.iter.next() {
|
match self.iter.next() {
|
||||||
Some(&DataTree::Internal { type_name, ident, ref children }) => {
|
Some(&DataTree::Internal { type_name, ident, ref children, byte_offset }) => {
|
||||||
if type_name == self.type_name {
|
if type_name == self.type_name {
|
||||||
return Some((type_name, ident, children));
|
return Some((type_name, ident, children, byte_offset));
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -214,18 +224,18 @@ pub struct DataTreeFilterLeafIter<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for DataTreeFilterLeafIter<'a> {
|
impl<'a> Iterator for DataTreeFilterLeafIter<'a> {
|
||||||
type Item = (&'a str, &'a str);
|
type Item = (&'a str, &'a str, usize);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<(&'a str, &'a str)> {
|
fn next(&mut self) -> Option<(&'a str, &'a str, usize)> {
|
||||||
loop {
|
loop {
|
||||||
match self.iter.next() {
|
match self.iter.next() {
|
||||||
Some(&DataTree::Internal { .. }) => {
|
Some(&DataTree::Internal { .. }) => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(&DataTree::Leaf { type_name, contents }) => {
|
Some(&DataTree::Leaf { type_name, contents, byte_offset }) => {
|
||||||
if type_name == self.type_name {
|
if type_name == self.type_name {
|
||||||
return Some((type_name, contents));
|
return Some((type_name, contents, byte_offset));
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -290,6 +300,7 @@ fn parse_node<'a>(source_text: (usize, &'a str)) -> ParseResult<'a> {
|
||||||
type_name: type_name,
|
type_name: type_name,
|
||||||
ident: Some(n),
|
ident: Some(n),
|
||||||
children: children,
|
children: children,
|
||||||
|
byte_offset: text1.0,
|
||||||
},
|
},
|
||||||
text4)));
|
text4)));
|
||||||
} else {
|
} else {
|
||||||
|
@ -314,6 +325,7 @@ fn parse_node<'a>(source_text: (usize, &'a str)) -> ParseResult<'a> {
|
||||||
type_name: type_name,
|
type_name: type_name,
|
||||||
ident: None,
|
ident: None,
|
||||||
children: children,
|
children: children,
|
||||||
|
byte_offset: text1.0,
|
||||||
},
|
},
|
||||||
text3)));
|
text3)));
|
||||||
} else {
|
} else {
|
||||||
|
@ -328,6 +340,7 @@ fn parse_node<'a>(source_text: (usize, &'a str)) -> ParseResult<'a> {
|
||||||
return Ok(Some((DataTree::Leaf {
|
return Ok(Some((DataTree::Leaf {
|
||||||
type_name: type_name,
|
type_name: type_name,
|
||||||
contents: contents,
|
contents: contents,
|
||||||
|
byte_offset: text1.0,
|
||||||
},
|
},
|
||||||
text4)));
|
text4)));
|
||||||
} else {
|
} else {
|
||||||
|
|
217
src/parse/psy.rs
217
src/parse/psy.rs
|
@ -21,10 +21,70 @@ use super::psy_assembly::parse_assembly;
|
||||||
use super::psy_light::parse_distant_disk_light;
|
use super::psy_light::parse_distant_disk_light;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PsyParseError {
|
pub enum PsyParseError {
|
||||||
UnknownError,
|
// The first usize for all errors is their byte offset
|
||||||
SectionWrongCount(&'static str, usize),
|
// into the psy content where they occured.
|
||||||
|
UnknownError(usize),
|
||||||
|
UnknownVariant(usize, &'static str), // Error message
|
||||||
|
ExpectedInternalNode(usize, &'static str), // Error message
|
||||||
|
ExpectedLeafNode(usize, &'static str), // Error message
|
||||||
|
MissingNode(usize, &'static str), // Error message
|
||||||
|
IncorrectLeafData(usize, &'static str), // Error message
|
||||||
|
WrongNodeCount(usize, &'static str, usize), // Error message, sections found
|
||||||
|
InstancedMissingData(usize, &'static str, String), // Error message, data name
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PsyParseError {
|
||||||
|
pub fn print(&self, psy_content: &str) {
|
||||||
|
match self {
|
||||||
|
&PsyParseError::UnknownError(offset) => {
|
||||||
|
let line = line_count_to_byte_offset(psy_content, offset);
|
||||||
|
println!("Line {}: Unknown parse error. If you get this message, please report \
|
||||||
|
it to the developers so they can improve the error messages.",
|
||||||
|
line);
|
||||||
|
}
|
||||||
|
|
||||||
|
&PsyParseError::UnknownVariant(offset, error) => {
|
||||||
|
let line = line_count_to_byte_offset(psy_content, offset);
|
||||||
|
println!("Line {}: {}", line, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
&PsyParseError::ExpectedInternalNode(offset, error) => {
|
||||||
|
let line = line_count_to_byte_offset(psy_content, offset);
|
||||||
|
println!("Line {}: {}", line, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
&PsyParseError::ExpectedLeafNode(offset, error) => {
|
||||||
|
let line = line_count_to_byte_offset(psy_content, offset);
|
||||||
|
println!("Line {}: {}", line, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
&PsyParseError::MissingNode(offset, error) => {
|
||||||
|
let line = line_count_to_byte_offset(psy_content, offset);
|
||||||
|
println!("Line {}: {}", line, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
&PsyParseError::IncorrectLeafData(offset, error) => {
|
||||||
|
let line = line_count_to_byte_offset(psy_content, offset);
|
||||||
|
println!("Line {}: {}", line, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
&PsyParseError::WrongNodeCount(offset, error, count) => {
|
||||||
|
let line = line_count_to_byte_offset(psy_content, offset);
|
||||||
|
println!("Line {}: {} Found: {}", line, error, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
&PsyParseError::InstancedMissingData(offset, error, ref data_name) => {
|
||||||
|
let line = line_count_to_byte_offset(psy_content, offset);
|
||||||
|
println!("Line {}: {} Data name: '{}'", line, error, data_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_count_to_byte_offset(text: &str, offset: usize) -> usize {
|
||||||
|
text[..offset].matches("\n").count() + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,23 +95,37 @@ pub fn parse_scene<'a>(arena: &'a MemArena,
|
||||||
// Verify we have the right number of each section
|
// Verify we have the right number of each section
|
||||||
if tree.iter_children_with_type("Output").count() != 1 {
|
if tree.iter_children_with_type("Output").count() != 1 {
|
||||||
let count = tree.iter_children_with_type("Output").count();
|
let count = tree.iter_children_with_type("Output").count();
|
||||||
return Err(PsyParseError::SectionWrongCount("Output", count));
|
return Err(PsyParseError::WrongNodeCount(tree.byte_offset(),
|
||||||
|
"Scene should have precisely one Output \
|
||||||
|
section.",
|
||||||
|
count));
|
||||||
}
|
}
|
||||||
if tree.iter_children_with_type("RenderSettings").count() != 1 {
|
if tree.iter_children_with_type("RenderSettings").count() != 1 {
|
||||||
let count = tree.iter_children_with_type("RenderSettings").count();
|
let count = tree.iter_children_with_type("RenderSettings").count();
|
||||||
return Err(PsyParseError::SectionWrongCount("RenderSettings", count));
|
return Err(PsyParseError::WrongNodeCount(tree.byte_offset(),
|
||||||
|
"Scene should have precisely one \
|
||||||
|
RenderSettings section.",
|
||||||
|
count));
|
||||||
}
|
}
|
||||||
if tree.iter_children_with_type("Camera").count() != 1 {
|
if tree.iter_children_with_type("Camera").count() != 1 {
|
||||||
let count = tree.iter_children_with_type("Camera").count();
|
let count = tree.iter_children_with_type("Camera").count();
|
||||||
return Err(PsyParseError::SectionWrongCount("Camera", count));
|
return Err(PsyParseError::WrongNodeCount(tree.byte_offset(),
|
||||||
|
"Scene should have precisely one Camera \
|
||||||
|
section.",
|
||||||
|
count));
|
||||||
}
|
}
|
||||||
if tree.iter_children_with_type("World").count() != 1 {
|
if tree.iter_children_with_type("World").count() != 1 {
|
||||||
let count = tree.iter_children_with_type("World").count();
|
let count = tree.iter_children_with_type("World").count();
|
||||||
return Err(PsyParseError::SectionWrongCount("World", count));
|
return Err(PsyParseError::WrongNodeCount(tree.byte_offset(),
|
||||||
|
"Scene should have precisely one World section.",
|
||||||
|
count));
|
||||||
}
|
}
|
||||||
if tree.iter_children_with_type("Assembly").count() != 1 {
|
if tree.iter_children_with_type("Assembly").count() != 1 {
|
||||||
let count = tree.iter_children_with_type("Assembly").count();
|
let count = tree.iter_children_with_type("Assembly").count();
|
||||||
return Err(PsyParseError::SectionWrongCount("Root Assembly", count));
|
return Err(PsyParseError::WrongNodeCount(tree.byte_offset(),
|
||||||
|
"Scene should have precisely one Root Assembly \
|
||||||
|
section.",
|
||||||
|
count));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse output info
|
// Parse output info
|
||||||
|
@ -114,16 +188,18 @@ fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> {
|
||||||
|
|
||||||
for child in children {
|
for child in children {
|
||||||
match child {
|
match child {
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Path" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Path" => {
|
||||||
// Trim and validate
|
// Trim and validate
|
||||||
let tc = contents.trim();
|
let tc = contents.trim();
|
||||||
if tc.chars().count() < 2 {
|
if tc.chars().count() < 2 {
|
||||||
// TODO: proper error
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
panic!();
|
"File path format is \
|
||||||
|
incorrect."));
|
||||||
}
|
}
|
||||||
if tc.chars().nth(0).unwrap() != '"' || tc.chars().last().unwrap() != '"' {
|
if tc.chars().nth(0).unwrap() != '"' || tc.chars().last().unwrap() != '"' {
|
||||||
// TODO: proper error
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
panic!();
|
"File paths must be \
|
||||||
|
surrounded by quotes."));
|
||||||
}
|
}
|
||||||
let len = tc.len();
|
let len = tc.len();
|
||||||
let tc = &tc[1..len - 1];
|
let tc = &tc[1..len - 1];
|
||||||
|
@ -141,10 +217,13 @@ fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> {
|
||||||
if found_path {
|
if found_path {
|
||||||
return Ok((path));
|
return Ok((path));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::MissingNode(tree.byte_offset(),
|
||||||
|
"Output section must contain a Path."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::ExpectedInternalNode(tree.byte_offset(),
|
||||||
|
"Output section should be an internal \
|
||||||
|
node, containing at least a Path."));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,35 +241,45 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP
|
||||||
for child in children {
|
for child in children {
|
||||||
match child {
|
match child {
|
||||||
// Resolution
|
// Resolution
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Resolution" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name ==
|
||||||
|
"Resolution" => {
|
||||||
if let IResult::Done(_, (w, h)) = closure!(terminated!(tuple!(ws_u32, ws_u32),
|
if let IResult::Done(_, (w, h)) = closure!(terminated!(tuple!(ws_u32, ws_u32),
|
||||||
nom::eof))(contents.as_bytes()) {
|
nom::eof))(contents.as_bytes()) {
|
||||||
found_res = true;
|
found_res = true;
|
||||||
res = (w, h);
|
res = (w, h);
|
||||||
} else {
|
} else {
|
||||||
// Found Resolution, but its contents is not in the right format
|
// Found Resolution, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
|
"Resolution should be specified with two \
|
||||||
|
integers in the form '[width height]'."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SamplesPerPixel
|
// SamplesPerPixel
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "SamplesPerPixel" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name ==
|
||||||
|
"SamplesPerPixel" => {
|
||||||
if let IResult::Done(_, n) = ws_u32(contents.as_bytes()) {
|
if let IResult::Done(_, n) = ws_u32(contents.as_bytes()) {
|
||||||
found_spp = true;
|
found_spp = true;
|
||||||
spp = n;
|
spp = n;
|
||||||
} else {
|
} else {
|
||||||
// Found SamplesPerPixel, but its contents is not in the right format
|
// Found SamplesPerPixel, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
|
"SamplesPerPixel should be \
|
||||||
|
an integer specified in \
|
||||||
|
the form '[samples]'."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seed
|
// Seed
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Seed" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Seed" => {
|
||||||
if let IResult::Done(_, n) = ws_u32(contents.as_bytes()) {
|
if let IResult::Done(_, n) = ws_u32(contents.as_bytes()) {
|
||||||
seed = n;
|
seed = n;
|
||||||
} else {
|
} else {
|
||||||
// Found Seed, but its contents is not in the right format
|
// Found Seed, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
|
"Seed should be an integer \
|
||||||
|
specified in the form \
|
||||||
|
'[samples]'."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,10 +290,15 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP
|
||||||
if found_res && found_spp {
|
if found_res && found_spp {
|
||||||
return Ok((res, spp, seed));
|
return Ok((res, spp, seed));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::MissingNode(tree.byte_offset(),
|
||||||
|
"RenderSettings must have both Resolution and \
|
||||||
|
SamplesPerPixel specified."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::ExpectedInternalNode(tree.byte_offset(),
|
||||||
|
"RenderSettings section should be an \
|
||||||
|
internal node, containing at least \
|
||||||
|
Resolution and SamplesPerPixel."));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,42 +316,54 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<Camera<'a
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
match child {
|
match child {
|
||||||
// Fov
|
// Fov
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Fov" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Fov" => {
|
||||||
if let IResult::Done(_, fov) = ws_f32(contents.as_bytes()) {
|
if let IResult::Done(_, fov) = ws_f32(contents.as_bytes()) {
|
||||||
fovs.push(fov * (3.1415926536 / 180.0));
|
fovs.push(fov * (3.1415926536 / 180.0));
|
||||||
} else {
|
} else {
|
||||||
// Found Fov, but its contents is not in the right format
|
// Found Fov, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
|
"Fov should be a decimal \
|
||||||
|
number specified in the \
|
||||||
|
form '[fov]'."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FocalDistance
|
// FocalDistance
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "FocalDistance" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name ==
|
||||||
|
"FocalDistance" => {
|
||||||
if let IResult::Done(_, fd) = ws_f32(contents.as_bytes()) {
|
if let IResult::Done(_, fd) = ws_f32(contents.as_bytes()) {
|
||||||
focus_distances.push(fd);
|
focus_distances.push(fd);
|
||||||
} else {
|
} else {
|
||||||
// Found FocalDistance, but its contents is not in the right format
|
// Found FocalDistance, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
|
"FocalDistance should be a \
|
||||||
|
decimal number specified \
|
||||||
|
in the form '[fov]'."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApertureRadius
|
// ApertureRadius
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "ApertureRadius" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name ==
|
||||||
|
"ApertureRadius" => {
|
||||||
if let IResult::Done(_, ar) = ws_f32(contents.as_bytes()) {
|
if let IResult::Done(_, ar) = ws_f32(contents.as_bytes()) {
|
||||||
aperture_radii.push(ar);
|
aperture_radii.push(ar);
|
||||||
} else {
|
} else {
|
||||||
// Found ApertureRadius, but its contents is not in the right format
|
// Found ApertureRadius, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
|
"ApertureRadius should be a \
|
||||||
|
decimal number specified \
|
||||||
|
in the form '[fov]'."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform
|
// Transform
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Transform" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name ==
|
||||||
|
"Transform" => {
|
||||||
if let Ok(mat) = parse_matrix(contents) {
|
if let Ok(mat) = parse_matrix(contents) {
|
||||||
mats.push(mat);
|
mats.push(mat);
|
||||||
} else {
|
} else {
|
||||||
// Found Transform, but its contents is not in the right format
|
// Found Transform, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(make_transform_format_error(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +373,10 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<Camera<'a
|
||||||
|
|
||||||
return Ok(Camera::new(arena, mats, fovs, aperture_radii, focus_distances));
|
return Ok(Camera::new(arena, mats, fovs, aperture_radii, focus_distances));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::ExpectedInternalNode(tree.byte_offset(),
|
||||||
|
"Camera section should be an internal \
|
||||||
|
node, containing at least Fov and \
|
||||||
|
Transform."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,13 +391,19 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<World<'a>,
|
||||||
// Parse background shader
|
// Parse background shader
|
||||||
let bgs = {
|
let bgs = {
|
||||||
if tree.iter_children_with_type("BackgroundShader").count() != 1 {
|
if tree.iter_children_with_type("BackgroundShader").count() != 1 {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::WrongNodeCount(tree.byte_offset(),
|
||||||
|
"World should have precisely one BackgroundShader section.",
|
||||||
|
tree.iter_children_with_type("BackgroundShader").count()));
|
||||||
}
|
}
|
||||||
tree.iter_children_with_type("BackgroundShader").nth(0).unwrap()
|
tree.iter_children_with_type("BackgroundShader").nth(0).unwrap()
|
||||||
};
|
};
|
||||||
let bgs_type = {
|
let bgs_type = {
|
||||||
if bgs.iter_children_with_type("Type").count() != 1 {
|
if bgs.iter_children_with_type("Type").count() != 1 {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::WrongNodeCount(bgs.byte_offset(),
|
||||||
|
"BackgroundShader should have \
|
||||||
|
precisely one Type specified.",
|
||||||
|
bgs.iter_children_with_type("Type")
|
||||||
|
.count()));
|
||||||
}
|
}
|
||||||
if let &DataTree::Leaf { contents, .. } =
|
if let &DataTree::Leaf { contents, .. } =
|
||||||
bgs.iter_children_with_type("Type")
|
bgs.iter_children_with_type("Type")
|
||||||
|
@ -296,12 +411,14 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<World<'a>,
|
||||||
.unwrap() {
|
.unwrap() {
|
||||||
contents.trim()
|
contents.trim()
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::ExpectedLeafNode(bgs.byte_offset(),
|
||||||
|
"BackgroundShader's Type should be a \
|
||||||
|
leaf node."));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match bgs_type {
|
match bgs_type {
|
||||||
"Color" => {
|
"Color" => {
|
||||||
if let Some(&DataTree::Leaf { contents, .. }) =
|
if let Some(&DataTree::Leaf { contents, byte_offset, .. }) =
|
||||||
bgs.iter_children_with_type("Color")
|
bgs.iter_children_with_type("Color")
|
||||||
.nth(0) {
|
.nth(0) {
|
||||||
if let IResult::Done(_, color) =
|
if let IResult::Done(_, color) =
|
||||||
|
@ -311,14 +428,23 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<World<'a>,
|
||||||
// rec.709.
|
// rec.709.
|
||||||
background_color = XYZ::from_tuple(rec709e_to_xyz(color));
|
background_color = XYZ::from_tuple(rec709e_to_xyz(color));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
|
"Color should be specified \
|
||||||
|
with three decimal numbers \
|
||||||
|
in the form '[R G B]'."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::MissingNode(bgs.byte_offset(),
|
||||||
|
"BackgroundShader's Type is Color, \
|
||||||
|
but no Color is specified."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => return Err(PsyParseError::UnknownError),
|
_ => {
|
||||||
|
return Err(PsyParseError::UnknownVariant(bgs.byte_offset(),
|
||||||
|
"The specified BackgroundShader Type \
|
||||||
|
isn't a recognized type."))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse light sources
|
// Parse light sources
|
||||||
|
@ -338,7 +464,10 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<World<'a>,
|
||||||
lights: arena.copy_slice(&lights),
|
lights: arena.copy_slice(&lights),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::ExpectedInternalNode(tree.byte_offset(),
|
||||||
|
"World section should be an internal \
|
||||||
|
node, containing at least a \
|
||||||
|
BackgroundShader."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,6 +510,12 @@ pub fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
|
||||||
ns.11,
|
ns.11,
|
||||||
ns.15));
|
ns.15));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError {
|
||||||
|
return PsyParseError::IncorrectLeafData(byte_offset,
|
||||||
|
"Transform should be sixteen integers specified in \
|
||||||
|
the form '[# # # # # # # # # # # # # # # #]'.");
|
||||||
|
}
|
||||||
|
|
|
@ -25,8 +25,7 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
||||||
builder.add_assembly(ident, parse_assembly(arena, &child)?);
|
builder.add_assembly(ident, parse_assembly(arena, &child)?);
|
||||||
} else {
|
} else {
|
||||||
// TODO: error condition of some kind, because no ident
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
||||||
panic!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,22 +33,20 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
"Instance" => {
|
"Instance" => {
|
||||||
// Pre-conditions
|
// Pre-conditions
|
||||||
if !child.is_internal() {
|
if !child.is_internal() {
|
||||||
// TODO: proper error
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
||||||
panic!();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get data name
|
// Get data name
|
||||||
let name = {
|
let name = {
|
||||||
if child.iter_leaf_children_with_type("Data").count() != 1 {
|
if child.iter_leaf_children_with_type("Data").count() != 1 {
|
||||||
// TODO: proper error message
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
||||||
panic!();
|
|
||||||
}
|
}
|
||||||
child.iter_leaf_children_with_type("Data").nth(0).unwrap().1
|
child.iter_leaf_children_with_type("Data").nth(0).unwrap().1
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get xforms
|
// Get xforms
|
||||||
let mut xforms = Vec::new();
|
let mut xforms = Vec::new();
|
||||||
for (_, contents) in child.iter_leaf_children_with_type("Transform") {
|
for (_, contents, _) in child.iter_leaf_children_with_type("Transform") {
|
||||||
xforms.push(parse_matrix(contents)?);
|
xforms.push(parse_matrix(contents)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +54,13 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
if builder.name_exists(name) {
|
if builder.name_exists(name) {
|
||||||
builder.add_instance(name, Some(&xforms));
|
builder.add_instance(name, Some(&xforms));
|
||||||
} else {
|
} else {
|
||||||
// TODO: proper error message
|
return Err(PsyParseError::InstancedMissingData(
|
||||||
panic!("Attempted to add instance for data with a name that doesn't \
|
child.iter_leaf_children_with_type("Data").nth(0).unwrap().2,
|
||||||
exist.");
|
"Attempted to add \
|
||||||
|
instance for data with \
|
||||||
|
a name that doesn't \
|
||||||
|
exist.",
|
||||||
|
name.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +73,9 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
)));
|
)));
|
||||||
} else {
|
} else {
|
||||||
// TODO: error condition of some kind, because no ident
|
// TODO: error condition of some kind, because no ident
|
||||||
panic!();
|
panic!("MeshSurface encountered that was a leaf, but MeshSurfaces cannot \
|
||||||
|
be a leaf: {}",
|
||||||
|
child.byte_offset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +87,8 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
parse_sphere_light(arena, &child)?
|
parse_sphere_light(arena, &child)?
|
||||||
)));
|
)));
|
||||||
} else {
|
} else {
|
||||||
// TODO: error condition of some kind, because no ident
|
// No ident
|
||||||
panic!();
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,8 +100,8 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
parse_rectangle_light(arena, &child)?
|
parse_rectangle_light(arena, &child)?
|
||||||
)));
|
)));
|
||||||
} else {
|
} else {
|
||||||
// TODO: error condition of some kind, because no ident
|
// No ident
|
||||||
panic!();
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,8 +111,8 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
// TODO
|
// TODO
|
||||||
//unimplemented!()
|
//unimplemented!()
|
||||||
} else {
|
} else {
|
||||||
// TODO: error condition of some kind, because no ident
|
// No ident
|
||||||
panic!();
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +148,7 @@ pub fn parse_assembly<'a>(arena: &'a MemArena,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(builder.build());
|
return Ok(builder.build());
|
||||||
|
|
|
@ -27,28 +27,29 @@ pub fn parse_distant_disk_light<'a>(arena: &'a MemArena,
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
match child {
|
match child {
|
||||||
// Radius
|
// Radius
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Radius" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Radius" => {
|
||||||
if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) {
|
if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) {
|
||||||
radii.push(radius);
|
radii.push(radius);
|
||||||
} else {
|
} else {
|
||||||
// Found radius, but its contents is not in the right format
|
// Found radius, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direction
|
// Direction
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Direction" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name ==
|
||||||
|
"Direction" => {
|
||||||
if let IResult::Done(_, direction) =
|
if let IResult::Done(_, direction) =
|
||||||
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) {
|
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) {
|
||||||
directions.push(Vector::new(direction.0, direction.1, direction.2));
|
directions.push(Vector::new(direction.0, direction.1, direction.2));
|
||||||
} else {
|
} else {
|
||||||
// Found color, but its contents is not in the right format
|
// Found direction, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Color" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Color" => {
|
||||||
if let IResult::Done(_, color) =
|
if let IResult::Done(_, color) =
|
||||||
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) {
|
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) {
|
||||||
// TODO: handle color space conversions properly.
|
// TODO: handle color space conversions properly.
|
||||||
|
@ -57,7 +58,7 @@ pub fn parse_distant_disk_light<'a>(arena: &'a MemArena,
|
||||||
colors.push(XYZ::from_tuple(rec709e_to_xyz(color)));
|
colors.push(XYZ::from_tuple(rec709e_to_xyz(color)));
|
||||||
} else {
|
} else {
|
||||||
// Found color, but its contents is not in the right format
|
// Found color, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ pub fn parse_distant_disk_light<'a>(arena: &'a MemArena,
|
||||||
|
|
||||||
return Ok(DistantDiskLight::new(arena, radii, directions, colors));
|
return Ok(DistantDiskLight::new(arena, radii, directions, colors));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,17 +84,17 @@ pub fn parse_sphere_light<'a>(arena: &'a MemArena,
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
match child {
|
match child {
|
||||||
// Radius
|
// Radius
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Radius" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Radius" => {
|
||||||
if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) {
|
if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) {
|
||||||
radii.push(radius);
|
radii.push(radius);
|
||||||
} else {
|
} else {
|
||||||
// Found radius, but its contents is not in the right format
|
// Found radius, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Color" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Color" => {
|
||||||
if let IResult::Done(_, color) =
|
if let IResult::Done(_, color) =
|
||||||
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) {
|
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) {
|
||||||
// TODO: handle color space conversions properly.
|
// TODO: handle color space conversions properly.
|
||||||
|
@ -102,7 +103,7 @@ pub fn parse_sphere_light<'a>(arena: &'a MemArena,
|
||||||
colors.push(XYZ::from_tuple(rec709e_to_xyz(color)));
|
colors.push(XYZ::from_tuple(rec709e_to_xyz(color)));
|
||||||
} else {
|
} else {
|
||||||
// Found color, but its contents is not in the right format
|
// Found color, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +113,7 @@ pub fn parse_sphere_light<'a>(arena: &'a MemArena,
|
||||||
|
|
||||||
return Ok(SphereLight::new(arena, radii, colors));
|
return Ok(SphereLight::new(arena, radii, colors));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,18 +128,19 @@ pub fn parse_rectangle_light<'a>(arena: &'a MemArena,
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
match child {
|
match child {
|
||||||
// Dimensions
|
// Dimensions
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Dimensions" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name ==
|
||||||
|
"Dimensions" => {
|
||||||
if let IResult::Done(_, radius) =
|
if let IResult::Done(_, radius) =
|
||||||
closure!(tuple!(ws_f32, ws_f32))(contents.as_bytes()) {
|
closure!(tuple!(ws_f32, ws_f32))(contents.as_bytes()) {
|
||||||
dimensions.push(radius);
|
dimensions.push(radius);
|
||||||
} else {
|
} else {
|
||||||
// Found dimensions, but its contents is not in the right format
|
// Found dimensions, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
&DataTree::Leaf { type_name, contents } if type_name == "Color" => {
|
&DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Color" => {
|
||||||
if let IResult::Done(_, color) =
|
if let IResult::Done(_, color) =
|
||||||
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) {
|
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) {
|
||||||
// TODO: handle color space conversions properly.
|
// TODO: handle color space conversions properly.
|
||||||
|
@ -147,7 +149,7 @@ pub fn parse_rectangle_light<'a>(arena: &'a MemArena,
|
||||||
colors.push(XYZ::from_tuple(rec709e_to_xyz(color)));
|
colors.push(XYZ::from_tuple(rec709e_to_xyz(color)));
|
||||||
} else {
|
} else {
|
||||||
// Found color, but its contents is not in the right format
|
// Found color, but its contents is not in the right format
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +159,6 @@ pub fn parse_rectangle_light<'a>(arena: &'a MemArena,
|
||||||
|
|
||||||
return Ok(RectangleLight::new(arena, dimensions, colors));
|
return Ok(RectangleLight::new(arena, dimensions, colors));
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError);
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub fn parse_mesh_surface<'a>(arena: &'a MemArena,
|
||||||
// Get verts
|
// Get verts
|
||||||
let mut time_samples = 0;
|
let mut time_samples = 0;
|
||||||
let mut first_vert_count = None;
|
let mut first_vert_count = None;
|
||||||
for (_, text) in tree.iter_leaf_children_with_type("Vertices") {
|
for (_, text, _) in tree.iter_leaf_children_with_type("Vertices") {
|
||||||
let mut raw_text = text.trim().as_bytes();
|
let mut raw_text = text.trim().as_bytes();
|
||||||
|
|
||||||
// Collect verts for this time sample
|
// Collect verts for this time sample
|
||||||
|
@ -58,7 +58,7 @@ pub fn parse_mesh_surface<'a>(arena: &'a MemArena,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get face vert counts
|
// Get face vert counts
|
||||||
if let Some((_, text)) = tree.iter_leaf_children_with_type("FaceVertCounts").nth(0) {
|
if let Some((_, text, _)) = tree.iter_leaf_children_with_type("FaceVertCounts").nth(0) {
|
||||||
let mut raw_text = text.trim().as_bytes();
|
let mut raw_text = text.trim().as_bytes();
|
||||||
|
|
||||||
while let IResult::Done(remaining, count) = ws_usize(raw_text) {
|
while let IResult::Done(remaining, count) = ws_usize(raw_text) {
|
||||||
|
@ -69,7 +69,7 @@ pub fn parse_mesh_surface<'a>(arena: &'a MemArena,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get face vert indices
|
// Get face vert indices
|
||||||
if let Some((_, text)) = tree.iter_leaf_children_with_type("FaceVertIndices").nth(0) {
|
if let Some((_, text, _)) = tree.iter_leaf_children_with_type("FaceVertIndices").nth(0) {
|
||||||
let mut raw_text = text.trim().as_bytes();
|
let mut raw_text = text.trim().as_bytes();
|
||||||
|
|
||||||
while let IResult::Done(remaining, index) = ws_usize(raw_text) {
|
while let IResult::Done(remaining, index) = ws_usize(raw_text) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user