Parse errors now use Strings for error messages.

This allows the error messages to be more informative by including
dynamically determined information.

Also made a utility function for ensuring that nodes get closed.
This commit is contained in:
Nathan Vegdahl 2020-01-11 07:26:21 +09:00
parent 4f564d1474
commit 6b188c4451
8 changed files with 170 additions and 516 deletions

View File

@ -1,377 +0,0 @@
#![allow(dead_code)]
use std::{io::Cursor, iter::Iterator, result::Result, slice};
use data_tree::{reader::DataTreeReader, Event};
#[derive(Debug, Eq, PartialEq)]
pub enum DataTree {
Internal {
type_name: String,
ident: Option<String>,
children: Vec<DataTree>,
byte_offset: usize,
},
Leaf {
type_name: String,
contents: String,
byte_offset: usize,
},
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum ParseError {
Other(&'static str),
}
// #[derive(Copy, Clone, Eq, PartialEq, Debug)]
// pub enum ParseError {
// MissingOpener(usize),
// MissingOpenInternal(usize),
// MissingCloseInternal(usize),
// MissingOpenLeaf(usize),
// MissingCloseLeaf(usize),
// MissingTypeName(usize),
// UnexpectedIdent(usize),
// UnknownToken(usize),
// Other((usize, &'static str)),
// }
impl<'a> DataTree {
pub fn from_str(source_text: &'a str) -> Result<DataTree, ParseError> {
let mut parser = DataTreeReader::new(Cursor::new(source_text));
let mut items = Vec::new();
loop {
let event = parser.next_event();
match event {
Ok(Event::InnerOpen {
type_name,
ident,
byte_offset,
}) => {
let type_name = type_name.into();
let ident = ident.map(|id| id.into());
items.push(parse_node(&mut parser, type_name, ident, byte_offset)?);
}
Ok(Event::Leaf {
type_name,
contents,
byte_offset,
}) => return Err(ParseError::Other("Unexpected leaf value at root level.")),
Ok(Event::InnerClose { .. }) => {
return Err(ParseError::Other("Unexpected closing tag."))
}
Ok(Event::ValidEnd) => {
break;
}
Ok(Event::NeedMoreInput) | Err(_) => {
return Err(ParseError::Other("Some error happened."))
}
}
}
return Ok(DataTree::Internal {
type_name: "ROOT".into(),
ident: None,
children: items,
byte_offset: 0,
});
}
pub fn type_name(&'a self) -> &'a str {
match self {
DataTree::Internal { type_name, .. } | DataTree::Leaf { type_name, .. } => type_name,
}
}
pub fn ident(&'a self) -> Option<&'a str> {
match self {
DataTree::Internal {
ident: Some(id), ..
} => Some(id.as_str()),
_ => None,
}
}
pub fn byte_offset(&'a self) -> usize {
match self {
DataTree::Internal { byte_offset, .. } | DataTree::Leaf { byte_offset, .. } => {
*byte_offset
}
}
}
pub fn is_internal(&self) -> bool {
match self {
DataTree::Internal { .. } => true,
DataTree::Leaf { .. } => false,
}
}
pub fn is_leaf(&self) -> bool {
match self {
DataTree::Internal { .. } => false,
DataTree::Leaf { .. } => true,
}
}
pub fn leaf_contents(&'a self) -> Option<&'a str> {
match self {
DataTree::Internal { .. } => None,
DataTree::Leaf { contents, .. } => Some(contents.as_str()),
}
}
pub fn iter_children(&'a self) -> slice::Iter<'a, DataTree> {
if let DataTree::Internal { ref children, .. } = self {
children.iter()
} else {
[].iter()
}
}
pub fn iter_children_with_type(&'a self, type_name: &'static str) -> DataTreeFilterIter<'a> {
if let DataTree::Internal { ref children, .. } = self {
DataTreeFilterIter {
type_name: type_name,
iter: children.iter(),
}
} else {
DataTreeFilterIter {
type_name: type_name,
iter: [].iter(),
}
}
}
pub fn iter_internal_children_with_type(
&'a self,
type_name: &'static str,
) -> DataTreeFilterInternalIter<'a> {
if let DataTree::Internal { ref children, .. } = *self {
DataTreeFilterInternalIter {
type_name: type_name,
iter: children.iter(),
}
} else {
DataTreeFilterInternalIter {
type_name: type_name,
iter: [].iter(),
}
}
}
pub fn iter_leaf_children_with_type(
&'a self,
type_name: &'static str,
) -> DataTreeFilterLeafIter<'a> {
if let DataTree::Internal { ref children, .. } = *self {
DataTreeFilterLeafIter {
type_name: type_name,
iter: children.iter(),
}
} else {
DataTreeFilterLeafIter {
type_name: type_name,
iter: [].iter(),
}
}
}
// For unit tests
fn internal_data_or_panic(&'a self) -> (&'a str, Option<&'a str>, &'a Vec<DataTree>) {
if let DataTree::Internal {
type_name,
ref ident,
ref children,
..
} = self
{
(type_name, ident.as_ref().map(|id| id.as_str()), 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
{
(type_name, contents)
} else {
panic!("Expected DataTree::Leaf, found DataTree::Internal")
}
}
}
fn parse_node<R: std::io::BufRead>(
parser: &mut DataTreeReader<R>,
type_name: String,
ident: Option<String>,
byte_offset: usize,
) -> Result<DataTree, ParseError> {
let mut children = Vec::new();
loop {
match parser.next_event() {
Ok(Event::InnerOpen {
type_name,
ident,
byte_offset,
}) => {
let type_name = type_name.into();
let ident = ident.map(|id| id.into());
children.push(parse_node(parser, type_name, ident, byte_offset)?);
}
Ok(Event::Leaf {
type_name,
contents,
byte_offset,
}) => {
children.push(DataTree::Leaf {
type_name: type_name.into(),
contents: contents.into(),
byte_offset: byte_offset,
});
}
Ok(Event::InnerClose { .. }) => break,
Ok(Event::ValidEnd) => {
return Err(ParseError::Other("Unexpected end of contents."));
}
Ok(Event::NeedMoreInput) | Err(_) => {
return Err(ParseError::Other("Some error happened."));
}
}
}
Ok(DataTree::Internal {
type_name: type_name,
ident: ident,
children: children,
byte_offset: byte_offset,
})
}
/// Splits text at approximately the given byte index,
/// shifting it as needed to stay in bounds and be on a
/// valid `char` break.
fn aprx_split_at(text: &str, idx: usize) -> (&str, &str) {
let mut idx = text.len().min(idx);
while !text.is_char_boundary(idx) {
idx += 1;
}
(&text[..idx], &text[idx..])
}
/// An iterator over the children of a `DataTree` node that filters out the
/// children not matching a specified type name.
pub struct DataTreeFilterIter<'a> {
type_name: &'a str,
iter: slice::Iter<'a, DataTree>,
}
impl<'a> Iterator for DataTreeFilterIter<'a> {
type Item = &'a DataTree;
fn next(&mut self) -> Option<&'a DataTree> {
loop {
if let Some(dt) = self.iter.next() {
if dt.type_name() == self.type_name {
return Some(dt);
} else {
continue;
}
} else {
return None;
}
}
}
}
/// An iterator over the children of a `DataTree` node that filters out the
/// children that aren't internal nodes and that don't match a specified
/// type name.
pub struct DataTreeFilterInternalIter<'a> {
type_name: &'a str,
iter: slice::Iter<'a, DataTree>,
}
impl<'a> Iterator for DataTreeFilterInternalIter<'a> {
type Item = (&'a str, Option<&'a str>, &'a Vec<DataTree>, usize);
fn next(&mut self) -> Option<(&'a str, Option<&'a str>, &'a Vec<DataTree>, usize)> {
loop {
match self.iter.next() {
Some(DataTree::Internal {
type_name,
ident,
children,
byte_offset,
}) => {
if type_name == self.type_name {
return Some((
type_name,
ident.as_ref().map(|id| id.as_str()),
children,
*byte_offset,
));
} else {
continue;
}
}
Some(DataTree::Leaf { .. }) => {
continue;
}
None => {
return None;
}
}
}
}
}
/// An iterator over the children of a `DataTree` node that filters out the
/// children that aren't internal nodes and that don't match a specified
/// type name.
pub struct DataTreeFilterLeafIter<'a> {
type_name: &'a str,
iter: slice::Iter<'a, DataTree>,
}
impl<'a> Iterator for DataTreeFilterLeafIter<'a> {
type Item = (&'a str, &'a str, usize);
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,
byte_offset,
}) => {
if type_name == self.type_name {
return Some((type_name, contents, *byte_offset));
} else {
continue;
}
}
None => {
return None;
}
}
}
}
}

