param-xml 1.1.0

Application for converting Smash Ultimate param files to XML and back
mod args;

use args::{Args, Mode};
use clap::Parser;
use prc::hash40::Hash40;
use prc::xml::quick_xml::Error;
use prc::xml::{get_xml_error, read_xml, write_xml, ReadError};
use prc::{open, save};

use std::fs::File;
use std::io::{BufReader, BufWriter, Seek, SeekFrom};
use std::time::Instant;

fn main() {
    let args = Args::parse();

    if let Some(label_file) = args.label {
        let label_clone = Hash40::label_map();
        let mut labels = label_clone.lock().unwrap();
        labels.add_custom_labels_from_path(label_file).unwrap();
        labels.strict = args.strict;
    }

    match args.mode {
        Mode::Asm { file } => {
            let now = Instant::now();
            if let Err(e) = to_prc(&file, args.out.as_deref().unwrap_or("out.prc")) {
                eprintln!("Error in xml-to-prc step: \n{:?}", e);
            } else {
                println!("Completed in {}", now.elapsed().as_secs_f32())
            }
        }
        Mode::Disasm { file } => {
            let now = Instant::now();
            if let Err(e) = to_xml(&file, args.out.as_deref().unwrap_or("out.xml")) {
                eprintln!("Error in prc-to-xml step: \n{:#?}", e);
            } else {
                println!("Completed in {}", now.elapsed().as_secs_f32())
            }
        }
    }
}

fn to_xml(in_path: &str, out_path: &str) -> Result<(), Error> {
    let p = open(in_path)?;
    let mut writer = BufWriter::new(File::create(out_path)?);
    write_xml(&p, &mut writer)
}

fn to_prc(in_path: &str, out_path: &str) -> Result<(), ReadError> {
    let mut file = File::open(in_path)?;
    let mut reader = BufReader::new(&file);
    match read_xml(&mut reader) {
        Ok(p) => {
            save(out_path, &p)?;
            Ok(())
        }
        Err(e) => {
            file.seek(SeekFrom::Start(0))?;
            eprint!("{}", get_xml_error(&mut file, e.start, e.end)?);
            Err(e.error)
        }
    }
}