jabyengine/src/Tools/psxcdgen_ex/src/config_reader/xml.rs

111 lines
3.5 KiB
Rust

use std::path::PathBuf;
use crate::config_reader::Directory;
use super::{Configuration, ErrorString, File};
pub fn parse(xml: String) -> Result<Configuration, Error> {
let mut config = Configuration::new();
let parser = roxmltree::Document::parse(xml.as_str())?;
let children = parser.root().children();
for node in children {
if node.is_element() && node.tag_name().name() == "ISO_Project" {
parse_iso_project(node, &mut config)?;
}
}
Ok(config)
}
fn parse_iso_project(iso_project: roxmltree::Node, config: &mut Configuration) -> Result<(), Error> {
for node in iso_project.children() {
if node.is_element() {
match node.tag_name().name() {
"Description" => parse_description(node, config),
"Track" => parse_track(node, config)?,
_ => ()
}
}
}
Ok(())
}
fn parse_description(description: roxmltree::Node, config: &mut Configuration) {
for node in description.descendants() {
if node.is_element() {
match node.tag_name().name() {
"Publisher" => config.publisher = Some(String::from(node.text().unwrap_or_default())),
"License" => config.license_path = Some(PathBuf::from(node.text().unwrap_or_default())),
_ => ()
}
}
}
}
fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(), Error> {
fn parse_file(file: roxmltree::Node) -> Result<File, Error> {
Ok(File{
name: String::from(file.attribute("name").unwrap_or_default()),
path: PathBuf::from(file.text().unwrap_or_default()),
is_hidden: parse_boolean_attribute(&file, "hidden")?
})
}
fn parse_file_system(cur_node: roxmltree::Node, root: &mut Directory) -> Result<(), Error> {
for node in cur_node.children() {
if node.is_element() {
match node.tag_name().name() {
"File" => root.add_file(parse_file(node)?),
"Directory" => {
let mut new_dir = Directory::new(node.attribute("name").unwrap_or_default());
parse_file_system(node, &mut new_dir)?;
root.add_dir(new_dir);
},
_ => (),
}
}
}
Ok(())
}
parse_file_system(track, &mut config.root)
}
fn parse_boolean_attribute(xml: &roxmltree::Node, attribute_name: &str) -> Result<bool, Error> {
if let Some(bool_str) = xml.attribute(attribute_name) {
match bool_str {
"true" | "1" => Ok(true),
"false" | "0" => Ok(false),
_ => {
return Err(Error::Generic(super::Error::from_text(format!("Attribute \"{}\" expects either true,false or 1,0 as valid attributes - found {}", attribute_name, bool_str))));
}
}
}
else {
Ok(false)
}
}
pub enum Error {
XML(roxmltree::Error),
Generic(super::Error)
}
impl ErrorString for Error {
fn to_string(self) -> String {
match self {
Self::XML(xml) => xml.to_string(),
Self::Generic(generic) => generic.to_string()
}
}
}
impl std::convert::From<roxmltree::Error> for Error {
fn from(error: roxmltree::Error) -> Error {
Error::XML(error)
}
}