mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-07-08 01:31:53 +08:00
Add support read archiver from file directly
This commit is contained in:
20
src/main.rs
20
src/main.rs
@@ -96,8 +96,10 @@ pub fn parse_script(
|
|||||||
for builder in scripts::BUILDER.iter() {
|
for builder in scripts::BUILDER.iter() {
|
||||||
if typ == builder.script_type() {
|
if typ == builder.script_type() {
|
||||||
let encoding = get_encoding(arg, builder);
|
let encoding = get_encoding(arg, builder);
|
||||||
let data = utils::files::read_file(filename)?;
|
return Ok((
|
||||||
return Ok((builder.build_script(data, encoding, config)?, builder));
|
builder.build_script_from_file(filename, encoding, config)?,
|
||||||
|
builder,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,8 +123,10 @@ pub fn parse_script(
|
|||||||
if exts_builder.len() == 1 {
|
if exts_builder.len() == 1 {
|
||||||
let builder = exts_builder.first().unwrap();
|
let builder = exts_builder.first().unwrap();
|
||||||
let encoding = get_encoding(arg, builder);
|
let encoding = get_encoding(arg, builder);
|
||||||
let data = utils::files::read_file(filename)?;
|
return Ok((
|
||||||
return Ok((builder.build_script(data, encoding, config)?, builder));
|
builder.build_script_from_file(filename, encoding, config)?,
|
||||||
|
builder,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let mut buf = [0u8; 1024];
|
let mut buf = [0u8; 1024];
|
||||||
let mut size = 0;
|
let mut size = 0;
|
||||||
@@ -149,8 +153,10 @@ pub fn parse_script(
|
|||||||
if best_builders.len() == 1 {
|
if best_builders.len() == 1 {
|
||||||
let builder = best_builders.first().unwrap();
|
let builder = best_builders.first().unwrap();
|
||||||
let encoding = get_encoding(arg, builder);
|
let encoding = get_encoding(arg, builder);
|
||||||
let data = utils::files::read_file(filename)?;
|
return Ok((
|
||||||
return Ok((builder.build_script(data, encoding, config)?, builder));
|
builder.build_script_from_file(filename, encoding, config)?,
|
||||||
|
builder,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if best_builders.len() > 1 {
|
if best_builders.len() > 1 {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
@@ -236,7 +242,7 @@ pub fn export_script(
|
|||||||
is_dir: bool,
|
is_dir: bool,
|
||||||
) -> anyhow::Result<types::ScriptResult> {
|
) -> anyhow::Result<types::ScriptResult> {
|
||||||
eprintln!("Exporting {}", filename);
|
eprintln!("Exporting {}", filename);
|
||||||
let script = parse_script(filename, arg, config)?.0;
|
let mut script = parse_script(filename, arg, config)?.0;
|
||||||
if script.is_archive() {
|
if script.is_archive() {
|
||||||
let odir = match output.as_ref() {
|
let odir = match output.as_ref() {
|
||||||
Some(output) => {
|
Some(output) => {
|
||||||
|
|||||||
@@ -15,6 +15,16 @@ pub trait ScriptBuilder: std::fmt::Debug {
|
|||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>>;
|
) -> 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 extensions(&self) -> &'static [&'static str];
|
||||||
|
|
||||||
fn is_this_format(&self, _filename: &str, _buf: &[u8], _buf_len: usize) -> Option<u8> {
|
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 script_type(&self) -> &'static ScriptType;
|
||||||
|
|
||||||
|
fn is_archive(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ArchiveContent {
|
pub trait ArchiveContent {
|
||||||
@@ -64,7 +78,7 @@ pub trait Script: std::fmt::Debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn iter_archive<'a>(
|
fn iter_archive<'a>(
|
||||||
&'a self,
|
&'a mut self,
|
||||||
) -> Result<Box<dyn Iterator<Item = Result<Box<dyn ArchiveContent>>> + 'a>> {
|
) -> Result<Box<dyn Iterator<Item = Result<Box<dyn ArchiveContent>>> + 'a>> {
|
||||||
Ok(Box::new(std::iter::empty()))
|
Ok(Box::new(std::iter::empty()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use super::crypto::*;
|
use super::crypto::*;
|
||||||
use crate::ext::io::*;
|
|
||||||
use crate::scripts::base::*;
|
use crate::scripts::base::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use crate::utils::encoding::decode_to_string;
|
use crate::utils::encoding::decode_to_string;
|
||||||
|
use crate::ext::io::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
@@ -26,7 +26,27 @@ impl ScriptBuilder for EscudeBinArchiveBuilder {
|
|||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>> {
|
) -> 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] {
|
fn extensions(&self) -> &'static [&'static str] {
|
||||||
@@ -43,6 +63,10 @@ impl ScriptBuilder for EscudeBinArchiveBuilder {
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_archive(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -72,17 +96,16 @@ impl ArchiveContent for Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EscudeBinArchive {
|
pub struct EscudeBinArchive<T: Read + Seek + std::fmt::Debug> {
|
||||||
reader: MemReader,
|
reader: T,
|
||||||
file_count: u32,
|
file_count: u32,
|
||||||
name_tbl_len: u32,
|
name_tbl_len: u32,
|
||||||
entries: Vec<BinEntry>,
|
entries: Vec<BinEntry>,
|
||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EscudeBinArchive {
|
impl<T: Read + Seek + std::fmt::Debug> EscudeBinArchive<T> {
|
||||||
pub fn new(data: Vec<u8>, encoding: Encoding, _config: &ExtraConfig) -> Result<Self> {
|
pub fn new(mut reader: T, encoding: Encoding, _config: &ExtraConfig) -> Result<Self> {
|
||||||
let mut reader = MemReader::new(data);
|
|
||||||
let mut header = [0u8; 8];
|
let mut header = [0u8; 8];
|
||||||
reader.read_exact(&mut header)?;
|
reader.read_exact(&mut header)?;
|
||||||
if &header != b"ESC-ARC2" {
|
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 {
|
fn default_output_script_type(&self) -> OutputScriptType {
|
||||||
OutputScriptType::Json
|
OutputScriptType::Json
|
||||||
}
|
}
|
||||||
@@ -127,27 +150,28 @@ impl Script for EscudeBinArchive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn iter_archive<'a>(
|
fn iter_archive<'a>(
|
||||||
&'a self,
|
&'a mut self,
|
||||||
) -> Result<Box<dyn Iterator<Item = Result<Box<dyn ArchiveContent>>> + 'a>> {
|
) -> Result<Box<dyn Iterator<Item = Result<Box<dyn ArchiveContent>>> + 'a>> {
|
||||||
let reader = self.reader.to_ref();
|
|
||||||
let encoding = self.encoding;
|
let encoding = self.encoding;
|
||||||
Ok(Box::new(EscudeBinArchiveIterator {
|
Ok(Box::new(EscudeBinArchiveIterator {
|
||||||
entries: self.entries.iter(),
|
entries: self.entries.iter(),
|
||||||
reader,
|
reader: &mut self.reader,
|
||||||
encoding,
|
encoding,
|
||||||
file_count: self.file_count,
|
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,
|
entries: T,
|
||||||
reader: MemReaderRef<'a>,
|
reader: &'a mut R,
|
||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
file_count: u32,
|
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>>;
|
type Item = Result<Box<dyn ArchiveContent>>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
|||||||
Reference in New Issue
Block a user