From 6623443e2ef43641fb0f899b0766e73e3c95add6 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Mon, 10 Apr 2017 14:03:01 -0700 Subject: [PATCH] Improved .psy file parsing error messages. Biggest improvement: it gives you line numbers. But also progress on better descriptions. --- src/accel/light_tree.rs | 2 - src/main.rs | 11 +- src/parse/data_tree.rs | 33 ++++-- src/parse/psy.rs | 217 +++++++++++++++++++++++++++------- src/parse/psy_assembly.rs | 39 +++--- src/parse/psy_light.rs | 38 +++--- src/parse/psy_mesh_surface.rs | 6 +- 7 files changed, 250 insertions(+), 96 deletions(-) diff --git a/src/accel/light_tree.rs b/src/accel/light_tree.rs index 5bdb668..bf7fc43 100644 --- a/src/accel/light_tree.rs +++ b/src/accel/light_tree.rs @@ -140,7 +140,6 @@ struct LightTreeBuilder { nodes: Vec, bounds: Vec, depth: usize, - bounds_cache: Vec, } impl LightTreeBuilder { @@ -149,7 +148,6 @@ impl LightTreeBuilder { nodes: Vec::new(), bounds: Vec::new(), depth: 0, - bounds_cache: Vec::new(), } } diff --git a/src/main.rs b/src/main.rs index 191cbb6..1c85eab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -117,12 +117,12 @@ fn main() { // Parse data tree of scene file println!("Parsing scene file..."); t.tick(); - let mut s = String::new(); + let mut psy_contents = String::new(); let dt = if let Some(fp) = args.flag_input { 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 { panic!() }; @@ -137,7 +137,10 @@ fn main() { println!("Building scene..."); 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 { println!("\tOverriding scene spp: {}", spp); diff --git a/src/parse/data_tree.rs b/src/parse/data_tree.rs index c1cb739..bee4485 100644 --- a/src/parse/data_tree.rs +++ b/src/parse/data_tree.rs @@ -11,11 +11,13 @@ pub enum DataTree<'a> { type_name: &'a str, ident: Option<&'a str>, children: Vec>, + byte_offset: usize, }, Leaf { type_name: &'a str, contents: &'a str, + byte_offset: usize, }, } @@ -37,6 +39,7 @@ impl<'a> DataTree<'a> { type_name: "ROOT", ident: None, children: items, + byte_offset: 0, }); } else { // 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 { match self { &DataTree::Internal { .. } => true, @@ -128,14 +138,14 @@ impl<'a> DataTree<'a> { // For unit tests fn internal_data_or_panic(&'a self) -> (&'a str, Option<&'a str>, &'a Vec>) { - 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) } else { panic!("Expected DataTree::Internal, found DataTree::Leaf") } } 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) } else { panic!("Expected DataTree::Leaf, found DataTree::Internal") @@ -179,14 +189,14 @@ pub struct DataTreeFilterInternalIter<'a> { } impl<'a> Iterator for DataTreeFilterInternalIter<'a> { - type Item = (&'a str, Option<&'a str>, &'a Vec>); + type Item = (&'a str, Option<&'a str>, &'a Vec>, usize); - fn next(&mut self) -> Option<(&'a str, Option<&'a str>, &'a Vec>)> { + fn next(&mut self) -> Option<(&'a str, Option<&'a str>, &'a Vec>, usize)> { loop { 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 { - return Some((type_name, ident, children)); + return Some((type_name, ident, children, byte_offset)); } else { continue; } @@ -214,18 +224,18 @@ pub struct 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 { match self.iter.next() { Some(&DataTree::Internal { .. }) => { continue; } - Some(&DataTree::Leaf { type_name, contents }) => { + Some(&DataTree::Leaf { type_name, contents, byte_offset }) => { if type_name == self.type_name { - return Some((type_name, contents)); + return Some((type_name, contents, byte_offset)); } else { continue; } @@ -290,6 +300,7 @@ fn parse_node<'a>(source_text: (usize, &'a str)) -> ParseResult<'a> { type_name: type_name, ident: Some(n), children: children, + byte_offset: text1.0, }, text4))); } else { @@ -314,6 +325,7 @@ fn parse_node<'a>(source_text: (usize, &'a str)) -> ParseResult<'a> { type_name: type_name, ident: None, children: children, + byte_offset: text1.0, }, text3))); } else { @@ -328,6 +340,7 @@ fn parse_node<'a>(source_text: (usize, &'a str)) -> ParseResult<'a> { return Ok(Some((DataTree::Leaf { type_name: type_name, contents: contents, + byte_offset: text1.0, }, text4))); } else { diff --git a/src/parse/psy.rs b/src/parse/psy.rs index 9fdc817..bd9c1b8 100644 --- a/src/parse/psy.rs +++ b/src/parse/psy.rs @@ -21,10 +21,70 @@ use super::psy_assembly::parse_assembly; use super::psy_light::parse_distant_disk_light; -#[derive(Copy, Clone, Debug)] +#[derive(Debug)] pub enum PsyParseError { - UnknownError, - SectionWrongCount(&'static str, usize), + // The first usize for all errors is their byte offset + // 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 if tree.iter_children_with_type("Output").count() != 1 { 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 { 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 { 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 { 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 { 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 @@ -114,16 +188,18 @@ fn parse_output_info(tree: &DataTree) -> Result { for child in children { 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 let tc = contents.trim(); if tc.chars().count() < 2 { - // TODO: proper error - panic!(); + return Err(PsyParseError::IncorrectLeafData(byte_offset, + "File path format is \ + incorrect.")); } if tc.chars().nth(0).unwrap() != '"' || tc.chars().last().unwrap() != '"' { - // TODO: proper error - panic!(); + return Err(PsyParseError::IncorrectLeafData(byte_offset, + "File paths must be \ + surrounded by quotes.")); } let len = tc.len(); let tc = &tc[1..len - 1]; @@ -141,10 +217,13 @@ fn parse_output_info(tree: &DataTree) -> Result { if found_path { return Ok((path)); } else { - return Err(PsyParseError::UnknownError); + return Err(PsyParseError::MissingNode(tree.byte_offset(), + "Output section must contain a Path.")); } } 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 { match child { // 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), nom::eof))(contents.as_bytes()) { found_res = true; res = (w, h); } else { // 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 - &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()) { found_spp = true; spp = n; } else { // 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 - &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()) { seed = n; } else { // 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 { return Ok((res, spp, seed)); } else { - return Err(PsyParseError::UnknownError); + return Err(PsyParseError::MissingNode(tree.byte_offset(), + "RenderSettings must have both Resolution and \ + SamplesPerPixel specified.")); } } 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 { + &DataTree::Leaf { type_name, contents, byte_offset } if type_name == "Fov" => { if let IResult::Done(_, fov) = ws_f32(contents.as_bytes()) { fovs.push(fov * (3.1415926536 / 180.0)); } else { // 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 - &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()) { focus_distances.push(fd); } else { // 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 - &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()) { aperture_radii.push(ar); } else { // 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 - &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) { mats.push(mat); } else { // 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(arena: &'a MemArena, tree: &'a DataTree) -> Result, // Parse background shader let bgs = { 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() }; let bgs_type = { 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, .. } = bgs.iter_children_with_type("Type") @@ -296,12 +411,14 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, .unwrap() { contents.trim() } else { - return Err(PsyParseError::UnknownError); + return Err(PsyParseError::ExpectedLeafNode(bgs.byte_offset(), + "BackgroundShader's Type should be a \ + leaf node.")); } }; match bgs_type { "Color" => { - if let Some(&DataTree::Leaf { contents, .. }) = + if let Some(&DataTree::Leaf { contents, byte_offset, .. }) = bgs.iter_children_with_type("Color") .nth(0) { if let IResult::Done(_, color) = @@ -311,14 +428,23 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, // rec.709. background_color = XYZ::from_tuple(rec709e_to_xyz(color)); } 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 { - 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 @@ -338,7 +464,10 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, lights: arena.copy_slice(&lights), }); } 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 { ns.11, ns.15)); } 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 '[# # # # # # # # # # # # # # # #]'."); +} diff --git a/src/parse/psy_assembly.rs b/src/parse/psy_assembly.rs index 5e3289f..36e3538 100644 --- a/src/parse/psy_assembly.rs +++ b/src/parse/psy_assembly.rs @@ -25,8 +25,7 @@ pub fn parse_assembly<'a>(arena: &'a MemArena, if let &DataTree::Internal { ident: Some(ident), .. } = child { builder.add_assembly(ident, parse_assembly(arena, &child)?); } else { - // TODO: error condition of some kind, because no ident - panic!(); + return Err(PsyParseError::UnknownError(child.byte_offset())); } } @@ -34,22 +33,20 @@ pub fn parse_assembly<'a>(arena: &'a MemArena, "Instance" => { // Pre-conditions if !child.is_internal() { - // TODO: proper error - panic!(); + return Err(PsyParseError::UnknownError(child.byte_offset())); } // Get data name let name = { if child.iter_leaf_children_with_type("Data").count() != 1 { - // TODO: proper error message - panic!(); + return Err(PsyParseError::UnknownError(child.byte_offset())); } child.iter_leaf_children_with_type("Data").nth(0).unwrap().1 }; // Get xforms 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)?); } @@ -57,9 +54,13 @@ pub fn parse_assembly<'a>(arena: &'a MemArena, if builder.name_exists(name) { builder.add_instance(name, Some(&xforms)); } else { - // TODO: proper error message - panic!("Attempted to add instance for data with a name that doesn't \ - exist."); + return Err(PsyParseError::InstancedMissingData( + child.iter_leaf_children_with_type("Data").nth(0).unwrap().2, + "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 { // 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)? ))); } else { - // TODO: error condition of some kind, because no ident - panic!(); + // No ident + return Err(PsyParseError::UnknownError(child.byte_offset())); } } @@ -97,8 +100,8 @@ pub fn parse_assembly<'a>(arena: &'a MemArena, parse_rectangle_light(arena, &child)? ))); } else { - // TODO: error condition of some kind, because no ident - panic!(); + // No ident + return Err(PsyParseError::UnknownError(child.byte_offset())); } } @@ -108,8 +111,8 @@ pub fn parse_assembly<'a>(arena: &'a MemArena, // TODO //unimplemented!() } else { - // TODO: error condition of some kind, because no ident - panic!(); + // No ident + return Err(PsyParseError::UnknownError(child.byte_offset())); } } @@ -145,7 +148,7 @@ pub fn parse_assembly<'a>(arena: &'a MemArena, } } } else { - return Err(PsyParseError::UnknownError); + return Err(PsyParseError::UnknownError(tree.byte_offset())); } return Ok(builder.build()); diff --git a/src/parse/psy_light.rs b/src/parse/psy_light.rs index 91b081c..dd2c90c 100644 --- a/src/parse/psy_light.rs +++ b/src/parse/psy_light.rs @@ -27,28 +27,29 @@ pub fn parse_distant_disk_light<'a>(arena: &'a MemArena, for child in children.iter() { match child { // 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()) { radii.push(radius); } else { // Found radius, but its contents is not in the right format - return Err(PsyParseError::UnknownError); + return Err(PsyParseError::UnknownError(byte_offset)); } } // 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) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) { directions.push(Vector::new(direction.0, direction.1, direction.2)); } else { - // Found color, but its contents is not in the right format - return Err(PsyParseError::UnknownError); + // Found direction, but its contents is not in the right format + return Err(PsyParseError::UnknownError(byte_offset)); } } // 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) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) { // 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))); } else { // 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)); } 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() { match child { // 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()) { radii.push(radius); } else { // Found radius, but its contents is not in the right format - return Err(PsyParseError::UnknownError); + return Err(PsyParseError::UnknownError(byte_offset)); } } // 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) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) { // 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))); } else { // 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)); } 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() { match child { // 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) = closure!(tuple!(ws_f32, ws_f32))(contents.as_bytes()) { dimensions.push(radius); } else { // Found dimensions, but its contents is not in the right format - return Err(PsyParseError::UnknownError); + return Err(PsyParseError::UnknownError(byte_offset)); } } // 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) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) { // 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))); } else { // 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)); } else { - return Err(PsyParseError::UnknownError); + return Err(PsyParseError::UnknownError(tree.byte_offset())); } } diff --git a/src/parse/psy_mesh_surface.rs b/src/parse/psy_mesh_surface.rs index c3d7c01..ae5eb97 100644 --- a/src/parse/psy_mesh_surface.rs +++ b/src/parse/psy_mesh_surface.rs @@ -34,7 +34,7 @@ pub fn parse_mesh_surface<'a>(arena: &'a MemArena, // Get verts let mut time_samples = 0; 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(); // Collect verts for this time sample @@ -58,7 +58,7 @@ pub fn parse_mesh_surface<'a>(arena: &'a MemArena, } // 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(); 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 - 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(); while let IResult::Done(remaining, index) = ws_usize(raw_text) {