From a64d0e038027850a621c01e5c7c9f85a827afa2c Mon Sep 17 00:00:00 2001 From: lifegpc Date: Wed, 11 Jun 2025 12:03:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20ArchiveContent=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E6=94=B9=E4=B8=BA=E4=BD=BF=E7=94=A8=20MemRea?= =?UTF-8?q?der=20=E5=A4=84=E7=90=86=E6=95=B0=E6=8D=AE=EF=BC=8C=E6=8F=90?= =?UTF-8?q?=E5=8D=87=E5=86=85=E5=AD=98=E7=AE=A1=E7=90=86=E6=95=88=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 35 +++++++++++-------------- src/scripts/base.rs | 12 +++++++-- src/scripts/escude/archive.rs | 31 +++++++++++++++++----- src/scripts/yaneurao/itufuru/archive.rs | 25 +++++++++++++----- 4 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/main.rs b/src/main.rs index e4611c2..5bdcb53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -235,7 +235,7 @@ pub fn parse_script( } pub fn parse_script_from_archive( - file: &Box, + file: &mut Box, arg: &args::Arg, config: &types::ExtraConfig, ) -> anyhow::Result<( @@ -250,7 +250,7 @@ pub fn parse_script_from_archive( let archive_encoding = get_archived_encoding(arg, builder, encoding); return Ok(( builder.build_script( - file.data().to_vec(), + file.data()?, file.name(), encoding, archive_encoding, @@ -284,7 +284,7 @@ pub fn parse_script_from_archive( let archive_encoding = get_archived_encoding(arg, builder, encoding); return Ok(( builder.build_script( - file.data().to_vec(), + file.data()?, file.name(), encoding, archive_encoding, @@ -293,9 +293,10 @@ pub fn parse_script_from_archive( builder, )); } + let buf = file.data()?; let mut scores = Vec::new(); for builder in exts_builder.iter() { - if let Some(score) = builder.is_this_format(file.name(), file.data(), file.data().len()) { + if let Some(score) = builder.is_this_format(file.name(), buf.as_slice(), buf.len()) { scores.push((score, builder)); } } @@ -314,13 +315,7 @@ pub fn parse_script_from_archive( let encoding = get_encoding(arg, builder); let archive_encoding = get_archived_encoding(arg, builder, encoding); return Ok(( - builder.build_script( - file.data().to_vec(), - file.name(), - encoding, - archive_encoding, - config, - )?, + builder.build_script(buf, file.name(), encoding, archive_encoding, config)?, builder, )); } @@ -366,9 +361,9 @@ pub fn export_script( std::fs::create_dir_all(&odir)?; } for f in script.iter_archive_mut()? { - let f = f?; + let mut f = f?; if f.is_script() { - let (script_file, _) = parse_script_from_archive(&f, arg, config)?; + let (script_file, _) = parse_script_from_archive(&mut f, arg, config)?; let mut of = match &arg.output_type { Some(t) => t.clone(), None => script_file.default_output_script_type(), @@ -502,7 +497,7 @@ pub fn export_script( } } match utils::files::write_file(&out_path) { - Ok(mut fi) => match fi.write_all(f.data()) { + Ok(mut fi) => match std::io::copy(&mut f, &mut fi) { Ok(_) => {} Err(e) => { eprintln!("Error writing to file {}: {}", out_path.display(), e); @@ -629,10 +624,10 @@ pub fn import_script( let enc = get_patched_archive_encoding(imp_cfg, builder, pencoding); let mut arch = builder.create_archive(&patched_f, &files, enc, config)?; for f in script.iter_archive_mut()? { - let f = f?; + let mut f = f?; let mut writer = arch.new_file(f.name())?; if f.is_script() { - let (script_file, _) = parse_script_from_archive(&f, arg, config)?; + let (script_file, _) = parse_script_from_archive(&mut f, arg, config)?; let mut of = match &arg.output_type { Some(t) => t.clone(), None => script_file.default_output_script_type(), @@ -657,7 +652,7 @@ pub fn import_script( ); COUNTER.inc_warning(); } - match writer.write_all(f.data()) { + match std::io::copy(&mut f, &mut writer) { Ok(_) => {} Err(e) => { eprintln!("Error writing to file {}: {}", out_path.display(), e); @@ -821,7 +816,7 @@ pub fn import_script( out_path.display() ); COUNTER.inc_warning(); - match writer.write_all(f.data()) { + match std::io::copy(&mut f, &mut writer) { Ok(_) => {} Err(e) => { eprintln!("Error writing to file {}: {}", out_path.display(), e); @@ -1032,7 +1027,7 @@ pub fn unpack_archive( std::fs::create_dir_all(&odir)?; } for f in script.iter_archive_mut()? { - let f = f?; + let mut f = f?; let out_path = std::path::PathBuf::from(&odir).join(f.name()); match utils::files::make_sure_dir_exists(&out_path) { Ok(_) => {} @@ -1047,7 +1042,7 @@ pub fn unpack_archive( } } match utils::files::write_file(&out_path) { - Ok(mut fi) => match fi.write_all(f.data()) { + Ok(mut fi) => match std::io::copy(&mut f, &mut fi) { Ok(_) => {} Err(e) => { eprintln!("Error writing to file {}: {}", out_path.display(), e); diff --git a/src/scripts/base.rs b/src/scripts/base.rs index 2550c30..d1b5033 100644 --- a/src/scripts/base.rs +++ b/src/scripts/base.rs @@ -1,3 +1,4 @@ +use crate::ext::io::*; use crate::types::*; use anyhow::Result; use std::io::{Read, Seek, Write}; @@ -109,15 +110,22 @@ pub trait ScriptBuilder: std::fmt::Debug { } } -pub trait ArchiveContent { +pub trait ArchiveContent: Read { fn name(&self) -> &str; - fn data(&self) -> &[u8]; fn is_script(&self) -> bool { self.script_type().is_some() } fn script_type(&self) -> Option<&ScriptType> { None } + fn data(&mut self) -> Result> { + let mut data = Vec::new(); + self.read_to_end(&mut data)?; + Ok(data) + } + fn to_data<'a>(&'a mut self) -> Result> { + Ok(Box::new(MemReader::new(self.data()?))) + } } pub trait Script: std::fmt::Debug { diff --git a/src/scripts/escude/archive.rs b/src/scripts/escude/archive.rs index 05b78c4..8ad2b22 100644 --- a/src/scripts/escude/archive.rs +++ b/src/scripts/escude/archive.rs @@ -123,7 +123,13 @@ struct BinEntry { struct Entry { name: String, - data: Vec, + data: MemReader, +} + +impl Read for Entry { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.data.read(buf) + } } impl ArchiveContent for Entry { @@ -131,12 +137,22 @@ impl ArchiveContent for Entry { &self.name } - fn data(&self) -> &[u8] { - &self.data + fn script_type(&self) -> Option<&ScriptType> { + if self.data.data.starts_with(b"ESCR1_00") { + Some(&ScriptType::Escude) + } else if self.data.data.starts_with(b"LIST") { + Some(&ScriptType::EscudeList) + } else { + None + } } - fn is_script(&self) -> bool { - self.data.starts_with(b"ESCR1_00") || self.data.starts_with(b"LIST") + fn data(&mut self) -> Result> { + Ok(self.data.data.clone()) + } + + fn to_data<'a>(&'a mut self) -> Result> { + Ok(Box::new(&mut self.data)) } } @@ -288,7 +304,10 @@ impl<'a, T: Iterator, R: Read + Seek> Iterator Err(e) => return Some(Err(e)), }; } - Some(Ok(Box::new(Entry { name, data }))) + Some(Ok(Box::new(Entry { + name, + data: MemReader::new(data), + }))) } } diff --git a/src/scripts/yaneurao/itufuru/archive.rs b/src/scripts/yaneurao/itufuru/archive.rs index 43a4fc9..1268140 100644 --- a/src/scripts/yaneurao/itufuru/archive.rs +++ b/src/scripts/yaneurao/itufuru/archive.rs @@ -134,7 +134,13 @@ struct CustomHeader { struct Entry { name: String, - data: Vec, + data: MemReader, +} + +impl Read for Entry { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.data.read(buf) + } } impl ArchiveContent for Entry { @@ -142,13 +148,17 @@ impl ArchiveContent for Entry { &self.name } - fn data(&self) -> &[u8] { - &self.data - } - fn script_type(&self) -> Option<&ScriptType> { Some(&ScriptType::YaneuraoItufuru) } + + fn data(&mut self) -> Result> { + Ok(self.data.data.clone()) + } + + fn to_data<'a>(&'a mut self) -> Result> { + Ok(Box::new(&mut self.data)) + } } #[derive(Debug)] @@ -250,7 +260,10 @@ impl<'a, T: Iterator, R: Read + Seek> Iterator ) { Ok(data) => { let name = entry.file_name.clone(); - Some(Ok(Box::new(Entry { name, data }))) + Some(Ok(Box::new(Entry { + name, + data: MemReader::new(data), + }))) } Err(e) => Some(Err(anyhow::anyhow!( "Failed to read file {}: {}",