diff --git a/src/main.rs b/src/main.rs index c65af12..3e8103f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -96,8 +96,10 @@ pub fn parse_script( for builder in scripts::BUILDER.iter() { if typ == builder.script_type() { let encoding = get_encoding(arg, builder); - let data = utils::files::read_file(filename)?; - return Ok((builder.build_script(data, encoding, config)?, builder)); + return Ok(( + builder.build_script_from_file(filename, encoding, config)?, + builder, + )); } } } @@ -121,8 +123,10 @@ pub fn parse_script( if exts_builder.len() == 1 { let builder = exts_builder.first().unwrap(); let encoding = get_encoding(arg, builder); - let data = utils::files::read_file(filename)?; - return Ok((builder.build_script(data, encoding, config)?, builder)); + return Ok(( + builder.build_script_from_file(filename, encoding, config)?, + builder, + )); } let mut buf = [0u8; 1024]; let mut size = 0; @@ -149,8 +153,10 @@ pub fn parse_script( if best_builders.len() == 1 { let builder = best_builders.first().unwrap(); let encoding = get_encoding(arg, builder); - let data = utils::files::read_file(filename)?; - return Ok((builder.build_script(data, encoding, config)?, builder)); + return Ok(( + builder.build_script_from_file(filename, encoding, config)?, + builder, + )); } if best_builders.len() > 1 { eprintln!( @@ -236,7 +242,7 @@ pub fn export_script( is_dir: bool, ) -> anyhow::Result { eprintln!("Exporting {}", filename); - let script = parse_script(filename, arg, config)?.0; + let mut script = parse_script(filename, arg, config)?.0; if script.is_archive() { let odir = match output.as_ref() { Some(output) => { diff --git a/src/scripts/base.rs b/src/scripts/base.rs index 2db7e3b..23face3 100644 --- a/src/scripts/base.rs +++ b/src/scripts/base.rs @@ -15,6 +15,16 @@ pub trait ScriptBuilder: std::fmt::Debug { config: &ExtraConfig, ) -> Result>; + fn build_script_from_file( + &self, + filename: &str, + encoding: Encoding, + config: &ExtraConfig, + ) -> Result> { + let data = crate::utils::files::read_file(filename)?; + self.build_script(data, encoding, config) + } + fn extensions(&self) -> &'static [&'static str]; fn is_this_format(&self, _filename: &str, _buf: &[u8], _buf_len: usize) -> Option { @@ -22,6 +32,10 @@ pub trait ScriptBuilder: std::fmt::Debug { } fn script_type(&self) -> &'static ScriptType; + + fn is_archive(&self) -> bool { + false + } } pub trait ArchiveContent { @@ -64,7 +78,7 @@ pub trait Script: std::fmt::Debug { } fn iter_archive<'a>( - &'a self, + &'a mut self, ) -> Result>> + 'a>> { Ok(Box::new(std::iter::empty())) } diff --git a/src/scripts/escude/archive.rs b/src/scripts/escude/archive.rs index 666f5e8..e8c380c 100644 --- a/src/scripts/escude/archive.rs +++ b/src/scripts/escude/archive.rs @@ -1,8 +1,8 @@ use super::crypto::*; -use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; use crate::utils::encoding::decode_to_string; +use crate::ext::io::*; use anyhow::Result; use std::io::{Read, Seek, SeekFrom}; @@ -26,7 +26,27 @@ impl ScriptBuilder for EscudeBinArchiveBuilder { encoding: Encoding, config: &ExtraConfig, ) -> Result> { - Ok(Box::new(EscudeBinArchive::new(data, encoding, config)?)) + Ok(Box::new(EscudeBinArchive::new( + MemReader::new(data), + encoding, + config, + )?)) + } + + fn build_script_from_file( + &self, + filename: &str, + encoding: Encoding, + config: &ExtraConfig, + ) -> Result> { + if filename == "-" { + let data = crate::utils::files::read_file(filename)?; + self.build_script(data, encoding, config) + } else { + let f = std::fs::File::open(filename)?; + let reader = std::io::BufReader::new(f); + Ok(Box::new(EscudeBinArchive::new(reader, encoding, config)?)) + } } fn extensions(&self) -> &'static [&'static str] { @@ -43,6 +63,10 @@ impl ScriptBuilder for EscudeBinArchiveBuilder { } None } + + fn is_archive(&self) -> bool { + true + } } #[derive(Debug)] @@ -72,17 +96,16 @@ impl ArchiveContent for Entry { } #[derive(Debug)] -pub struct EscudeBinArchive { - reader: MemReader, +pub struct EscudeBinArchive { + reader: T, file_count: u32, name_tbl_len: u32, entries: Vec, encoding: Encoding, } -impl EscudeBinArchive { - pub fn new(data: Vec, encoding: Encoding, _config: &ExtraConfig) -> Result { - let mut reader = MemReader::new(data); +impl EscudeBinArchive { + pub fn new(mut reader: T, encoding: Encoding, _config: &ExtraConfig) -> Result { let mut header = [0u8; 8]; reader.read_exact(&mut header)?; if &header != b"ESC-ARC2" { @@ -113,7 +136,7 @@ impl EscudeBinArchive { } } -impl Script for EscudeBinArchive { +impl Script for EscudeBinArchive { fn default_output_script_type(&self) -> OutputScriptType { OutputScriptType::Json } @@ -127,27 +150,28 @@ impl Script for EscudeBinArchive { } fn iter_archive<'a>( - &'a self, + &'a mut self, ) -> Result>> + 'a>> { - let reader = self.reader.to_ref(); let encoding = self.encoding; Ok(Box::new(EscudeBinArchiveIterator { entries: self.entries.iter(), - reader, + reader: &mut self.reader, encoding, file_count: self.file_count, })) } } -struct EscudeBinArchiveIterator<'a, T: Iterator> { +struct EscudeBinArchiveIterator<'a, T: Iterator, R: Read + Seek> { entries: T, - reader: MemReaderRef<'a>, + reader: &'a mut R, encoding: Encoding, file_count: u32, } -impl<'a, T: Iterator> Iterator for EscudeBinArchiveIterator<'a, T> { +impl<'a, T: Iterator, R: Read + Seek> Iterator + for EscudeBinArchiveIterator<'a, T, R> +{ type Item = Result>; fn next(&mut self) -> Option {