Add support read archiver from file directly

This commit is contained in:
2025-06-03 09:57:10 +08:00
parent a2248cf529
commit 3e1c7c28fb
3 changed files with 66 additions and 22 deletions

View File

@@ -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<types::ScriptResult> {
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) => {

View File

@@ -15,6 +15,16 @@ pub trait ScriptBuilder: std::fmt::Debug {
config: &ExtraConfig,
) -> Result<Box<dyn Script>>;
fn build_script_from_file(
&self,
filename: &str,
encoding: Encoding,
config: &ExtraConfig,
) -> Result<Box<dyn Script>> {
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<u8> {
@@ -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<Box<dyn Iterator<Item = Result<Box<dyn ArchiveContent>>> + 'a>> {
Ok(Box::new(std::iter::empty()))
}

View File

@@ -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<Box<dyn Script>> {
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<Box<dyn Script>> {
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<T: Read + Seek + std::fmt::Debug> {
reader: T,
file_count: u32,
name_tbl_len: u32,
entries: Vec<BinEntry>,
encoding: Encoding,
}
impl EscudeBinArchive {
pub fn new(data: Vec<u8>, encoding: Encoding, _config: &ExtraConfig) -> Result<Self> {
let mut reader = MemReader::new(data);
impl<T: Read + Seek + std::fmt::Debug> EscudeBinArchive<T> {
pub fn new(mut reader: T, encoding: Encoding, _config: &ExtraConfig) -> Result<Self> {
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<T: Read + Seek + std::fmt::Debug> Script for EscudeBinArchive<T> {
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<Box<dyn Iterator<Item = Result<Box<dyn ArchiveContent>>> + '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<Item = &'a BinEntry>> {
struct EscudeBinArchiveIterator<'a, T: Iterator<Item = &'a BinEntry>, R: Read + Seek> {
entries: T,
reader: MemReaderRef<'a>,
reader: &'a mut R,
encoding: Encoding,
file_count: u32,
}
impl<'a, T: Iterator<Item = &'a BinEntry>> Iterator for EscudeBinArchiveIterator<'a, T> {
impl<'a, T: Iterator<Item = &'a BinEntry>, R: Read + Seek> Iterator
for EscudeBinArchiveIterator<'a, T, R>
{
type Item = Result<Box<dyn ArchiveContent>>;
fn next(&mut self) -> Option<Self::Item> {