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:
parent
4f564d1474
commit
6b188c4451
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,4 @@
|
||||||
pub mod basics;
|
mod parse_utils;
|
||||||
// mod data_tree;
|
|
||||||
mod psy;
|
mod psy;
|
||||||
mod psy_assembly;
|
mod psy_assembly;
|
||||||
mod psy_light;
|
mod psy_light;
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
//! Some basic nom parsers
|
//! Some basic nom parsers
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::str::{self, FromStr};
|
use std::{
|
||||||
|
io::BufRead,
|
||||||
|
str::{self, FromStr},
|
||||||
|
};
|
||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
character::complete::{digit1, multispace0, one_of},
|
character::complete::{digit1, multispace0, one_of},
|
||||||
|
@ -11,6 +14,10 @@ use nom::{
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use data_tree::{reader::DataTreeReader, Event};
|
||||||
|
|
||||||
|
use super::psy::{PsyError, PsyResult};
|
||||||
|
|
||||||
// ========================================================
|
// ========================================================
|
||||||
|
|
||||||
pub fn ws_f32(input: &str) -> IResult<&str, f32, ()> {
|
pub fn ws_f32(input: &str) -> IResult<&str, f32, ()> {
|
||||||
|
@ -36,6 +43,39 @@ pub fn ws_i32(input: &str) -> IResult<&str, i32, ()> {
|
||||||
)(input)
|
)(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)]
|
#[cfg(test)]
|
156
src/parse/psy.rs
156
src/parse/psy.rs
|
@ -22,33 +22,36 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
basics::{ws_f32, ws_u32},
|
parse_utils::{ensure_close, ws_f32, ws_u32},
|
||||||
psy_assembly::parse_assembly,
|
psy_assembly::parse_assembly,
|
||||||
psy_light::parse_distant_disk_light,
|
psy_light::parse_distant_disk_light,
|
||||||
psy_surface_shader::parse_surface_shader,
|
psy_surface_shader::parse_surface_shader,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub type PsyResult<T> = Result<T, PsyError>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PsyParseError {
|
pub enum PsyError {
|
||||||
// The first usize for all errors is their byte offset
|
// The first usize for all errors is their byte offset
|
||||||
// into the psy content where they occured.
|
// into the psy content where they occured.
|
||||||
UnknownError(usize),
|
UnknownError(usize),
|
||||||
UnknownVariant(usize, &'static str), // Error message
|
UnknownVariant(usize, String), // Error message
|
||||||
ExpectedInternalNode(usize, &'static str), // Error message
|
ExpectedInternalNode(usize, String), // Error message
|
||||||
ExpectedLeafNode(usize, &'static str), // Error message
|
ExpectedLeafNode(usize, String), // Error message
|
||||||
ExpectedIdent(usize, &'static str), // Error message
|
ExpectedIdent(usize, String), // Error message
|
||||||
MissingNode(usize, &'static str), // Error message
|
MissingNode(usize, String), // Error message
|
||||||
IncorrectLeafData(usize, &'static str), // Error message
|
IncorrectLeafData(usize, String), // Error message
|
||||||
WrongNodeCount(usize, &'static str), // Error message
|
WrongNodeCount(usize, String), // Error message
|
||||||
InstancedMissingData(usize, &'static str, String), // Error message, data name
|
InstancedMissingData(usize, String, String), // Error message, data name
|
||||||
|
ExpectedInternalNodeClose(usize, String),
|
||||||
ReaderError(ReaderError),
|
ReaderError(ReaderError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PsyParseError {
|
impl PsyError {
|
||||||
pub fn print(&self, psy_content: &str) {
|
pub fn print(&self, psy_content: &str) {
|
||||||
match *self {
|
match self {
|
||||||
PsyParseError::UnknownError(offset) => {
|
PsyError::UnknownError(offset) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!(
|
println!(
|
||||||
"Line {}: Unknown parse error. If you get this message, please report \
|
"Line {}: Unknown parse error. If you get this message, please report \
|
||||||
it to the developers so they can improve the error messages.",
|
it to the developers so they can improve the error messages.",
|
||||||
|
@ -56,43 +59,43 @@ impl PsyParseError {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::UnknownVariant(offset, error) => {
|
PsyError::UnknownVariant(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::ExpectedInternalNode(offset, error) => {
|
PsyError::ExpectedInternalNode(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::ExpectedLeafNode(offset, error) => {
|
PsyError::ExpectedLeafNode(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::ExpectedIdent(offset, error) => {
|
PsyError::ExpectedIdent(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::MissingNode(offset, error) => {
|
PsyError::MissingNode(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::IncorrectLeafData(offset, error) => {
|
PsyError::IncorrectLeafData(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::WrongNodeCount(offset, error) => {
|
PsyError::WrongNodeCount(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::InstancedMissingData(offset, error, ref data_name) => {
|
PsyError::InstancedMissingData(offset, error, data_name) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, offset);
|
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||||
println!("Line {}: {} Data name: '{}'", line, error, data_name);
|
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> {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
write!(f, "{:?}", self)
|
write!(f, "{:?}", self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ReaderError> for PsyParseError {
|
impl From<ReaderError> for PsyError {
|
||||||
fn from(e: ReaderError) -> Self {
|
fn from(e: ReaderError) -> Self {
|
||||||
PsyParseError::ReaderError(e)
|
PsyError::ReaderError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +129,7 @@ pub fn parse_scene<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
_ident: Option<&str>,
|
_ident: Option<&str>,
|
||||||
) -> Result<Scene<'a>, PsyParseError> {
|
) -> PsyResult<Scene<'a>> {
|
||||||
// Get output info.
|
// Get output info.
|
||||||
let _output_info = if let Event::InnerOpen {
|
let _output_info = if let Event::InnerOpen {
|
||||||
type_name: "Output",
|
type_name: "Output",
|
||||||
|
@ -226,7 +229,7 @@ pub fn parse_scene<'a>(
|
||||||
return Ok(scene);
|
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 found_path = false;
|
||||||
let mut path = String::new();
|
let mut path = String::new();
|
||||||
loop {
|
loop {
|
||||||
|
@ -239,15 +242,15 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
|
||||||
// Trim and validate
|
// Trim and validate
|
||||||
let tc = contents.trim();
|
let tc = contents.trim();
|
||||||
if tc.chars().count() < 2 {
|
if tc.chars().count() < 2 {
|
||||||
return Err(PsyParseError::IncorrectLeafData(
|
return Err(PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"File path format is incorrect.",
|
"File path format is incorrect.".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') {
|
if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') {
|
||||||
return Err(PsyParseError::IncorrectLeafData(
|
return Err(PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"File paths must be surrounded by quotes.",
|
"File paths must be surrounded by quotes.".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let len = tc.len();
|
let len = tc.len();
|
||||||
|
@ -272,7 +275,7 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
|
||||||
if found_path {
|
if found_path {
|
||||||
return Ok(path);
|
return Ok(path);
|
||||||
} else {
|
} else {
|
||||||
// return Err(PsyParseError::MissingNode(
|
// return Err(PsyError::MissingNode(
|
||||||
// tree.byte_offset(),
|
// tree.byte_offset(),
|
||||||
// "Output section must contain a Path.",
|
// "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(
|
fn parse_render_settings(
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<((u32, u32), u32, u32), PsyParseError> {
|
) -> PsyResult<((u32, u32), u32, u32)> {
|
||||||
let mut found_res = false;
|
let mut found_res = false;
|
||||||
let mut found_spp = false;
|
let mut found_spp = false;
|
||||||
let mut res = (0, 0);
|
let mut res = (0, 0);
|
||||||
|
@ -302,10 +305,11 @@ fn parse_render_settings(
|
||||||
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::IncorrectLeafData(
|
return Err(PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Resolution should be specified with two \
|
"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;
|
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::IncorrectLeafData(
|
return Err(PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"SamplesPerPixel should be \
|
"SamplesPerPixel should be an integer specified in \
|
||||||
an integer specified in \
|
the form '[samples]'."
|
||||||
the form '[samples]'.",
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,11 +344,11 @@ fn parse_render_settings(
|
||||||
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::IncorrectLeafData(
|
return Err(PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Seed should be an integer \
|
"Seed should be an integer specified in the form \
|
||||||
specified in the form \
|
'[samples]'."
|
||||||
'[samples]'.",
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,7 +366,7 @@ fn parse_render_settings(
|
||||||
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::MissingNode(
|
// return Err(PsyError::MissingNode(
|
||||||
// tree.byte_offset(),
|
// tree.byte_offset(),
|
||||||
// "RenderSettings must have both Resolution and \
|
// "RenderSettings must have both Resolution and \
|
||||||
// SamplesPerPixel specified.",
|
// SamplesPerPixel specified.",
|
||||||
|
@ -374,7 +378,7 @@ fn parse_render_settings(
|
||||||
fn parse_camera<'a>(
|
fn parse_camera<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<Camera<'a>, PsyParseError> {
|
) -> PsyResult<Camera<'a>> {
|
||||||
let mut mats = Vec::new();
|
let mut mats = Vec::new();
|
||||||
let mut fovs = Vec::new();
|
let mut fovs = Vec::new();
|
||||||
let mut focus_distances = Vec::new();
|
let mut focus_distances = Vec::new();
|
||||||
|
@ -393,11 +397,11 @@ fn parse_camera<'a>(
|
||||||
fovs.push(fov * (f32::consts::PI / 180.0));
|
fovs.push(fov * (f32::consts::PI / 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::IncorrectLeafData(
|
return Err(PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Fov should be a decimal \
|
"Fov should be a decimal number specified in the \
|
||||||
number specified in the \
|
form '[fov]'."
|
||||||
form '[fov]'.",
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,11 +416,11 @@ fn parse_camera<'a>(
|
||||||
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::IncorrectLeafData(
|
return Err(PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"FocalDistance should be a \
|
"FocalDistance should be a decimal number specified \
|
||||||
decimal number specified \
|
in the form '[fov]'."
|
||||||
in the form '[fov]'.",
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -431,11 +435,11 @@ fn parse_camera<'a>(
|
||||||
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::IncorrectLeafData(
|
return Err(PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"ApertureRadius should be a \
|
"ApertureRadius should be a decimal number specified \
|
||||||
decimal number specified \
|
in the form '[fov]'."
|
||||||
in the form '[fov]'.",
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -476,7 +480,7 @@ fn parse_camera<'a>(
|
||||||
fn parse_world<'a>(
|
fn parse_world<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<World<'a>, PsyParseError> {
|
) -> PsyResult<World<'a>> {
|
||||||
let mut background_color = None;
|
let mut background_color = None;
|
||||||
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
|
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
|
||||||
|
|
||||||
|
@ -524,10 +528,7 @@ fn parse_world<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close it out.
|
// Close it out.
|
||||||
if let Event::InnerClose { .. } = events.next_event()? {
|
ensure_close(events)?;
|
||||||
} else {
|
|
||||||
todo!(); // Return error.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse light sources
|
// Parse light sources
|
||||||
|
@ -568,7 +569,7 @@ fn parse_world<'a>(
|
||||||
fn parse_shaders<'a>(
|
fn parse_shaders<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<HashMap<String, Box<dyn SurfaceShader>>, PsyParseError> {
|
) -> PsyResult<HashMap<String, Box<dyn SurfaceShader>>> {
|
||||||
let mut shaders = HashMap::new();
|
let mut shaders = HashMap::new();
|
||||||
loop {
|
loop {
|
||||||
match events.next_event()? {
|
match events.next_event()? {
|
||||||
|
@ -602,7 +603,7 @@ fn parse_shaders<'a>(
|
||||||
return Ok(shaders);
|
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((
|
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, 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.
|
todo!(); // Return an error.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError {
|
pub fn make_transform_format_error(byte_offset: usize) -> PsyError {
|
||||||
PsyParseError::IncorrectLeafData(
|
PsyError::IncorrectLeafData(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Transform should be sixteen integers specified in \
|
"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();
|
let items: Vec<_> = contents.split(',').map(|s| s.trim()).collect();
|
||||||
if items.len() != 2 {
|
if items.len() != 2 {
|
||||||
todo!(); // Return an error.
|
todo!(); // Return an error.
|
||||||
|
|
|
@ -9,7 +9,8 @@ use data_tree::{reader::DataTreeReader, Event};
|
||||||
use crate::scene::{Assembly, Object, ObjectData};
|
use crate::scene::{Assembly, Object, ObjectData};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
psy::{parse_matrix, PsyParseError},
|
parse_utils::ensure_close,
|
||||||
|
psy::{parse_matrix, PsyError, PsyResult},
|
||||||
psy_light::{parse_rectangle_light, parse_sphere_light},
|
psy_light::{parse_rectangle_light, parse_sphere_light},
|
||||||
psy_mesh_surface::parse_mesh_surface,
|
psy_mesh_surface::parse_mesh_surface,
|
||||||
};
|
};
|
||||||
|
@ -17,7 +18,7 @@ use super::{
|
||||||
pub fn parse_assembly<'a>(
|
pub fn parse_assembly<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<Assembly<'a>, PsyParseError> {
|
) -> PsyResult<Assembly<'a>> {
|
||||||
let mut assembly = Assembly::new();
|
let mut assembly = Assembly::new();
|
||||||
loop {
|
loop {
|
||||||
match events.next_event()? {
|
match events.next_event()? {
|
||||||
|
@ -30,9 +31,10 @@ pub fn parse_assembly<'a>(
|
||||||
let object_ident = if let Some(id) = ident {
|
let object_ident = if let Some(id) = ident {
|
||||||
id.to_string()
|
id.to_string()
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::ExpectedIdent(
|
return Err(PsyError::ExpectedIdent(
|
||||||
byte_offset,
|
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)?)),
|
} => ObjectData::Light(Box::new(parse_rectangle_light(arena, events)?)),
|
||||||
|
|
||||||
Event::InnerClose { byte_offset } => {
|
Event::InnerClose { byte_offset } => {
|
||||||
return Err(PsyParseError::MissingNode(
|
return Err(PsyError::MissingNode(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Object contains no object data.",
|
"Object contains no object data.".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(PsyParseError::UnknownVariant(
|
return Err(PsyError::UnknownVariant(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Unknown data type for Object.",
|
"Unknown data type for Object.".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Close object node.
|
// Close object node.
|
||||||
if let Event::InnerClose { .. } = events.next_event()? {
|
ensure_close(events)?;
|
||||||
// Success, do nothing.
|
|
||||||
} else {
|
|
||||||
todo!(); // Return error.
|
|
||||||
}
|
|
||||||
|
|
||||||
assembly.objects.insert(
|
assembly.objects.insert(
|
||||||
object_ident,
|
object_ident,
|
||||||
|
@ -133,7 +131,7 @@ pub fn parse_assembly<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// if !tree.is_internal() {
|
// if !tree.is_internal() {
|
||||||
// return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
// return Err(PsyError::UnknownError(tree.byte_offset()));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// for object in tree.iter_children() {
|
// for object in tree.iter_children() {
|
||||||
|
|
|
@ -14,15 +14,15 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
basics::ws_f32,
|
parse_utils::ws_f32,
|
||||||
psy::{parse_color, PsyParseError},
|
psy::{parse_color, PsyError, PsyResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_distant_disk_light<'a>(
|
pub fn parse_distant_disk_light<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
_ident: Option<&str>,
|
_ident: Option<&str>,
|
||||||
) -> Result<DistantDiskLight<'a>, PsyParseError> {
|
) -> PsyResult<DistantDiskLight<'a>> {
|
||||||
let mut radii = Vec::new();
|
let mut radii = Vec::new();
|
||||||
let mut directions = Vec::new();
|
let mut directions = Vec::new();
|
||||||
let mut colors = Vec::new();
|
let mut colors = Vec::new();
|
||||||
|
@ -39,7 +39,7 @@ pub fn parse_distant_disk_light<'a>(
|
||||||
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(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));
|
directions.push(Vector::new(direction.0, direction.1, direction.2));
|
||||||
} else {
|
} else {
|
||||||
// Found direction, but its contents is not in the right format
|
// 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);
|
colors.push(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(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>(
|
pub fn parse_sphere_light<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<SphereLight<'a>, PsyParseError> {
|
) -> Result<SphereLight<'a>, PsyError> {
|
||||||
let mut radii = Vec::new();
|
let mut radii = Vec::new();
|
||||||
let mut colors = Vec::new();
|
let mut colors = Vec::new();
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ pub fn parse_sphere_light<'a>(
|
||||||
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(byte_offset));
|
return Err(PsyError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ pub fn parse_sphere_light<'a>(
|
||||||
colors.push(color);
|
colors.push(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(byte_offset));
|
return Err(PsyError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ pub fn parse_sphere_light<'a>(
|
||||||
pub fn parse_rectangle_light<'a>(
|
pub fn parse_rectangle_light<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<RectangleLight<'a>, PsyParseError> {
|
) -> Result<RectangleLight<'a>, PsyError> {
|
||||||
let mut dimensions = Vec::new();
|
let mut dimensions = Vec::new();
|
||||||
let mut colors = Vec::new();
|
let mut colors = Vec::new();
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ pub fn parse_rectangle_light<'a>(
|
||||||
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(byte_offset));
|
return Err(PsyError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ pub fn parse_rectangle_light<'a>(
|
||||||
colors.push(color);
|
colors.push(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(byte_offset));
|
return Err(PsyError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
basics::{ws_f32, ws_usize},
|
parse_utils::{ws_f32, ws_usize},
|
||||||
psy::PsyParseError,
|
psy::{PsyError, PsyResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
// pub struct TriangleMesh {
|
// pub struct TriangleMesh {
|
||||||
|
@ -28,7 +28,7 @@ use super::{
|
||||||
pub fn parse_mesh_surface<'a>(
|
pub fn parse_mesh_surface<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
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 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 normals = Vec::new(); // Vec of vecs, on for each time sample
|
||||||
let mut face_vert_counts = Vec::new();
|
let mut face_vert_counts = Vec::new();
|
||||||
|
@ -81,9 +81,9 @@ pub fn parse_mesh_surface<'a>(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} => {
|
} => {
|
||||||
if !face_vert_counts.is_empty() {
|
if !face_vert_counts.is_empty() {
|
||||||
return Err(PsyParseError::WrongNodeCount(
|
return Err(PsyError::WrongNodeCount(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Meshes can only have one FaceVertCounts section.",
|
"Meshes can only have one FaceVertCounts section.".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let mut text = contents;
|
let mut text = contents;
|
||||||
|
@ -99,9 +99,9 @@ pub fn parse_mesh_surface<'a>(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} => {
|
} => {
|
||||||
if !face_vert_indices.is_empty() {
|
if !face_vert_indices.is_empty() {
|
||||||
return Err(PsyParseError::WrongNodeCount(
|
return Err(PsyError::WrongNodeCount(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Meshes can only have one FaceVertIndices section.",
|
"Meshes can only have one FaceVertIndices section.".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let mut text = contents;
|
let mut text = contents;
|
||||||
|
|
|
@ -11,8 +11,8 @@ use data_tree::{reader::DataTreeReader, Event};
|
||||||
use crate::shading::{SimpleSurfaceShader, SurfaceShader};
|
use crate::shading::{SimpleSurfaceShader, SurfaceShader};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
basics::ws_f32,
|
parse_utils::{ensure_close, ws_f32},
|
||||||
psy::{parse_color, PsyParseError},
|
psy::{parse_color, PsyError, PsyResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
// pub struct TriangleMesh {
|
// pub struct TriangleMesh {
|
||||||
|
@ -26,7 +26,7 @@ pub fn parse_surface_shader(
|
||||||
_arena: &Arena,
|
_arena: &Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
_ident: Option<&str>,
|
_ident: Option<&str>,
|
||||||
) -> Result<Box<dyn SurfaceShader>, PsyParseError> {
|
) -> PsyResult<Box<dyn SurfaceShader>> {
|
||||||
// Get shader type.
|
// Get shader type.
|
||||||
let shader = match events.next_event()? {
|
let shader = match events.next_event()? {
|
||||||
Event::Leaf {
|
Event::Leaf {
|
||||||
|
@ -44,21 +44,17 @@ pub fn parse_surface_shader(
|
||||||
color
|
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(byte_offset));
|
return Err(PsyError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::MissingNode(
|
return Err(PsyError::MissingNode(
|
||||||
events.byte_offset(),
|
events.byte_offset(),
|
||||||
"Expected a Color field in Lambert SurfaceShader.",
|
"Expected a Color field in Lambert SurfaceShader.".into(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Close shader node.
|
// Close shader node.
|
||||||
if let Event::InnerClose { .. } = events.next_event()? {
|
ensure_close(events)?;
|
||||||
// Success, do nothing.
|
|
||||||
} else {
|
|
||||||
todo!(); // Return error.
|
|
||||||
}
|
|
||||||
|
|
||||||
Box::new(SimpleSurfaceShader::Lambert { color: color })
|
Box::new(SimpleSurfaceShader::Lambert { color: color })
|
||||||
}
|
}
|
||||||
|
@ -85,7 +81,7 @@ pub fn parse_surface_shader(
|
||||||
} else {
|
} else {
|
||||||
// Found color, but its contents is not in the right
|
// Found color, but its contents is not in the right
|
||||||
// format.
|
// 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) {
|
if let IResult::Ok((_, rgh)) = all_consuming(ws_f32)(contents) {
|
||||||
roughness = Some(rgh);
|
roughness = Some(rgh);
|
||||||
} else {
|
} 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) {
|
if let IResult::Ok((_, frs)) = all_consuming(ws_f32)(contents) {
|
||||||
fresnel = Some(frs);
|
fresnel = Some(frs);
|
||||||
} else {
|
} 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.
|
// Validation: make sure all fields are present.
|
||||||
if color == None || roughness == None || fresnel == None {
|
if color == None || roughness == None || fresnel == None {
|
||||||
return Err(PsyParseError::MissingNode(
|
return Err(PsyError::MissingNode(
|
||||||
events.byte_offset(),
|
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
|
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(byte_offset));
|
return Err(PsyError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::MissingNode(
|
return Err(PsyError::MissingNode(
|
||||||
events.byte_offset(),
|
events.byte_offset(),
|
||||||
"Expected a Color field in Emit SurfaceShader.",
|
"Expected a Color field in Emit SurfaceShader.".into(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Close shader node.
|
// Close shader node.
|
||||||
if let Event::InnerClose { .. } = events.next_event()? {
|
ensure_close(events)?;
|
||||||
// Success, do nothing.
|
|
||||||
} else {
|
|
||||||
todo!(); // Return error.
|
|
||||||
}
|
|
||||||
|
|
||||||
Box::new(SimpleSurfaceShader::Emit { color: color })
|
Box::new(SimpleSurfaceShader::Emit { color: color })
|
||||||
}
|
}
|
||||||
|
@ -179,9 +171,9 @@ pub fn parse_surface_shader(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
return Err(PsyParseError::MissingNode(
|
return Err(PsyError::MissingNode(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Unknown SurfaceShader type.",
|
"Unknown SurfaceShader type.".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user