All parsing is now streaming! But lots left to do.
In particular, parsing error messages are now either terrible or non-existent. But it compiles and works for correct inputs!
This commit is contained in:
parent
5196e8e2c2
commit
4f564d1474
|
@ -7,18 +7,6 @@ Scene $Scene_fr1 {
|
||||||
SamplesPerPixel [16]
|
SamplesPerPixel [16]
|
||||||
Seed [1]
|
Seed [1]
|
||||||
}
|
}
|
||||||
Camera {
|
|
||||||
Fov [39.449188]
|
|
||||||
FocalDistance [10.62]
|
|
||||||
ApertureRadius [0.0]
|
|
||||||
Transform [1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 -2.779998 -8.000000 2.730010 1.0]
|
|
||||||
}
|
|
||||||
World {
|
|
||||||
BackgroundShader {
|
|
||||||
Type [Color]
|
|
||||||
Color [rec709, 0.0 0.0 0.0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Shaders {
|
Shaders {
|
||||||
SurfaceShader $Green {
|
SurfaceShader $Green {
|
||||||
Type [Lambert]
|
Type [Lambert]
|
||||||
|
@ -33,6 +21,18 @@ Scene $Scene_fr1 {
|
||||||
Color [rec709, 0.7295 0.7355 0.729]
|
Color [rec709, 0.7295 0.7355 0.729]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
World {
|
||||||
|
BackgroundShader {
|
||||||
|
Type [Color]
|
||||||
|
Color [rec709, 0.0 0.0 0.0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Camera {
|
||||||
|
Fov [39.449188]
|
||||||
|
FocalDistance [10.62]
|
||||||
|
ApertureRadius [0.0]
|
||||||
|
Transform [1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 -2.779998 -8.000000 2.730010 1.0]
|
||||||
|
}
|
||||||
Assembly {
|
Assembly {
|
||||||
Object $__Area {
|
Object $__Area {
|
||||||
Instance {
|
Instance {
|
||||||
|
|
|
@ -7,11 +7,11 @@ Scene $Scene_fr1 {
|
||||||
SamplesPerPixel [16]
|
SamplesPerPixel [16]
|
||||||
Seed [1]
|
Seed [1]
|
||||||
}
|
}
|
||||||
Camera {
|
Shaders {
|
||||||
Fov [49.134342]
|
SurfaceShader $Material {
|
||||||
FocalDistance [9.56]
|
Type [Lambert]
|
||||||
ApertureRadius [0.25]
|
Color [rec709, 0.8 0.8 0.8]
|
||||||
Transform [0.685881 0.727634 -0.010817 0.0 -0.317370 0.312469 0.895343 0.0 -0.654862 0.610666 -0.445245 0.0 7.481132 -6.507640 5.343665 1.0]
|
}
|
||||||
}
|
}
|
||||||
World {
|
World {
|
||||||
BackgroundShader {
|
BackgroundShader {
|
||||||
|
@ -19,11 +19,11 @@ Scene $Scene_fr1 {
|
||||||
Color [rec709, 0.050876 0.050876 0.050876]
|
Color [rec709, 0.050876 0.050876 0.050876]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Shaders {
|
Camera {
|
||||||
SurfaceShader $Material {
|
Fov [49.134342]
|
||||||
Type [Lambert]
|
FocalDistance [9.56]
|
||||||
Color [rec709, 0.8 0.8 0.8]
|
ApertureRadius [0.25]
|
||||||
}
|
Transform [0.685881 0.727634 -0.010817 0.0 -0.317370 0.312469 0.895343 0.0 -0.654862 0.610666 -0.445245 0.0 7.481132 -6.507640 5.343665 1.0]
|
||||||
}
|
}
|
||||||
Assembly {
|
Assembly {
|
||||||
Object $__Plane_ {
|
Object $__Plane_ {
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn wavelengths(hero_wavelength: f32) -> Vec4 {
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum Color {
|
pub enum Color {
|
||||||
XYZ(f32, f32, f32),
|
XYZ(f32, f32, f32),
|
||||||
Blackbody {
|
Blackbody {
|
||||||
|
|
46
src/main.rs
46
src/main.rs
|
@ -47,15 +47,12 @@ use nom::bytes::complete::take_until;
|
||||||
|
|
||||||
use kioku::Arena;
|
use kioku::Arena;
|
||||||
|
|
||||||
use data_tree::{
|
use data_tree::{reader::DataTreeReader, Event};
|
||||||
reader::{DataTreeReader, ReaderError},
|
|
||||||
Event,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
accel::BVH4Node,
|
accel::BVH4Node,
|
||||||
bbox::BBox,
|
bbox::BBox,
|
||||||
parse::{parse_scene, DataTree},
|
parse::parse_scene,
|
||||||
// renderer::LightPath,
|
// renderer::LightPath,
|
||||||
surface::SurfaceIntersection,
|
surface::SurfaceIntersection,
|
||||||
timer::Timer,
|
timer::Timer,
|
||||||
|
@ -242,27 +239,14 @@ fn main() {
|
||||||
// println!("\tParsed scene file in {:.3}s", t.tick());
|
// println!("\tParsed scene file in {:.3}s", t.tick());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let mut psy_file = io::BufReader::new(File::open(fp).unwrap());
|
let file_path = args.value_of("input").unwrap();
|
||||||
|
let mut psy_file = io::BufReader::new(File::open(file_path).unwrap());
|
||||||
let mut events = DataTreeReader::new(&mut psy_file);
|
let mut events = DataTreeReader::new(&mut psy_file);
|
||||||
|
|
||||||
// Iterate through scenes and render them
|
// Iterate through scenes and render them
|
||||||
loop {
|
loop {
|
||||||
t.tick();
|
t.tick();
|
||||||
match events.next_event() {
|
match events.next_event() {
|
||||||
Ok(Event::ValidEnd) => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(_) => {
|
|
||||||
println!("Error: invalid scene in psy file.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error: {:?}", e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse a scene and render it.
|
// Parse a scene and render it.
|
||||||
Ok(Event::InnerOpen {
|
Ok(Event::InnerOpen {
|
||||||
type_name: "Scene",
|
type_name: "Scene",
|
||||||
|
@ -274,9 +258,11 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let arena = Arena::new().with_block_size((1 << 20) * 4);
|
let arena = Arena::new().with_block_size((1 << 20) * 4);
|
||||||
let ident = ident.into::<String>();
|
let ident = ident.map(|v| v.to_string());
|
||||||
let mut scene = parse_scene(&arena, &mut events, &ident).unwrap_or_else(|e| {
|
let scene =
|
||||||
e.print(&psy_contents);
|
parse_scene(&arena, &mut events, ident.as_deref()).unwrap_or_else(|e| {
|
||||||
|
println!("Parse error: {}", e);
|
||||||
|
// e.print(&psy_contents);
|
||||||
panic!("Parse error.");
|
panic!("Parse error.");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -384,6 +370,20 @@ fn main() {
|
||||||
// println!("\tTotal blocks: {}", arena_stats.2);
|
// println!("\tTotal blocks: {}", arena_stats.2);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(Event::ValidEnd) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error: {:?}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(_) => {
|
||||||
|
println!("Error: invalid scene in psy file.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
|
|
||||||
use std::{io::Cursor, iter::Iterator, result::Result, slice};
|
use std::{io::Cursor, iter::Iterator, result::Result, slice};
|
||||||
|
|
||||||
use data_tree::{
|
use data_tree::{reader::DataTreeReader, Event};
|
||||||
reader::{DataTreeReader, ReaderError},
|
|
||||||
Event,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub enum DataTree {
|
pub enum DataTree {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
pub mod basics;
|
pub mod basics;
|
||||||
mod data_tree;
|
// mod data_tree;
|
||||||
mod psy;
|
mod psy;
|
||||||
mod psy_assembly;
|
mod psy_assembly;
|
||||||
mod psy_light;
|
mod psy_light;
|
||||||
mod psy_mesh_surface;
|
mod psy_mesh_surface;
|
||||||
mod psy_surface_shader;
|
mod psy_surface_shader;
|
||||||
|
|
||||||
pub use self::{data_tree::DataTree, psy::parse_scene};
|
pub use self::psy::parse_scene;
|
||||||
|
|
124
src/parse/psy.rs
124
src/parse/psy.rs
|
@ -26,7 +26,6 @@ use super::{
|
||||||
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,
|
||||||
DataTree,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -40,7 +39,7 @@ pub enum PsyParseError {
|
||||||
ExpectedIdent(usize, &'static str), // Error message
|
ExpectedIdent(usize, &'static str), // Error message
|
||||||
MissingNode(usize, &'static str), // Error message
|
MissingNode(usize, &'static str), // Error message
|
||||||
IncorrectLeafData(usize, &'static str), // Error message
|
IncorrectLeafData(usize, &'static str), // Error message
|
||||||
WrongNodeCount(usize, &'static str, usize), // Error message, sections found
|
WrongNodeCount(usize, &'static str), // Error message
|
||||||
InstancedMissingData(usize, &'static str, String), // Error message, data name
|
InstancedMissingData(usize, &'static str, String), // Error message, data name
|
||||||
ReaderError(ReaderError),
|
ReaderError(ReaderError),
|
||||||
}
|
}
|
||||||
|
@ -87,15 +86,17 @@ impl PsyParseError {
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::WrongNodeCount(offset, error, count) => {
|
PsyParseError::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 {}: {} Found: {}", line, error, count);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyParseError::InstancedMissingData(offset, error, ref data_name) => {
|
PsyParseError::InstancedMissingData(offset, error, ref 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,10 +125,10 @@ fn line_count_to_byte_offset(text: &str, offset: usize) -> usize {
|
||||||
pub fn parse_scene<'a>(
|
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> {
|
) -> Result<Scene<'a>, PsyParseError> {
|
||||||
// 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",
|
||||||
..
|
..
|
||||||
} = events.next_event()?
|
} = events.next_event()?
|
||||||
|
@ -138,7 +139,7 @@ pub fn parse_scene<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get render settings.
|
// Get render settings.
|
||||||
let render_settings = if let Event::InnerOpen {
|
let _render_settings = if let Event::InnerOpen {
|
||||||
type_name: "RenderSettings",
|
type_name: "RenderSettings",
|
||||||
..
|
..
|
||||||
} = events.next_event()?
|
} = events.next_event()?
|
||||||
|
@ -148,17 +149,6 @@ pub fn parse_scene<'a>(
|
||||||
todo!(); // Return error.
|
todo!(); // Return error.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get camera.
|
|
||||||
let camera = if let Event::InnerOpen {
|
|
||||||
type_name: "Camera",
|
|
||||||
..
|
|
||||||
} = events.next_event()?
|
|
||||||
{
|
|
||||||
parse_camera(arena, events)?
|
|
||||||
} else {
|
|
||||||
todo!(); // Return error.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get shaders.
|
// Get shaders.
|
||||||
let shaders = if let Event::InnerOpen {
|
let shaders = if let Event::InnerOpen {
|
||||||
type_name: "Shaders",
|
type_name: "Shaders",
|
||||||
|
@ -180,14 +170,24 @@ pub fn parse_scene<'a>(
|
||||||
todo!(); // Return error.
|
todo!(); // Return error.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the root assembly.
|
// Get camera.
|
||||||
let root_assembly = if let Event::InnerOpen {
|
let camera = if let Event::InnerOpen {
|
||||||
type_name: "Assembly",
|
type_name: "Camera",
|
||||||
ident,
|
|
||||||
..
|
..
|
||||||
} = events.next_event()?
|
} = events.next_event()?
|
||||||
{
|
{
|
||||||
parse_assembly(arena, events, &(ident.into::<String>()))?
|
parse_camera(arena, events)?
|
||||||
|
} else {
|
||||||
|
todo!(); // Return error.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the root assembly.
|
||||||
|
let root_assembly = if let Event::InnerOpen {
|
||||||
|
type_name: "Assembly",
|
||||||
|
..
|
||||||
|
} = events.next_event()?
|
||||||
|
{
|
||||||
|
parse_assembly(arena, events)?
|
||||||
} else {
|
} else {
|
||||||
todo!(); // Return error.
|
todo!(); // Return error.
|
||||||
};
|
};
|
||||||
|
@ -199,12 +199,11 @@ pub fn parse_scene<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put scene together
|
// Put scene together
|
||||||
let scene_name = if let Some(name) = ident {
|
// let scene_name = if let Some(name) = ident {
|
||||||
Some(name.into())
|
// Some(name.into())
|
||||||
} else {
|
// } else {
|
||||||
None
|
// None
|
||||||
};
|
// };
|
||||||
|
|
||||||
let scene = Scene {
|
let scene = Scene {
|
||||||
camera: camera,
|
camera: camera,
|
||||||
world: world,
|
world: world,
|
||||||
|
@ -241,13 +240,13 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
|
||||||
let tc = contents.trim();
|
let tc = contents.trim();
|
||||||
if tc.chars().count() < 2 {
|
if tc.chars().count() < 2 {
|
||||||
return Err(PsyParseError::IncorrectLeafData(
|
return Err(PsyParseError::IncorrectLeafData(
|
||||||
*byte_offset,
|
byte_offset,
|
||||||
"File path format is incorrect.",
|
"File path format is incorrect.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') {
|
if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') {
|
||||||
return Err(PsyParseError::IncorrectLeafData(
|
return Err(PsyParseError::IncorrectLeafData(
|
||||||
*byte_offset,
|
byte_offset,
|
||||||
"File paths must be surrounded by quotes.",
|
"File paths must be surrounded by quotes.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -304,7 +303,7 @@ fn parse_render_settings(
|
||||||
} 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(PsyParseError::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]'.",
|
||||||
));
|
));
|
||||||
|
@ -312,7 +311,7 @@ fn parse_render_settings(
|
||||||
}
|
}
|
||||||
|
|
||||||
// SamplesPerPixel
|
// SamplesPerPixel
|
||||||
DataTree::Leaf {
|
Event::Leaf {
|
||||||
type_name: "SamplesPerPixel",
|
type_name: "SamplesPerPixel",
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
|
@ -323,7 +322,7 @@ fn parse_render_settings(
|
||||||
} 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(PsyParseError::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]'.",
|
||||||
|
@ -332,7 +331,7 @@ fn parse_render_settings(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seed
|
// Seed
|
||||||
DataTree::Leaf {
|
Event::Leaf {
|
||||||
type_name: "Seed",
|
type_name: "Seed",
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
|
@ -342,7 +341,7 @@ fn parse_render_settings(
|
||||||
} 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(PsyParseError::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]'.",
|
||||||
|
@ -395,7 +394,7 @@ fn parse_camera<'a>(
|
||||||
} 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(PsyParseError::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]'.",
|
||||||
|
@ -414,7 +413,7 @@ fn parse_camera<'a>(
|
||||||
} 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(PsyParseError::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]'.",
|
||||||
|
@ -433,7 +432,7 @@ fn parse_camera<'a>(
|
||||||
} 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(PsyParseError::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]'.",
|
||||||
|
@ -451,7 +450,7 @@ fn parse_camera<'a>(
|
||||||
mats.push(mat);
|
mats.push(mat);
|
||||||
} else {
|
} else {
|
||||||
// Found Transform, but its contents is not in the right format
|
// Found Transform, but its contents is not in the right format
|
||||||
return Err(make_transform_format_error(*byte_offset));
|
return Err(make_transform_format_error(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,7 +477,7 @@ fn parse_world<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<World<'a>, PsyParseError> {
|
) -> Result<World<'a>, PsyParseError> {
|
||||||
let background_color = None;
|
let mut background_color = None;
|
||||||
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
|
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -486,25 +485,26 @@ fn parse_world<'a>(
|
||||||
// Parse background shader
|
// Parse background shader
|
||||||
Event::InnerOpen {
|
Event::InnerOpen {
|
||||||
type_name: "BackgroundShader",
|
type_name: "BackgroundShader",
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
let bgs_type = if let Event::Leaf {
|
let bgs_type = if let Event::Leaf {
|
||||||
type_name: "Type",
|
type_name: "Type",
|
||||||
contents,
|
contents,
|
||||||
..
|
..
|
||||||
} = events.next_event()
|
} = events.next_event()?
|
||||||
{
|
{
|
||||||
contents.into::<String>()
|
contents.to_string()
|
||||||
} else {
|
} else {
|
||||||
todo!(); // Return error.
|
todo!(); // Return error.
|
||||||
};
|
};
|
||||||
|
|
||||||
match bgs_type {
|
match bgs_type.as_ref() {
|
||||||
"Color" => {
|
"Color" => {
|
||||||
if let Event::Leaf {
|
if let Event::Leaf {
|
||||||
type_name: "Color",
|
type_name: "Color",
|
||||||
contents,
|
contents,
|
||||||
..
|
..
|
||||||
} = events.next_event()
|
} = events.next_event()?
|
||||||
{
|
{
|
||||||
background_color = Some(parse_color(contents)?);
|
background_color = Some(parse_color(contents)?);
|
||||||
} else {
|
} else {
|
||||||
|
@ -524,7 +524,7 @@ fn parse_world<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close it out.
|
// Close it out.
|
||||||
if let Event::InnerClose { .. } = events.next_event() {
|
if let Event::InnerClose { .. } = events.next_event()? {
|
||||||
} else {
|
} else {
|
||||||
todo!(); // Return error.
|
todo!(); // Return error.
|
||||||
}
|
}
|
||||||
|
@ -533,9 +533,23 @@ fn parse_world<'a>(
|
||||||
// Parse light sources
|
// Parse light sources
|
||||||
Event::InnerOpen {
|
Event::InnerOpen {
|
||||||
type_name: "DistantDiskLight",
|
type_name: "DistantDiskLight",
|
||||||
|
ident,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
lights.push(arena.alloc(parse_distant_disk_light(arena, events)?));
|
let ident = ident.map(|v| v.to_string());
|
||||||
|
lights.push(arena.alloc(parse_distant_disk_light(
|
||||||
|
arena,
|
||||||
|
events,
|
||||||
|
ident.as_deref(),
|
||||||
|
)?));
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!(); // Return error.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,24 +566,32 @@ fn parse_world<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_shaders<'a>(
|
fn parse_shaders<'a>(
|
||||||
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader<impl BufRead>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
) -> Result<HashMap<String, Box<dyn SurfaceShader>>, PsyParseError> {
|
) -> Result<HashMap<String, Box<dyn SurfaceShader>>, PsyParseError> {
|
||||||
let mut shaders = HashMap::new();
|
let mut shaders = HashMap::new();
|
||||||
loop {
|
loop {
|
||||||
match events.next_event() {
|
match events.next_event()? {
|
||||||
DataTree::Internal {
|
Event::InnerOpen {
|
||||||
type_name: "SurfaceShader",
|
type_name: "SurfaceShader",
|
||||||
ident,
|
ident,
|
||||||
byte_offset,
|
..
|
||||||
} => {
|
} => {
|
||||||
if let Some(name) = ident {
|
if let Some(name) = ident {
|
||||||
let name = name.to_string();
|
let name = name.to_string();
|
||||||
shaders.insert(name, parse_surface_shader(events)?);
|
shaders.insert(
|
||||||
|
name.clone(),
|
||||||
|
parse_surface_shader(arena, events, Some(&name))?,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
todo!("Shader has no name."); // Return error.
|
todo!("Shader has no name."); // Return error.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
todo!(); // Return error.
|
todo!(); // Return error.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::result::Result;
|
use std::{io::BufRead, result::Result};
|
||||||
|
|
||||||
use kioku::Arena;
|
use kioku::Arena;
|
||||||
|
|
||||||
use data_tree::{
|
use data_tree::{reader::DataTreeReader, Event};
|
||||||
reader::{DataTreeReader, ReaderError},
|
|
||||||
Event,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::scene::{Assembly, Object, ObjectData};
|
use crate::scene::{Assembly, Object, ObjectData};
|
||||||
|
|
||||||
|
@ -15,101 +12,137 @@ use super::{
|
||||||
psy::{parse_matrix, PsyParseError},
|
psy::{parse_matrix, PsyParseError},
|
||||||
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,
|
||||||
DataTree,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_assembly<'a>(
|
pub fn parse_assembly<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
ident: Option<&str>,
|
|
||||||
) -> Result<Assembly<'a>, PsyParseError> {
|
) -> Result<Assembly<'a>, PsyParseError> {
|
||||||
if !tree.is_internal() {
|
|
||||||
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut assembly = Assembly::new();
|
let mut assembly = Assembly::new();
|
||||||
for object in tree.iter_children() {
|
loop {
|
||||||
if object.type_name() == "Object" {
|
match events.next_event()? {
|
||||||
|
Event::InnerOpen {
|
||||||
|
type_name: "Object",
|
||||||
|
ident,
|
||||||
|
byte_offset,
|
||||||
|
} => {
|
||||||
// Get object identifier.
|
// Get object identifier.
|
||||||
let object_ident = if let Some(ident) = object.ident() {
|
let object_ident = if let Some(id) = ident {
|
||||||
ident
|
id.to_string()
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::ExpectedIdent(
|
return Err(PsyParseError::ExpectedIdent(
|
||||||
object.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.",
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Collect instances.
|
// Collect instances.
|
||||||
let mut instance_xform_idxs = Vec::new();
|
let mut instance_xform_idxs = Vec::new();
|
||||||
for instance in object.iter_children_with_type("Instance") {
|
while let Event::InnerOpen {
|
||||||
if !instance.is_internal() {
|
type_name: "Instance",
|
||||||
// TODO: error.
|
..
|
||||||
}
|
} = events.peek_event()?
|
||||||
|
{
|
||||||
|
events.next_event();
|
||||||
let xforms_start_idx = assembly.xforms.len();
|
let xforms_start_idx = assembly.xforms.len();
|
||||||
for (_, contents, _) in instance.iter_leaf_children_with_type("Transform") {
|
loop {
|
||||||
|
match events.next_event()? {
|
||||||
|
Event::Leaf {
|
||||||
|
type_name: "Transform",
|
||||||
|
contents,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
assembly.xforms.push(parse_matrix(contents)?);
|
assembly.xforms.push(parse_matrix(contents)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!("Instances can only contain Transforms.");
|
||||||
|
// Return an error.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
instance_xform_idxs.push(xforms_start_idx..assembly.xforms.len());
|
instance_xform_idxs.push(xforms_start_idx..assembly.xforms.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get object data.
|
// Get object data.
|
||||||
let object_data = {
|
let object_data = match events.next_event()? {
|
||||||
let obj_data_tree = {
|
Event::InnerOpen {
|
||||||
if object
|
type_name: "Assembly",
|
||||||
.iter_children()
|
..
|
||||||
.filter(|d| d.type_name() != "Instance")
|
} => ObjectData::Assembly(Box::new(parse_assembly(arena, events)?)),
|
||||||
.count()
|
|
||||||
!= 1
|
|
||||||
{
|
|
||||||
// TODO: error.
|
|
||||||
}
|
|
||||||
object
|
|
||||||
.iter_children()
|
|
||||||
.filter(|d| d.type_name() != "Instance")
|
|
||||||
.nth(0)
|
|
||||||
.unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
match obj_data_tree.type_name() {
|
Event::InnerOpen {
|
||||||
// Sub-Assembly
|
type_name: "MeshSurface",
|
||||||
"Assembly" => {
|
..
|
||||||
ObjectData::Assembly(Box::new(parse_assembly(arena, obj_data_tree)?))
|
} => ObjectData::Surface(Box::new(parse_mesh_surface(arena, events)?)),
|
||||||
}
|
|
||||||
|
|
||||||
"MeshSurface" => {
|
Event::InnerOpen {
|
||||||
ObjectData::Surface(Box::new(parse_mesh_surface(arena, obj_data_tree)?))
|
type_name: "SphereLight",
|
||||||
}
|
..
|
||||||
|
} => ObjectData::Light(Box::new(parse_sphere_light(arena, events)?)),
|
||||||
|
|
||||||
"SphereLight" => {
|
Event::InnerOpen {
|
||||||
ObjectData::Light(Box::new(parse_sphere_light(arena, obj_data_tree)?))
|
type_name: "RectangleLight",
|
||||||
}
|
..
|
||||||
|
} => ObjectData::Light(Box::new(parse_rectangle_light(arena, events)?)),
|
||||||
|
|
||||||
"RectangleLight" => {
|
Event::InnerClose { byte_offset } => {
|
||||||
ObjectData::Light(Box::new(parse_rectangle_light(arena, obj_data_tree)?))
|
return Err(PsyParseError::MissingNode(
|
||||||
|
byte_offset,
|
||||||
|
"Object contains no object data.",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(PsyParseError::UnknownVariant(
|
return Err(PsyParseError::UnknownVariant(
|
||||||
tree.byte_offset(),
|
byte_offset,
|
||||||
"Unknown data type for Object.",
|
"Unknown data type for Object.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Close object node.
|
||||||
|
if let Event::InnerClose { .. } = events.next_event()? {
|
||||||
|
// Success, do nothing.
|
||||||
|
} else {
|
||||||
|
todo!(); // Return error.
|
||||||
|
}
|
||||||
|
|
||||||
assembly.objects.insert(
|
assembly.objects.insert(
|
||||||
object_ident.to_string(),
|
object_ident,
|
||||||
Object {
|
Object {
|
||||||
data: object_data,
|
data: object_data,
|
||||||
instance_xform_idxs: instance_xform_idxs,
|
instance_xform_idxs: instance_xform_idxs,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
// TODO: error.
|
|
||||||
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!(); // Return an error.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if !tree.is_internal() {
|
||||||
|
// return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for object in tree.iter_children() {
|
||||||
|
// if object.type_name() == "Object" {
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// // TODO: error.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
return Ok(assembly);
|
return Ok(assembly);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::result::Result;
|
use std::{io::BufRead, result::Result};
|
||||||
|
|
||||||
use nom::{combinator::all_consuming, sequence::tuple, IResult};
|
use nom::{combinator::all_consuming, sequence::tuple, IResult};
|
||||||
|
|
||||||
use kioku::Arena;
|
use kioku::Arena;
|
||||||
|
|
||||||
use data_tree::{
|
use data_tree::{reader::DataTreeReader, Event};
|
||||||
reader::{DataTreeReader, ReaderError},
|
|
||||||
Event,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
light::{DistantDiskLight, RectangleLight, SphereLight},
|
light::{DistantDiskLight, RectangleLight, SphereLight},
|
||||||
|
@ -19,174 +16,175 @@ use crate::{
|
||||||
use super::{
|
use super::{
|
||||||
basics::ws_f32,
|
basics::ws_f32,
|
||||||
psy::{parse_color, PsyParseError},
|
psy::{parse_color, PsyParseError},
|
||||||
DataTree,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_distant_disk_light<'a>(
|
pub fn parse_distant_disk_light<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
ident: Option<&str>,
|
_ident: Option<&str>,
|
||||||
) -> Result<DistantDiskLight<'a>, PsyParseError> {
|
) -> Result<DistantDiskLight<'a>, PsyParseError> {
|
||||||
if let DataTree::Internal { ref children, .. } = *tree {
|
|
||||||
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();
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
for child in children.iter() {
|
loop {
|
||||||
match child {
|
match events.next_event()? {
|
||||||
// Radius
|
Event::Leaf {
|
||||||
DataTree::Leaf {
|
type_name: "Radius",
|
||||||
type_name,
|
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} if type_name == "Radius" => {
|
} => {
|
||||||
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
|
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
|
||||||
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(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direction
|
// Direction
|
||||||
DataTree::Leaf {
|
Event::Leaf {
|
||||||
type_name,
|
type_name: "Direction",
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} if type_name == "Direction" => {
|
} => {
|
||||||
if let IResult::Ok((_, direction)) =
|
if let IResult::Ok((_, direction)) =
|
||||||
all_consuming(tuple((ws_f32, ws_f32, ws_f32)))(&contents)
|
all_consuming(tuple((ws_f32, ws_f32, ws_f32)))(&contents)
|
||||||
{
|
{
|
||||||
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(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
DataTree::Leaf {
|
Event::Leaf {
|
||||||
type_name,
|
type_name: "Color",
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} if type_name == "Color" => {
|
} => {
|
||||||
if let Ok(color) = parse_color(&contents) {
|
if let Ok(color) = parse_color(&contents) {
|
||||||
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(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!(); // Return error.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors));
|
return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors));
|
||||||
} else {
|
|
||||||
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_sphere_light<'a>(
|
pub fn parse_sphere_light<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
ident: Option<&str>,
|
|
||||||
) -> Result<SphereLight<'a>, PsyParseError> {
|
) -> Result<SphereLight<'a>, PsyParseError> {
|
||||||
if let DataTree::Internal { ref children, .. } = *tree {
|
|
||||||
let mut radii = Vec::new();
|
let mut radii = Vec::new();
|
||||||
let mut colors = Vec::new();
|
let mut colors = Vec::new();
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
for child in children.iter() {
|
loop {
|
||||||
match child {
|
match events.next_event()? {
|
||||||
// Radius
|
// Radius
|
||||||
DataTree::Leaf {
|
Event::Leaf {
|
||||||
type_name,
|
type_name: "Radius",
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} if type_name == "Radius" => {
|
} => {
|
||||||
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
|
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
|
||||||
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(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
DataTree::Leaf {
|
Event::Leaf {
|
||||||
type_name,
|
type_name: "Color",
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} if type_name == "Color" => {
|
} => {
|
||||||
if let Ok(color) = parse_color(&contents) {
|
if let Ok(color) = parse_color(&contents) {
|
||||||
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(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!(); // Return error.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(SphereLight::new(arena, &radii, &colors));
|
return Ok(SphereLight::new(arena, &radii, &colors));
|
||||||
} else {
|
|
||||||
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_rectangle_light<'a>(
|
pub fn parse_rectangle_light<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
ident: Option<&str>,
|
|
||||||
) -> Result<RectangleLight<'a>, PsyParseError> {
|
) -> Result<RectangleLight<'a>, PsyParseError> {
|
||||||
if let DataTree::Internal { ref children, .. } = *tree {
|
|
||||||
let mut dimensions = Vec::new();
|
let mut dimensions = Vec::new();
|
||||||
let mut colors = Vec::new();
|
let mut colors = Vec::new();
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
for child in children.iter() {
|
loop {
|
||||||
match child {
|
match events.next_event()? {
|
||||||
// Dimensions
|
// Dimensions
|
||||||
DataTree::Leaf {
|
Event::Leaf {
|
||||||
type_name,
|
type_name: "Dimensions",
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} if type_name == "Dimensions" => {
|
} => {
|
||||||
if let IResult::Ok((_, radius)) =
|
if let IResult::Ok((_, radius)) = all_consuming(tuple((ws_f32, ws_f32)))(&contents)
|
||||||
all_consuming(tuple((ws_f32, ws_f32)))(&contents)
|
|
||||||
{
|
{
|
||||||
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(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
DataTree::Leaf {
|
Event::Leaf {
|
||||||
type_name,
|
type_name: "Color",
|
||||||
contents,
|
contents,
|
||||||
byte_offset,
|
byte_offset,
|
||||||
} if type_name == "Color" => {
|
} => {
|
||||||
if let Ok(color) = parse_color(&contents) {
|
if let Ok(color) = parse_color(&contents) {
|
||||||
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(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!(); // Return error.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(RectangleLight::new(arena, &dimensions, &colors));
|
return Ok(RectangleLight::new(arena, &dimensions, &colors));
|
||||||
} else {
|
|
||||||
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::result::Result;
|
use std::{io::BufRead, result::Result};
|
||||||
|
|
||||||
use nom::{sequence::tuple, IResult};
|
use nom::{sequence::tuple, IResult};
|
||||||
|
|
||||||
use kioku::Arena;
|
use kioku::Arena;
|
||||||
|
|
||||||
use data_tree::{
|
use data_tree::{reader::DataTreeReader, Event};
|
||||||
reader::{DataTreeReader, ReaderError},
|
|
||||||
Event,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
math::{Normal, Point},
|
math::{Normal, Point},
|
||||||
|
@ -19,7 +16,6 @@ use crate::{
|
||||||
use super::{
|
use super::{
|
||||||
basics::{ws_f32, ws_usize},
|
basics::{ws_f32, ws_usize},
|
||||||
psy::PsyParseError,
|
psy::PsyParseError,
|
||||||
DataTree,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// pub struct TriangleMesh {
|
// pub struct TriangleMesh {
|
||||||
|
@ -31,20 +27,29 @@ use super::{
|
||||||
|
|
||||||
pub fn parse_mesh_surface<'a>(
|
pub fn parse_mesh_surface<'a>(
|
||||||
arena: &'a Arena,
|
arena: &'a Arena,
|
||||||
events: &mut DataTreeReader,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
ident: Option<&str>,
|
|
||||||
) -> Result<TriangleMesh<'a>, PsyParseError> {
|
) -> Result<TriangleMesh<'a>, PsyParseError> {
|
||||||
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();
|
||||||
let mut face_vert_indices = Vec::new();
|
let mut face_vert_indices = Vec::new();
|
||||||
|
|
||||||
// TODO: make sure there are the right number of various children,
|
loop {
|
||||||
// and other validation.
|
match events.next_event()? {
|
||||||
|
Event::Leaf {
|
||||||
|
type_name: "SurfaceShaderBind",
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
// Get verts
|
Event::Leaf {
|
||||||
for (_, mut text, _) in tree.iter_leaf_children_with_type("Vertices") {
|
type_name: "Vertices",
|
||||||
|
contents,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
// Collect verts for this time sample
|
// Collect verts for this time sample
|
||||||
|
let mut text = contents;
|
||||||
let mut tverts = Vec::new();
|
let mut tverts = Vec::new();
|
||||||
while let IResult::Ok((remaining, vert)) = tuple((ws_f32, ws_f32, ws_f32))(text) {
|
while let IResult::Ok((remaining, vert)) = tuple((ws_f32, ws_f32, ws_f32))(text) {
|
||||||
text = remaining;
|
text = remaining;
|
||||||
|
@ -54,15 +59,13 @@ pub fn parse_mesh_surface<'a>(
|
||||||
verts.push(tverts);
|
verts.push(tverts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure all time samples have same vert count
|
Event::Leaf {
|
||||||
let vert_count = verts[0].len();
|
type_name: "Normals",
|
||||||
for vs in &verts {
|
contents,
|
||||||
assert_eq!(vert_count, vs.len());
|
..
|
||||||
}
|
} => {
|
||||||
|
|
||||||
// Get normals, if they exist
|
|
||||||
for (_, mut text, _) in tree.iter_leaf_children_with_type("Normals") {
|
|
||||||
// Collect normals for this time sample
|
// Collect normals for this time sample
|
||||||
|
let mut text = contents;
|
||||||
let mut tnormals = Vec::new();
|
let mut tnormals = Vec::new();
|
||||||
while let IResult::Ok((remaining, nor)) = tuple((ws_f32, ws_f32, ws_f32))(text) {
|
while let IResult::Ok((remaining, nor)) = tuple((ws_f32, ws_f32, ws_f32))(text) {
|
||||||
text = remaining;
|
text = remaining;
|
||||||
|
@ -72,7 +75,60 @@ pub fn parse_mesh_surface<'a>(
|
||||||
normals.push(tnormals);
|
normals.push(tnormals);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure normal's time samples and vert count match the vertices
|
Event::Leaf {
|
||||||
|
type_name: "FaceVertCounts",
|
||||||
|
contents,
|
||||||
|
byte_offset,
|
||||||
|
} => {
|
||||||
|
if !face_vert_counts.is_empty() {
|
||||||
|
return Err(PsyParseError::WrongNodeCount(
|
||||||
|
byte_offset,
|
||||||
|
"Meshes can only have one FaceVertCounts section.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let mut text = contents;
|
||||||
|
while let IResult::Ok((remaining, count)) = ws_usize(text) {
|
||||||
|
text = remaining;
|
||||||
|
face_vert_counts.push(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::Leaf {
|
||||||
|
type_name: "FaceVertIndices",
|
||||||
|
contents,
|
||||||
|
byte_offset,
|
||||||
|
} => {
|
||||||
|
if !face_vert_indices.is_empty() {
|
||||||
|
return Err(PsyParseError::WrongNodeCount(
|
||||||
|
byte_offset,
|
||||||
|
"Meshes can only have one FaceVertIndices section.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let mut text = contents;
|
||||||
|
while let IResult::Ok((remaining, index)) = ws_usize(text) {
|
||||||
|
text = remaining;
|
||||||
|
face_vert_indices.push(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!(); // Return error.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation: make sure all time samples have same vert count.
|
||||||
|
let vert_count = verts[0].len();
|
||||||
|
for vs in &verts {
|
||||||
|
assert_eq!(vert_count, vs.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation: make sure normal's time samples and vert count match
|
||||||
|
// the vertices.
|
||||||
if !normals.is_empty() {
|
if !normals.is_empty() {
|
||||||
assert_eq!(normals.len(), verts.len());
|
assert_eq!(normals.len(), verts.len());
|
||||||
for ns in &normals {
|
for ns in &normals {
|
||||||
|
@ -80,22 +136,10 @@ pub fn parse_mesh_surface<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get face vert counts
|
// Validation: make sure we have any mesh data.
|
||||||
if let Some((_, mut text, _)) = tree.iter_leaf_children_with_type("FaceVertCounts").nth(0) {
|
if verts.is_empty() || face_vert_counts.is_empty() || face_vert_indices.is_empty() {
|
||||||
while let IResult::Ok((remaining, count)) = ws_usize(text) {
|
todo!("Meshes must have at least one non-empty of each of the following sections: Vertices, FaceVertCounts, FaceVertIndices.");
|
||||||
text = remaining;
|
// Return an error.
|
||||||
|
|
||||||
face_vert_counts.push(count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get face vert indices
|
|
||||||
if let Some((_, mut text, _)) = tree.iter_leaf_children_with_type("FaceVertIndices").nth(0) {
|
|
||||||
while let IResult::Ok((remaining, index)) = ws_usize(text) {
|
|
||||||
text = remaining;
|
|
||||||
|
|
||||||
face_vert_indices.push(index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build triangle mesh
|
// Build triangle mesh
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::result::Result;
|
use std::{io::BufRead, result::Result};
|
||||||
|
|
||||||
use nom::{combinator::all_consuming, IResult};
|
use nom::{combinator::all_consuming, IResult};
|
||||||
|
|
||||||
use data_tree::{
|
use kioku::Arena;
|
||||||
reader::{DataTreeReader, ReaderError},
|
|
||||||
Event,
|
use data_tree::{reader::DataTreeReader, Event};
|
||||||
};
|
|
||||||
|
|
||||||
use crate::shading::{SimpleSurfaceShader, SurfaceShader};
|
use crate::shading::{SimpleSurfaceShader, SurfaceShader};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
basics::ws_f32,
|
basics::ws_f32,
|
||||||
psy::{parse_color, PsyParseError},
|
psy::{parse_color, PsyParseError},
|
||||||
DataTree,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// pub struct TriangleMesh {
|
// pub struct TriangleMesh {
|
||||||
|
@ -25,22 +23,22 @@ use super::{
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn parse_surface_shader(
|
pub fn parse_surface_shader(
|
||||||
events: &mut DataTreeReader,
|
_arena: &Arena,
|
||||||
ident: Option<&str>,
|
events: &mut DataTreeReader<impl BufRead>,
|
||||||
|
_ident: Option<&str>,
|
||||||
) -> Result<Box<dyn SurfaceShader>, PsyParseError> {
|
) -> Result<Box<dyn SurfaceShader>, PsyParseError> {
|
||||||
let type_name = if let Some((_, text, _)) = tree.iter_leaf_children_with_type("Type").nth(0) {
|
// Get shader type.
|
||||||
text.trim()
|
let shader = match events.next_event()? {
|
||||||
} else {
|
Event::Leaf {
|
||||||
return Err(PsyParseError::MissingNode(
|
type_name: "Type",
|
||||||
tree.byte_offset(),
|
contents: "Lambert",
|
||||||
"Expected a Type field in SurfaceShader.",
|
..
|
||||||
));
|
} => {
|
||||||
};
|
let color = if let Event::Leaf {
|
||||||
|
type_name: "Color",
|
||||||
let shader = match type_name {
|
contents,
|
||||||
"Lambert" => {
|
byte_offset,
|
||||||
let color = if let Some((_, contents, byte_offset)) =
|
} = events.next_event()?
|
||||||
tree.iter_leaf_children_with_type("Color").nth(0)
|
|
||||||
{
|
{
|
||||||
if let Ok(color) = parse_color(contents) {
|
if let Ok(color) = parse_color(contents) {
|
||||||
color
|
color
|
||||||
|
@ -50,74 +48,108 @@ pub fn parse_surface_shader(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::MissingNode(
|
return Err(PsyParseError::MissingNode(
|
||||||
tree.byte_offset(),
|
events.byte_offset(),
|
||||||
"Expected a Color field in Lambert SurfaceShader.",
|
"Expected a Color field in Lambert SurfaceShader.",
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Close shader node.
|
||||||
|
if let Event::InnerClose { .. } = events.next_event()? {
|
||||||
|
// Success, do nothing.
|
||||||
|
} else {
|
||||||
|
todo!(); // Return error.
|
||||||
|
}
|
||||||
|
|
||||||
Box::new(SimpleSurfaceShader::Lambert { color: color })
|
Box::new(SimpleSurfaceShader::Lambert { color: color })
|
||||||
}
|
}
|
||||||
|
|
||||||
"GGX" => {
|
Event::Leaf {
|
||||||
|
type_name: "Type",
|
||||||
|
contents: "GGX",
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let mut color = None;
|
||||||
|
let mut roughness = None;
|
||||||
|
let mut fresnel = None;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match events.next_event()? {
|
||||||
// Color
|
// Color
|
||||||
let color = if let Some((_, contents, byte_offset)) =
|
Event::Leaf {
|
||||||
tree.iter_leaf_children_with_type("Color").nth(0)
|
type_name: "Color",
|
||||||
{
|
contents,
|
||||||
if let Ok(color) = parse_color(contents) {
|
byte_offset,
|
||||||
color
|
} => {
|
||||||
|
if let Ok(col) = parse_color(contents) {
|
||||||
|
color = Some(col);
|
||||||
} 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(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
return Err(PsyParseError::MissingNode(
|
|
||||||
tree.byte_offset(),
|
|
||||||
"Expected a Color field in GTR SurfaceShader.",
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Roughness
|
// Roughness
|
||||||
let roughness = if let Some((_, contents, byte_offset)) =
|
Event::Leaf {
|
||||||
tree.iter_leaf_children_with_type("Roughness").nth(0)
|
type_name: "Roughness",
|
||||||
{
|
contents,
|
||||||
if let IResult::Ok((_, roughness)) = all_consuming(ws_f32)(contents) {
|
byte_offset,
|
||||||
roughness
|
} => {
|
||||||
|
if let IResult::Ok((_, rgh)) = all_consuming(ws_f32)(contents) {
|
||||||
|
roughness = Some(rgh);
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError(byte_offset));
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
return Err(PsyParseError::MissingNode(
|
|
||||||
tree.byte_offset(),
|
|
||||||
"Expected a Roughness field in GTR SurfaceShader.",
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fresnel
|
// Fresnel
|
||||||
let fresnel = if let Some((_, contents, byte_offset)) =
|
Event::Leaf {
|
||||||
tree.iter_leaf_children_with_type("Fresnel").nth(0)
|
type_name: "Fresnel",
|
||||||
{
|
contents,
|
||||||
if let IResult::Ok((_, fresnel)) = all_consuming(ws_f32)(contents) {
|
byte_offset,
|
||||||
fresnel
|
} => {
|
||||||
|
if let IResult::Ok((_, frs)) = all_consuming(ws_f32)(contents) {
|
||||||
|
fresnel = Some(frs);
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError(byte_offset));
|
return Err(PsyParseError::UnknownError(byte_offset));
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
Event::InnerClose { .. } => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!(); // Return an error.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation: make sure all fields are present.
|
||||||
|
if color == None || roughness == None || fresnel == None {
|
||||||
return Err(PsyParseError::MissingNode(
|
return Err(PsyParseError::MissingNode(
|
||||||
tree.byte_offset(),
|
events.byte_offset(),
|
||||||
"Expected a Fresnel field in GTR SurfaceShader.",
|
"GGX shader requires one of each field: Color, Roughness, Fresnel.",
|
||||||
));
|
));
|
||||||
};
|
}
|
||||||
|
|
||||||
Box::new(SimpleSurfaceShader::GGX {
|
Box::new(SimpleSurfaceShader::GGX {
|
||||||
color: color,
|
color: color.unwrap(),
|
||||||
roughness: roughness,
|
roughness: roughness.unwrap(),
|
||||||
fresnel: fresnel,
|
fresnel: fresnel.unwrap(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
"Emit" => {
|
Event::Leaf {
|
||||||
let color = if let Some((_, contents, byte_offset)) =
|
type_name: "Type",
|
||||||
tree.iter_leaf_children_with_type("Color").nth(0)
|
contents: "Emit",
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let color = if let Event::Leaf {
|
||||||
|
type_name: "Color",
|
||||||
|
contents,
|
||||||
|
byte_offset,
|
||||||
|
} = events.next_event()?
|
||||||
{
|
{
|
||||||
if let Ok(color) = parse_color(contents) {
|
if let Ok(color) = parse_color(contents) {
|
||||||
color
|
color
|
||||||
|
@ -127,15 +159,34 @@ pub fn parse_surface_shader(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::MissingNode(
|
return Err(PsyParseError::MissingNode(
|
||||||
tree.byte_offset(),
|
events.byte_offset(),
|
||||||
"Expected a Color field in Emit SurfaceShader.",
|
"Expected a Color field in Emit SurfaceShader.",
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Close shader node.
|
||||||
|
if let Event::InnerClose { .. } = events.next_event()? {
|
||||||
|
// Success, do nothing.
|
||||||
|
} else {
|
||||||
|
todo!(); // Return error.
|
||||||
|
}
|
||||||
|
|
||||||
Box::new(SimpleSurfaceShader::Emit { color: color })
|
Box::new(SimpleSurfaceShader::Emit { color: color })
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => unimplemented!(),
|
Event::Leaf {
|
||||||
|
type_name: "Type",
|
||||||
|
byte_offset,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
return Err(PsyParseError::MissingNode(
|
||||||
|
byte_offset,
|
||||||
|
"Unknown SurfaceShader type.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
todo!(); // Return error.
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(shader)
|
Ok(shader)
|
||||||
|
|
|
@ -127,8 +127,6 @@ impl Parser {
|
||||||
self.buf_consumed_idx += bytes_consumed;
|
self.buf_consumed_idx += bytes_consumed;
|
||||||
self.total_bytes_processed += bytes_consumed;
|
self.total_bytes_processed += bytes_consumed;
|
||||||
|
|
||||||
// Hack the borrow checker, which doesn't understand
|
|
||||||
// loops apparently, and return.
|
|
||||||
Ok(event.add_to_byte_offset(self.total_bytes_processed - self.buf_consumed_idx))
|
Ok(event.add_to_byte_offset(self.total_bytes_processed - self.buf_consumed_idx))
|
||||||
}
|
}
|
||||||
EventParse::ReachedEnd => {
|
EventParse::ReachedEnd => {
|
||||||
|
@ -157,6 +155,56 @@ impl Parser {
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn peek_event<'a>(&'a mut self) -> Result<Event<'a>, Error> {
|
||||||
|
// Remove any consumed data.
|
||||||
|
if self.buf_consumed_idx > 0 {
|
||||||
|
self.buffer.replace_range(..self.buf_consumed_idx, "");
|
||||||
|
self.buf_consumed_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to parse an event from the valid prefix.
|
||||||
|
match try_parse_event(&self.buffer) {
|
||||||
|
EventParse::Ok(event, _bytes_consumed) => {
|
||||||
|
if let Event::InnerClose { byte_offset, .. } = event {
|
||||||
|
if self.inner_opens == 0 {
|
||||||
|
return Err(Error::UnexpectedClose(
|
||||||
|
byte_offset + self.total_bytes_processed,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(event.add_to_byte_offset(self.total_bytes_processed))
|
||||||
|
}
|
||||||
|
EventParse::ReachedEnd => {
|
||||||
|
// If we consumed all data, then if all nodes are properly
|
||||||
|
// closed we're done. Otherwise we need more input.
|
||||||
|
if self.inner_opens == 0 {
|
||||||
|
Ok(Event::ValidEnd)
|
||||||
|
} else {
|
||||||
|
Ok(Event::NeedMoreInput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EventParse::IncompleteData => Ok(Event::NeedMoreInput),
|
||||||
|
|
||||||
|
// Hard errors.
|
||||||
|
EventParse::ExpectedTypeNameOrInnerClose(byte_offset) => Err(
|
||||||
|
Error::ExpectedTypeNameOrClose(byte_offset + self.total_bytes_processed),
|
||||||
|
),
|
||||||
|
EventParse::ExpectedOpenOrIdent(byte_offset) => Err(Error::ExpectedOpenOrIdent(
|
||||||
|
byte_offset + self.total_bytes_processed,
|
||||||
|
)),
|
||||||
|
EventParse::ExpectedInnerOpen(byte_offset) => Err(Error::ExpectedOpen(
|
||||||
|
byte_offset + self.total_bytes_processed,
|
||||||
|
)),
|
||||||
|
EventParse::UnexpectedIdent(byte_offset) => Err(Error::UnexpectedIdent(
|
||||||
|
byte_offset + self.total_bytes_processed,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn byte_offset(&self) -> usize {
|
||||||
|
self.total_bytes_processed + self.buf_consumed_idx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
|
@ -81,4 +81,41 @@ impl<R: std::io::BufRead> DataTreeReader<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn peek_event<'a>(&'a mut self) -> Result<Event<'a>, ReaderError> {
|
||||||
|
loop {
|
||||||
|
let valid_end = match self.parser.peek_event()? {
|
||||||
|
Event::ValidEnd => true,
|
||||||
|
Event::NeedMoreInput => false,
|
||||||
|
e => {
|
||||||
|
return Ok(unsafe {
|
||||||
|
// Transmute because the borrow checker is
|
||||||
|
// over-conservative about this. It thinks
|
||||||
|
// the liftime isn't valid, but since we aren't
|
||||||
|
// mutating self after returning (and in fact
|
||||||
|
// can't because of the borrow) there's no way for
|
||||||
|
// the references in this to become invalid.
|
||||||
|
std::mem::transmute::<Event, Event>(e)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if !self.eof {
|
||||||
|
self.buf.clear();
|
||||||
|
let read = self.reader.read_line(&mut self.buf)?;
|
||||||
|
self.parser.push_data(&self.buf);
|
||||||
|
if read == 0 {
|
||||||
|
self.eof = true;
|
||||||
|
}
|
||||||
|
} else if !valid_end {
|
||||||
|
return Err(ReaderError::UnexpectedEOF);
|
||||||
|
} else {
|
||||||
|
return Ok(Event::ValidEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn byte_offset(&self) -> usize {
|
||||||
|
self.parser.byte_offset()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user