use std::io;
use indextree::Arena;
use log::{debug, error, trace};
use string_interner::{DefaultBackend, StringInterner};
use crate::{
low::v7400::FbxFooter,
pull_parser::{
v7400::{attribute::loaders::DirectLoader, Event, Parser, StartNode},
Error as ParserError,
},
tree::v7400::{LoadError, NodeData, NodeId, NodeNameSym, Tree},
};
#[derive(Debug, Clone)]
pub struct Loader {
arena: Arena<NodeData>,
node_names: StringInterner<DefaultBackend<NodeNameSym>>,
root_id: NodeId,
}
impl Loader {
#[inline]
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn load<R: io::Read>(
mut self,
parser: &mut Parser<R>,
) -> Result<(Tree, Result<Box<FbxFooter>, ParserError>), LoadError> {
debug!("Loading FBX data tree from a parser");
if parser.is_used() {
error!("The given parser should be brand-new, but it has already emitted some events");
return Err(LoadError::BadParser);
}
let mut open_nodes = vec![self.root_id];
let footer = loop {
trace!("Loading next parser event: open_nodes={:?}", open_nodes);
assert!(
!open_nodes.is_empty(),
"Open nodes stack should not be empty on loop start"
);
match parser.next_event()? {
Event::StartNode(start) => {
trace!("Got `Event::StartNode(name={:?})`", start.name());
let parent = open_nodes
.last_mut()
.expect("Should never fail: Open nodes stack should not be empty here");
let current = self.add_node(*parent, start)?;
open_nodes.push(current);
}
Event::EndNode => {
trace!("Got `Event::EndNode`");
open_nodes
.pop()
.expect("Should never fail: Open nodes stack should not be empty here");
}
Event::EndFbx(footer) => {
trace!("Got `Event::EndFbx(_)`");
open_nodes
.pop()
.expect("Should never fail: Open nodes stack should not be empty here");
break footer;
}
}
};
assert!(
open_nodes.is_empty(),
"Should never fail: There should be no open nodes after `EndFbx` event is emitted"
);
debug!("Successfully loaded FBX data tree");
let tree = Tree::new(self.arena, self.node_names, self.root_id);
Ok((tree, footer))
}
fn add_node<R: io::Read>(
&mut self,
parent: NodeId,
start: StartNode<'_, R>,
) -> Result<NodeId, LoadError> {
trace!(
"Adding a new child name={:?} to the parent {:?}",
start.name(),
parent
);
let current = {
let name_sym = self.node_names.get_or_intern(start.name());
let attributes = start
.attributes()
.into_iter(std::iter::repeat(DirectLoader))
.collect::<Result<Vec<_>, _>>()?;
NodeId::new(self.arena.new_node(NodeData::new(name_sym, attributes)))
};
parent.raw().append(current.raw(), &mut self.arena);
trace!(
"Successfully added a new child {:?} to the parent {:?}",
current,
parent
);
Ok(current)
}
}
impl Default for Loader {
fn default() -> Self {
let mut arena = Arena::new();
let mut node_names = StringInterner::new();
let root_id = {
let empty_sym = node_names.get_or_intern("");
NodeId::new(arena.new_node(NodeData::new(empty_sym, Vec::new())))
};
Self {
arena,
node_names,
root_id,
}
}
}