From 8c9f2d7d52f6dfdaa4e278de8c2967ce29086e46 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Tue, 20 Jan 2026 09:14:25 +0800 Subject: [PATCH] Use box instead --- src/scripts/entis_gls/csx/base.rs | 25 ++++ src/scripts/entis_gls/csx/mod.rs | 178 +++++++++++++++++++++++++++- src/scripts/entis_gls/csx/v1/img.rs | 23 ++-- src/scripts/entis_gls/csx/v1/mod.rs | 170 +------------------------- src/scripts/mod.rs | 2 +- src/types.rs | 4 +- 6 files changed, 216 insertions(+), 186 deletions(-) create mode 100644 src/scripts/entis_gls/csx/base.rs diff --git a/src/scripts/entis_gls/csx/base.rs b/src/scripts/entis_gls/csx/base.rs new file mode 100644 index 0000000..438460b --- /dev/null +++ b/src/scripts/entis_gls/csx/base.rs @@ -0,0 +1,25 @@ +use crate::scripts::base::*; +use crate::types::*; +use anyhow::Result; +use std::collections::HashMap; +use std::io::Write; + +pub trait ECSImage: std::fmt::Debug { + fn disasm<'a>(&self, writer: Box) -> Result<()>; + fn export(&self) -> Result>; + fn export_multi(&self) -> Result>>; + fn export_all(&self) -> Result>; + fn import<'a>( + &self, + messages: Vec, + file: Box, + replacement: Option<&'a ReplacementTable>, + ) -> Result<()>; + fn import_multi<'a>( + &self, + messages: HashMap>, + file: Box, + replacement: Option<&'a ReplacementTable>, + ) -> Result<()>; + fn import_all<'a>(&self, messages: Vec, file: Box) -> Result<()>; +} diff --git a/src/scripts/entis_gls/csx/mod.rs b/src/scripts/entis_gls/csx/mod.rs index 23ce58f..80ae84b 100644 --- a/src/scripts/entis_gls/csx/mod.rs +++ b/src/scripts/entis_gls/csx/mod.rs @@ -1,3 +1,177 @@ -//! Ported from Crsky/EntisGLS_Tools C# project +//! Entis GLS CSX Script Support +//! +//! Ported from Crsky/EntisGLS_Tools C# project //! Original license: GPL-3.0 -pub mod v1; +mod base; +mod v1; + +use crate::ext::io::*; +use crate::scripts::base::*; +use crate::types::*; +use crate::utils::encoding::*; +use anyhow::Result; +use base::ECSImage; +use v1::ECSExecutionImageV1; + +#[derive(Debug)] +pub struct CSXScriptBuilder {} + +impl CSXScriptBuilder { + pub fn new() -> Self { + Self {} + } +} + +impl ScriptBuilder for CSXScriptBuilder { + fn default_encoding(&self) -> Encoding { + Encoding::Utf16LE + } + + fn build_script( + &self, + buf: Vec, + _filename: &str, + _encoding: Encoding, + _archive_encoding: Encoding, + config: &ExtraConfig, + _archive: Option<&Box>, + ) -> Result> { + Ok(Box::new(CSXScript::new(buf, config)?)) + } + + fn extensions(&self) -> &'static [&'static str] { + &["csx"] + } + + fn script_type(&self) -> &'static ScriptType { + &ScriptType::EntisGlsCsx + } + + fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option { + if buf_len >= 8 && &buf[0..8] == b"Entis\x1a\0\0" { + Some(30) + } else { + None + } + } +} + +#[derive(Debug)] +pub struct CSXScript { + img: Box, + disasm: bool, + custom_yaml: bool, +} + +impl CSXScript { + pub fn new(buf: Vec, config: &ExtraConfig) -> Result { + let reader = MemReader::new(buf); + let img = ECSExecutionImageV1::new(reader.to_ref(), config)?; + Ok(Self { + img: Box::new(img), + disasm: config.entis_gls_csx_disasm, + custom_yaml: config.custom_yaml, + }) + } +} + +impl Script for CSXScript { + fn default_output_script_type(&self) -> OutputScriptType { + OutputScriptType::Json + } + + fn is_output_supported(&self, _output: OutputScriptType) -> bool { + true + } + + fn default_format_type(&self) -> FormatOptions { + FormatOptions::None + } + + fn extract_messages(&self) -> Result> { + self.img.export() + } + + fn import_messages<'a>( + &'a self, + messages: Vec, + file: Box, + _filename: &str, + _encoding: Encoding, + replacement: Option<&'a ReplacementTable>, + ) -> Result<()> { + self.img.import(messages, file, replacement) + } + + fn multiple_message_files(&self) -> bool { + true + } + + fn extract_multiple_messages(&self) -> Result>> { + self.img.export_multi() + } + + fn import_multiple_messages<'a>( + &'a self, + messages: std::collections::HashMap>, + file: Box, + _filename: &str, + _encoding: Encoding, + replacement: Option<&'a ReplacementTable>, + ) -> Result<()> { + self.img.import_multi(messages, file, replacement) + } + + fn custom_output_extension<'a>(&'a self) -> &'a str { + if self.disasm { + "d.txt" + } else if self.custom_yaml { + "yaml" + } else { + "json" + } + } + + fn custom_export(&self, filename: &std::path::Path, encoding: Encoding) -> Result<()> { + if self.disasm { + let file = crate::utils::files::write_file(filename)?; + let file = std::io::BufWriter::new(file); + self.img.disasm(Box::new(file))?; + } else { + let messages = self.img.export_all()?; + let s = if self.custom_yaml { + serde_yaml_ng::to_string(&messages)? + } else { + serde_json::to_string_pretty(&messages)? + }; + let s = encode_string(encoding, &s, false)?; + let mut file = crate::utils::files::write_file(filename)?; + file.write_all(&s)?; + } + Ok(()) + } + + fn custom_import<'a>( + &'a self, + custom_filename: &'a str, + file: Box, + _encoding: Encoding, + output_encoding: Encoding, + ) -> Result<()> { + if self.disasm { + Err(anyhow::anyhow!( + "Importing from disassembly is not supported." + )) + } else { + let data = crate::utils::files::read_file(custom_filename)?; + let s = decode_to_string(output_encoding, &data, false)?; + let messages: Vec = if self.custom_yaml { + serde_yaml_ng::from_str(&s)? + } else { + serde_json::from_str(&s)? + }; + self.img.import_all(messages, file)?; + Ok(()) + } + } +} diff --git a/src/scripts/entis_gls/csx/v1/img.rs b/src/scripts/entis_gls/csx/v1/img.rs index bc2854c..e6d8030 100644 --- a/src/scripts/entis_gls/csx/v1/img.rs +++ b/src/scripts/entis_gls/csx/v1/img.rs @@ -1,3 +1,4 @@ +use super::super::base::*; use super::disasm::*; use super::types::*; use crate::ext::io::*; @@ -34,7 +35,7 @@ pub struct ECSExecutionImage { } impl ECSExecutionImage { - pub fn new(mut reader: MemReader, config: &ExtraConfig) -> Result { + pub fn new(mut reader: MemReaderRef<'_>, config: &ExtraConfig) -> Result { let file_header = EMCFileHeader::unpack(&mut reader, false, Encoding::Utf8)?; // if file_header.signagure != *b"Entis\x1a\0\0" { // return Err(anyhow::anyhow!("Invalid EMC file signature")); @@ -362,8 +363,10 @@ impl ECSExecutionImage { writer.write_all(&data)?; Ok(()) } +} - pub fn disasm<'a>(&self, writer: Box) -> Result<()> { +impl ECSImage for ECSExecutionImage { + fn disasm<'a>(&self, writer: Box) -> Result<()> { let mut disasm = ECSExecutionImageDisassembler::new( self.image.to_ref(), self.ext_const_str.as_ref(), @@ -373,7 +376,7 @@ impl ECSExecutionImage { Ok(()) } - pub fn export(&self) -> Result> { + fn export(&self) -> Result> { let mut disasm = ECSExecutionImageDisassembler::new( self.image.to_ref(), self.ext_const_str.as_ref(), @@ -459,7 +462,7 @@ impl ECSExecutionImage { Ok(messages) } - pub fn export_multi(&self) -> Result>> { + fn export_multi(&self) -> Result>> { let mut key = String::from("global"); let mut messages = HashMap::new(); let mut disasm = ECSExecutionImageDisassembler::new( @@ -576,7 +579,7 @@ impl ECSExecutionImage { Ok(messages) } - pub fn export_all(&self) -> Result> { + fn export_all(&self) -> Result> { let mut disasm = ECSExecutionImageDisassembler::new( self.image.to_ref(), self.ext_const_str.as_ref(), @@ -599,7 +602,7 @@ impl ECSExecutionImage { Ok(messages) } - pub fn import<'a>( + fn import<'a>( &self, messages: Vec, file: Box, @@ -981,7 +984,7 @@ impl ECSExecutionImage { Ok(()) } - pub fn import_multi<'a>( + fn import_multi<'a>( &self, mut messages: HashMap>, file: Box, @@ -1388,11 +1391,7 @@ impl ECSExecutionImage { Ok(()) } - pub fn import_all<'a>( - &self, - messages: Vec, - file: Box, - ) -> Result<()> { + fn import_all<'a>(&self, messages: Vec, file: Box) -> Result<()> { let mut cloned = self.clone(); let mut mess = messages.into_iter(); let mut mes = mess.next(); diff --git a/src/scripts/entis_gls/csx/v1/mod.rs b/src/scripts/entis_gls/csx/v1/mod.rs index 1dea189..4c97edb 100644 --- a/src/scripts/entis_gls/csx/v1/mod.rs +++ b/src/scripts/entis_gls/csx/v1/mod.rs @@ -4,172 +4,4 @@ mod disasm; mod img; mod types; -use crate::ext::io::*; -use crate::scripts::base::*; -use crate::types::*; -use crate::utils::encoding::*; -use anyhow::Result; -use img::ECSExecutionImage; - -#[derive(Debug)] -pub struct CSXScriptBuilder {} - -impl CSXScriptBuilder { - pub fn new() -> Self { - Self {} - } -} - -impl ScriptBuilder for CSXScriptBuilder { - fn default_encoding(&self) -> Encoding { - Encoding::Utf16LE - } - - fn build_script( - &self, - buf: Vec, - _filename: &str, - _encoding: Encoding, - _archive_encoding: Encoding, - config: &ExtraConfig, - _archive: Option<&Box>, - ) -> Result> { - Ok(Box::new(CSXScript::new(buf, config)?)) - } - - fn extensions(&self) -> &'static [&'static str] { - &["csx"] - } - - fn script_type(&self) -> &'static ScriptType { - &ScriptType::EntisGlsCsx1 - } - - fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option { - if buf_len >= 8 && &buf[0..8] == b"Entis\x1a\0\0" { - Some(30) - } else { - None - } - } -} - -#[derive(Debug)] -pub struct CSXScript { - img: ECSExecutionImage, - disasm: bool, - custom_yaml: bool, -} - -impl CSXScript { - pub fn new(buf: Vec, config: &ExtraConfig) -> Result { - let reader = MemReader::new(buf); - let img = ECSExecutionImage::new(reader, config)?; - Ok(Self { - img, - disasm: config.entis_gls_csx_disasm, - custom_yaml: config.custom_yaml, - }) - } -} - -impl Script for CSXScript { - fn default_output_script_type(&self) -> OutputScriptType { - OutputScriptType::Json - } - - fn is_output_supported(&self, _output: OutputScriptType) -> bool { - true - } - - fn default_format_type(&self) -> FormatOptions { - FormatOptions::None - } - - fn extract_messages(&self) -> Result> { - self.img.export() - } - - fn import_messages<'a>( - &'a self, - messages: Vec, - file: Box, - _filename: &str, - _encoding: Encoding, - replacement: Option<&'a ReplacementTable>, - ) -> Result<()> { - self.img.import(messages, file, replacement) - } - - fn multiple_message_files(&self) -> bool { - true - } - - fn extract_multiple_messages(&self) -> Result>> { - self.img.export_multi() - } - - fn import_multiple_messages<'a>( - &'a self, - messages: std::collections::HashMap>, - file: Box, - _filename: &str, - _encoding: Encoding, - replacement: Option<&'a ReplacementTable>, - ) -> Result<()> { - self.img.import_multi(messages, file, replacement) - } - - fn custom_output_extension<'a>(&'a self) -> &'a str { - if self.disasm { - "d.txt" - } else if self.custom_yaml { - "yaml" - } else { - "json" - } - } - - fn custom_export(&self, filename: &std::path::Path, encoding: Encoding) -> Result<()> { - if self.disasm { - let file = crate::utils::files::write_file(filename)?; - let file = std::io::BufWriter::new(file); - self.img.disasm(Box::new(file))?; - } else { - let messages = self.img.export_all()?; - let s = if self.custom_yaml { - serde_yaml_ng::to_string(&messages)? - } else { - serde_json::to_string_pretty(&messages)? - }; - let s = encode_string(encoding, &s, false)?; - let mut file = crate::utils::files::write_file(filename)?; - file.write_all(&s)?; - } - Ok(()) - } - - fn custom_import<'a>( - &'a self, - custom_filename: &'a str, - file: Box, - _encoding: Encoding, - output_encoding: Encoding, - ) -> Result<()> { - if self.disasm { - Err(anyhow::anyhow!( - "Importing from disassembly is not supported." - )) - } else { - let data = crate::utils::files::read_file(custom_filename)?; - let s = decode_to_string(output_encoding, &data, false)?; - let messages: Vec = if self.custom_yaml { - serde_yaml_ng::from_str(&s)? - } else { - serde_json::from_str(&s)? - }; - self.img.import_all(messages, file)?; - Ok(()) - } - } -} +pub use img::ECSExecutionImage as ECSExecutionImageV1; diff --git a/src/scripts/mod.rs b/src/scripts/mod.rs index 72dd0e1..3850682 100644 --- a/src/scripts/mod.rs +++ b/src/scripts/mod.rs @@ -163,7 +163,7 @@ lazy_static::lazy_static! { #[cfg(feature = "musica-arc")] Box::new(musica::archive::paz::PazArcBuilder::new()), #[cfg(feature = "entis-gls")] - Box::new(entis_gls::csx::v1::CSXScriptBuilder::new()), + Box::new(entis_gls::csx::CSXScriptBuilder::new()), ]; /// A list of all script extensions. pub static ref ALL_EXTS: Vec = diff --git a/src/types.rs b/src/types.rs index d2f9736..e3983d5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -681,8 +681,8 @@ pub enum ScriptType { /// Entis GLS srcxml Script EntisGls, #[cfg(feature = "entis-gls")] - /// Entis GLS csx script (version 1) - EntisGlsCsx1, + /// Entis GLS csx script + EntisGlsCsx, #[cfg(feature = "escude-arc")] /// Escude bin archive EscudeArc,