View File

@ -1,5 +1,4 @@
pub mod basics;
// mod data_tree;
mod parse_utils;
mod psy;
mod psy_assembly;
mod psy_light;

View File

@ -1,7 +1,10 @@
//! Some basic nom parsers
#![allow(dead_code)]
use std::str::{self, FromStr};
use std::{
io::BufRead,
str::{self, FromStr},
};
use nom::{
character::complete::{digit1, multispace0, one_of},
@ -11,6 +14,10 @@ use nom::{
IResult,
};
use data_tree::{reader::DataTreeReader, Event};
use super::psy::{PsyError, PsyResult};
// ========================================================
pub fn ws_f32(input: &str) -> IResult<&str, f32, ()> {
@ -36,6 +43,39 @@ pub fn ws_i32(input: &str) -> IResult<&str, i32, ()> {
)(input)
}
//---------------------------------------------------------
/// Ensures that we encounter a InnerClose event, and returns a useful
/// error if we don't.
pub fn ensure_close(events: &mut DataTreeReader<impl BufRead>) -> PsyResult<()> {
match events.next_event()? {
Event::InnerClose { .. } => Ok(()),
Event::InnerOpen {
type_name,
byte_offset,
..
} => Err(PsyError::ExpectedInternalNodeClose(
byte_offset,
format!(
"Expected the node to be closed, but instead found a '{}'.",
type_name
),
)),
Event::Leaf {
type_name,
byte_offset,
..
} => Err(PsyError::ExpectedInternalNodeClose(
byte_offset,
format!(
"Expected the node to be closed, but instead found a '{}'.",
type_name
),
)),
_ => Err(PsyError::UnknownError(events.byte_offset())),
}
}
// ========================================================
#[cfg(test)]

View File

@ -22,33 +22,36 @@ use crate::{
};
use super::{
basics::{ws_f32, ws_u32},
parse_utils::{ensure_close, ws_f32, ws_u32},
psy_assembly::parse_assembly,
psy_light::parse_distant_disk_light,
psy_surface_shader::parse_surface_shader,
};
pub type PsyResult<T> = Result<T, PsyError>;
#[derive(Debug)]
pub enum PsyParseError {
pub enum PsyError {
// 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
ExpectedIdent(usize, &'static str), // Error message
MissingNode(usize, &'static str), // Error message
IncorrectLeafData(usize, &'static str), // Error message
WrongNodeCount(usize, &'static str), // Error message
InstancedMissingData(usize, &'static str, String), // Error message, data name
UnknownVariant(usize, String), // Error message
ExpectedInternalNode(usize, String), // Error message
ExpectedLeafNode(usize, String), // Error message
ExpectedIdent(usize, String), // Error message
MissingNode(usize, String), // Error message
IncorrectLeafData(usize, String), // Error message
WrongNodeCount(usize, String), // Error message
InstancedMissingData(usize, String, String), // Error message, data name
ExpectedInternalNodeClose(usize, String),
ReaderError(ReaderError),
}
impl PsyParseError {
impl PsyError {
pub fn print(&self, psy_content: &str) {
match *self {
PsyParseError::UnknownError(offset) => {
let line = line_count_to_byte_offset(psy_content, offset);
match self {
PsyError::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.",
@ -56,43 +59,43 @@ impl PsyParseError {
);
}
PsyParseError::UnknownVariant(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset);
PsyError::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);
PsyError::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);
PsyError::ExpectedLeafNode(offset, error) => {
let line = line_count_to_byte_offset(psy_content, *offset);
println!("Line {}: {}", line, error);
}
PsyParseError::ExpectedIdent(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset);
PsyError::ExpectedIdent(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);
PsyError::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);
PsyError::IncorrectLeafData(offset, error) => {
let line = line_count_to_byte_offset(psy_content, *offset);
println!("Line {}: {}", line, error);
}
PsyParseError::WrongNodeCount(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset);
PsyError::WrongNodeCount(offset, error) => {
let line = line_count_to_byte_offset(psy_content, *offset);
println!("Line {}: {}", line, error);
}
PsyParseError::InstancedMissingData(offset, error, ref data_name) => {
let line = line_count_to_byte_offset(psy_content, offset);
PsyError::InstancedMissingData(offset, error, data_name) => {
let line = line_count_to_byte_offset(psy_content, *offset);
println!("Line {}: {} Data name: '{}'", line, error, data_name);
}
@ -101,17 +104,17 @@ impl PsyParseError {
}
}
impl std::error::Error for PsyParseError {}
impl std::error::Error for PsyError {}
impl std::fmt::Display for PsyParseError {
impl std::fmt::Display for PsyError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "{:?}", self)
}
}
impl From<ReaderError> for PsyParseError {
impl From<ReaderError> for PsyError {
fn from(e: ReaderError) -> Self {
PsyParseError::ReaderError(e)
PsyError::ReaderError(e)
}
}
@ -126,7 +129,7 @@ pub fn parse_scene<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
_ident: Option<&str>,
) -> Result<Scene<'a>, PsyParseError> {
) -> PsyResult<Scene<'a>> {
// Get output info.
let _output_info = if let Event::InnerOpen {
type_name: "Output",
@ -226,7 +229,7 @@ pub fn parse_scene<'a>(
return Ok(scene);
}
fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String, PsyParseError> {
fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> PsyResult<String> {
let mut found_path = false;
let mut path = String::new();
loop {
@ -239,15 +242,15 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
// Trim and validate
let tc = contents.trim();
if tc.chars().count() < 2 {
return Err(PsyParseError::IncorrectLeafData(
return Err(PsyError::IncorrectLeafData(
byte_offset,
"File path format is incorrect.",
"File path format is incorrect.".into(),
));
}
if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') {
return Err(PsyParseError::IncorrectLeafData(
return Err(PsyError::IncorrectLeafData(
byte_offset,
"File paths must be surrounded by quotes.",
"File paths must be surrounded by quotes.".into(),
));
}
let len = tc.len();
@ -272,7 +275,7 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
if found_path {
return Ok(path);
} else {
// return Err(PsyParseError::MissingNode(
// return Err(PsyError::MissingNode(
// tree.byte_offset(),
// "Output section must contain a Path.",
// ));
@ -282,7 +285,7 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
fn parse_render_settings(
events: &mut DataTreeReader<impl BufRead>,
) -> Result<((u32, u32), u32, u32), PsyParseError> {
) -> PsyResult<((u32, u32), u32, u32)> {
let mut found_res = false;
let mut found_spp = false;
let mut res = (0, 0);
@ -302,10 +305,11 @@ fn parse_render_settings(
res = (w, h);
} else {
// Found Resolution, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
return Err(PsyError::IncorrectLeafData(
byte_offset,
"Resolution should be specified with two \
integers in the form '[width height]'.",
integers in the form '[width height]'."
.into(),
));
}
}
@ -321,11 +325,11 @@ fn parse_render_settings(
spp = n;
} else {
// Found SamplesPerPixel, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
return Err(PsyError::IncorrectLeafData(
byte_offset,
"SamplesPerPixel should be \
an integer specified in \
the form '[samples]'.",
"SamplesPerPixel should be an integer specified in \
the form '[samples]'."
.into(),
));
}
}
@ -340,11 +344,11 @@ fn parse_render_settings(
seed = n;
} else {
// Found Seed, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
return Err(PsyError::IncorrectLeafData(
byte_offset,
"Seed should be an integer \
specified in the form \
'[samples]'.",
"Seed should be an integer specified in the form \
'[samples]'."
.into(),
));
}
}
@ -362,7 +366,7 @@ fn parse_render_settings(
if found_res && found_spp {
return Ok((res, spp, seed));
} else {
// return Err(PsyParseError::MissingNode(
// return Err(PsyError::MissingNode(
// tree.byte_offset(),
// "RenderSettings must have both Resolution and \
// SamplesPerPixel specified.",
@ -374,7 +378,7 @@ fn parse_render_settings(
fn parse_camera<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<Camera<'a>, PsyParseError> {
) -> PsyResult<Camera<'a>> {
let mut mats = Vec::new();
let mut fovs = Vec::new();
let mut focus_distances = Vec::new();
@ -393,11 +397,11 @@ fn parse_camera<'a>(
fovs.push(fov * (f32::consts::PI / 180.0));
} else {
// Found Fov, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
return Err(PsyError::IncorrectLeafData(
byte_offset,
"Fov should be a decimal \
number specified in the \
form '[fov]'.",
"Fov should be a decimal number specified in the \
form '[fov]'."
.into(),
));
}
}
@ -412,11 +416,11 @@ fn parse_camera<'a>(
focus_distances.push(fd);
} else {
// Found FocalDistance, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
return Err(PsyError::IncorrectLeafData(
byte_offset,
"FocalDistance should be a \
decimal number specified \
in the form '[fov]'.",
"FocalDistance should be a decimal number specified \
in the form '[fov]'."
.into(),
));
}
}
@ -431,11 +435,11 @@ fn parse_camera<'a>(
aperture_radii.push(ar);
} else {
// Found ApertureRadius, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
return Err(PsyError::IncorrectLeafData(
byte_offset,
"ApertureRadius should be a \
decimal number specified \
in the form '[fov]'.",
"ApertureRadius should be a decimal number specified \
in the form '[fov]'."
.into(),
));
}
}
@ -476,7 +480,7 @@ fn parse_camera<'a>(
fn parse_world<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<World<'a>, PsyParseError> {
) -> PsyResult<World<'a>> {
let mut background_color = None;
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
@ -524,10 +528,7 @@ fn parse_world<'a>(
}
// Close it out.
if let Event::InnerClose { .. } = events.next_event()? {
} else {
todo!(); // Return error.
}
ensure_close(events)?;
}
// Parse light sources
@ -568,7 +569,7 @@ fn parse_world<'a>(
fn parse_shaders<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<HashMap<String, Box<dyn SurfaceShader>>, PsyParseError> {
) -> PsyResult<HashMap<String, Box<dyn SurfaceShader>>> {
let mut shaders = HashMap::new();
loop {
match events.next_event()? {
@ -602,7 +603,7 @@ fn parse_shaders<'a>(
return Ok(shaders);
}
pub fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
pub fn parse_matrix(contents: &str) -> PsyResult<Matrix4x4> {
if let IResult::Ok((leftover, ns)) = all_consuming(tuple((
ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32,
ws_f32, ws_f32, ws_f32, ws_f32, ws_f32,
@ -619,15 +620,16 @@ pub fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
todo!(); // Return an error.
}
pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError {
PsyParseError::IncorrectLeafData(
pub fn make_transform_format_error(byte_offset: usize) -> PsyError {
PsyError::IncorrectLeafData(
byte_offset,
"Transform should be sixteen integers specified in \
the form '[# # # # # # # # # # # # # # # #]'.",
the form '[# # # # # # # # # # # # # # # #]'."
.into(),
)
}
pub fn parse_color(contents: &str) -> Result<Color, PsyParseError> {
pub fn parse_color(contents: &str) -> PsyResult<Color> {
let items: Vec<_> = contents.split(',').map(|s| s.trim()).collect();
if items.len() != 2 {
todo!(); // Return an error.

View File

@ -9,7 +9,8 @@ use data_tree::{reader::DataTreeReader, Event};
use crate::scene::{Assembly, Object, ObjectData};
use super::{
psy::{parse_matrix, PsyParseError},
parse_utils::ensure_close,
psy::{parse_matrix, PsyError, PsyResult},
psy_light::{parse_rectangle_light, parse_sphere_light},
psy_mesh_surface::parse_mesh_surface,
};
@ -17,7 +18,7 @@ use super::{
pub fn parse_assembly<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<Assembly<'a>, PsyParseError> {
) -> PsyResult<Assembly<'a>> {
let mut assembly = Assembly::new();
loop {
match events.next_event()? {
@ -30,9 +31,10 @@ pub fn parse_assembly<'a>(
let object_ident = if let Some(id) = ident {
id.to_string()
} else {
return Err(PsyParseError::ExpectedIdent(
return Err(PsyError::ExpectedIdent(
byte_offset,
"\'Object\' types must have an identifier, but the identifier is missing.",
"\'Object\' types must have an identifier, but the identifier is missing."
.into(),
));
};
@ -92,26 +94,22 @@ pub fn parse_assembly<'a>(
} => ObjectData::Light(Box::new(parse_rectangle_light(arena, events)?)),
Event::InnerClose { byte_offset } => {
return Err(PsyParseError::MissingNode(
return Err(PsyError::MissingNode(
byte_offset,
"Object contains no object data.",
"Object contains no object data.".into(),
));
}
_ => {
return Err(PsyParseError::UnknownVariant(
return Err(PsyError::UnknownVariant(
byte_offset,
"Unknown data type for Object.",
"Unknown data type for Object.".into(),
));
}
};
// Close object node.
if let Event::InnerClose { .. } = events.next_event()? {
// Success, do nothing.
} else {
todo!(); // Return error.
}
ensure_close(events)?;
assembly.objects.insert(
object_ident,
@ -133,7 +131,7 @@ pub fn parse_assembly<'a>(
}
// if !tree.is_internal() {
// return Err(PsyParseError::UnknownError(tree.byte_offset()));
// return Err(PsyError::UnknownError(tree.byte_offset()));
// }
// for object in tree.iter_children() {

View File

@ -14,15 +14,15 @@ use crate::{
};
use super::{
basics::ws_f32,
psy::{parse_color, PsyParseError},
parse_utils::ws_f32,
psy::{parse_color, PsyError, PsyResult},
};
pub fn parse_distant_disk_light<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
_ident: Option<&str>,
) -> Result<DistantDiskLight<'a>, PsyParseError> {
) -> PsyResult<DistantDiskLight<'a>> {
let mut radii = Vec::new();
let mut directions = Vec::new();
let mut colors = Vec::new();
@ -39,7 +39,7 @@ pub fn parse_distant_disk_light<'a>(
radii.push(radius);
} else {
// Found radius, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -55,7 +55,7 @@ pub fn parse_distant_disk_light<'a>(
directions.push(Vector::new(direction.0, direction.1, direction.2));
} else {
// Found direction, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -69,7 +69,7 @@ pub fn parse_distant_disk_light<'a>(
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -89,7 +89,7 @@ pub fn parse_distant_disk_light<'a>(
pub fn parse_sphere_light<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<SphereLight<'a>, PsyParseError> {
) -> Result<SphereLight<'a>, PsyError> {
let mut radii = Vec::new();
let mut colors = Vec::new();
@ -106,7 +106,7 @@ pub fn parse_sphere_light<'a>(
radii.push(radius);
} else {
// Found radius, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -120,7 +120,7 @@ pub fn parse_sphere_light<'a>(
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -140,7 +140,7 @@ pub fn parse_sphere_light<'a>(
pub fn parse_rectangle_light<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<RectangleLight<'a>, PsyParseError> {
) -> Result<RectangleLight<'a>, PsyError> {
let mut dimensions = Vec::new();
let mut colors = Vec::new();
@ -158,7 +158,7 @@ pub fn parse_rectangle_light<'a>(
dimensions.push(radius);
} else {
// Found dimensions, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -172,7 +172,7 @@ pub fn parse_rectangle_light<'a>(
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}

View File

@ -14,8 +14,8 @@ use crate::{
};
use super::{
basics::{ws_f32, ws_usize},
psy::PsyParseError,
parse_utils::{ws_f32, ws_usize},
psy::{PsyError, PsyResult},
};
// pub struct TriangleMesh {
@ -28,7 +28,7 @@ use super::{
pub fn parse_mesh_surface<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<TriangleMesh<'a>, PsyParseError> {
) -> PsyResult<TriangleMesh<'a>> {
let mut verts = Vec::new(); // Vec of vecs, one for each time sample
let mut normals = Vec::new(); // Vec of vecs, on for each time sample
let mut face_vert_counts = Vec::new();
@ -81,9 +81,9 @@ pub fn parse_mesh_surface<'a>(
byte_offset,
} => {
if !face_vert_counts.is_empty() {
return Err(PsyParseError::WrongNodeCount(
return Err(PsyError::WrongNodeCount(
byte_offset,
"Meshes can only have one FaceVertCounts section.",
"Meshes can only have one FaceVertCounts section.".into(),
));
}
let mut text = contents;
@ -99,9 +99,9 @@ pub fn parse_mesh_surface<'a>(
byte_offset,
} => {
if !face_vert_indices.is_empty() {
return Err(PsyParseError::WrongNodeCount(
return Err(PsyError::WrongNodeCount(
byte_offset,
"Meshes can only have one FaceVertIndices section.",
"Meshes can only have one FaceVertIndices section.".into(),
));
}
let mut text = contents;

View File

@ -11,8 +11,8 @@ use data_tree::{reader::DataTreeReader, Event};
use crate::shading::{SimpleSurfaceShader, SurfaceShader};
use super::{
basics::ws_f32,
psy::{parse_color, PsyParseError},
parse_utils::{ensure_close, ws_f32},
psy::{parse_color, PsyError, PsyResult},
};
// pub struct TriangleMesh {
@ -26,7 +26,7 @@ pub fn parse_surface_shader(
_arena: &Arena,
events: &mut DataTreeReader<impl BufRead>,
_ident: Option<&str>,
) -> Result<Box<dyn SurfaceShader>, PsyParseError> {
) -> PsyResult<Box<dyn SurfaceShader>> {
// Get shader type.
let shader = match events.next_event()? {
Event::Leaf {
@ -44,21 +44,17 @@ pub fn parse_surface_shader(
color
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
return Err(PsyError::MissingNode(
events.byte_offset(),
"Expected a Color field in Lambert SurfaceShader.",
"Expected a Color field in Lambert SurfaceShader.".into(),
));
};
// Close shader node.
if let Event::InnerClose { .. } = events.next_event()? {
// Success, do nothing.
} else {
todo!(); // Return error.
}
ensure_close(events)?;
Box::new(SimpleSurfaceShader::Lambert { color: color })
}
@ -85,7 +81,7 @@ pub fn parse_surface_shader(
} else {
// Found color, but its contents is not in the right
// format.
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -98,7 +94,7 @@ pub fn parse_surface_shader(
if let IResult::Ok((_, rgh)) = all_consuming(ws_f32)(contents) {
roughness = Some(rgh);
} else {
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -111,7 +107,7 @@ pub fn parse_surface_shader(
if let IResult::Ok((_, frs)) = all_consuming(ws_f32)(contents) {
fresnel = Some(frs);
} else {
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
}
@ -127,9 +123,9 @@ pub fn parse_surface_shader(
// Validation: make sure all fields are present.
if color == None || roughness == None || fresnel == None {
return Err(PsyParseError::MissingNode(
return Err(PsyError::MissingNode(
events.byte_offset(),
"GGX shader requires one of each field: Color, Roughness, Fresnel.",
"GGX shader requires one of each field: Color, Roughness, Fresnel.".into(),
));
}
@ -155,21 +151,17 @@ pub fn parse_surface_shader(
color
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
return Err(PsyError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
return Err(PsyError::MissingNode(
events.byte_offset(),
"Expected a Color field in Emit SurfaceShader.",
"Expected a Color field in Emit SurfaceShader.".into(),
));
};
// Close shader node.
if let Event::InnerClose { .. } = events.next_event()? {
// Success, do nothing.
} else {
todo!(); // Return error.
}
ensure_close(events)?;
Box::new(SimpleSurfaceShader::Emit { color: color })
}
@ -179,9 +171,9 @@ pub fn parse_surface_shader(
byte_offset,
..
} => {
return Err(PsyParseError::MissingNode(
return Err(PsyError::MissingNode(
byte_offset,
"Unknown SurfaceShader type.",
"Unknown SurfaceShader type.".into(),
));
}
_ => {