Add m3t support

This commit is contained in:
2025-05-20 23:19:09 +08:00
parent 8aaf2da626
commit 63b09fc893
5 changed files with 106 additions and 12 deletions

View File

@@ -1,4 +1,5 @@
pub mod args; pub mod args;
pub mod output_scripts;
pub mod scripts; pub mod scripts;
pub mod types; pub mod types;
pub mod utils; pub mod utils;
@@ -82,7 +83,10 @@ pub fn parse_script(
filename: &str, filename: &str,
arg: &args::Arg, arg: &args::Arg,
config: &types::ExtraConfig, config: &types::ExtraConfig,
) -> anyhow::Result<(Box<dyn scripts::Script>, &'static Box<dyn scripts::ScriptBuilder + Send + Sync>)> { ) -> anyhow::Result<(
Box<dyn scripts::Script>,
&'static Box<dyn scripts::ScriptBuilder + Send + Sync>,
)> {
match &arg.script_type { match &arg.script_type {
Some(typ) => { Some(typ) => {
for builder in scripts::BUILDER.iter() { for builder in scripts::BUILDER.iter() {
@@ -160,7 +164,13 @@ pub fn export_script(
let mut f = utils::files::write_file(&f)?; let mut f = utils::files::write_file(&f)?;
f.write_all(&b)?; f.write_all(&b)?;
} }
_ => {} types::OutputScriptType::M3t => {
let enc = get_output_encoding(arg);
let s = output_scripts::m3t::M3tDumper::dump(&mes);
let b = utils::encoding::encode_string(enc, &s)?;
let mut f = utils::files::write_file(&f)?;
f.write_all(&b)?;
}
} }
Ok(()) Ok(())
} }
@@ -189,6 +199,10 @@ pub fn import_script(
} else { } else {
imp_cfg.output.clone() imp_cfg.output.clone()
}; };
if !std::fs::exists(&out_f).unwrap_or(false) {
eprintln!("Output file does not exist");
return Ok(());
}
let mes = match of { let mes = match of {
types::OutputScriptType::Json => { types::OutputScriptType::Json => {
let enc = get_output_encoding(arg); let enc = get_output_encoding(arg);
@@ -196,8 +210,12 @@ pub fn import_script(
let s = utils::encoding::decode_to_string(enc, &b)?; let s = utils::encoding::decode_to_string(enc, &b)?;
serde_json::from_str::<Vec<types::Message>>(&s)? serde_json::from_str::<Vec<types::Message>>(&s)?
} }
_ => { types::OutputScriptType::M3t => {
return Err(anyhow::anyhow!("Unsupported script type")); let enc = get_output_encoding(arg);
let b = utils::files::read_file(&out_f)?;
let s = utils::encoding::decode_to_string(enc, &b)?;
let mut parser = output_scripts::m3t::M3tParser::new(&s);
parser.parse()?
} }
}; };
if mes.is_empty() { if mes.is_empty() {
@@ -244,8 +262,7 @@ fn main() {
std::fs::create_dir_all(op).unwrap(); std::fs::create_dir_all(op).unwrap();
} }
} }
None => { None => {}
}
} }
} }
for script in scripts.iter() { for script in scripts.iter() {

79
src/output_scripts/m3t.rs Normal file
View File

@@ -0,0 +1,79 @@
use crate::types::Message;
use anyhow::Result;
pub struct M3tParser<'a> {
str: &'a str,
line: usize,
}
impl<'a> M3tParser<'a> {
pub fn new(str: &'a str) -> Self {
M3tParser { str, line: 1 }
}
fn next_line(&mut self) -> Option<&'a str> {
match self.str.find('\n') {
Some(pos) => {
let line = &self.str[..pos];
self.str = &self.str[pos + 1..];
self.line += 1;
Some(line.trim())
}
None => {
if !self.str.is_empty() {
let line = self.str;
self.str = "";
Some(line)
} else {
None
}
}
}
}
pub fn parse(&mut self) -> Result<Vec<Message>> {
let mut messages = Vec::new();
let mut name = None;
while let Some(line) = self.next_line() {
if line.is_empty() {
continue;
}
if line.starts_with("") {
let line = line[3..].trim();
if line.starts_with("NAME:") {
name = Some(line[5..].trim().to_string());
}
} else if line.starts_with("") {
let message = line[3..].trim();
messages.push(Message::new(message.replace("\\n", "\n"), name.take()));
} else {
return Err(anyhow::anyhow!(
"Invalid line format at line {}: {}",
self.line,
line
));
}
}
Ok(messages)
}
}
pub struct M3tDumper {}
impl M3tDumper {
pub fn dump(messages: &[Message]) -> String {
let mut result = String::new();
for message in messages {
if let Some(name) = &message.name {
result.push_str(&format!("○ NAME: {}\n\n", name));
}
result.push_str(&format!("{}\n", message.message.replace("\n", "\\n")));
if message.message.starts_with("") {
result.push_str("● 「」\n\n");
} else {
result.push_str("\n\n");
}
}
result
}
}

View File

@@ -0,0 +1 @@
pub mod m3t;

View File

@@ -311,10 +311,7 @@ impl Script for CircusMesScript {
self.asm_bin_offset + token.offset + token.length, self.asm_bin_offset + token.offset + token.length,
self.data.len(), self.data.len(),
); );
buffer.extend_from_slice( buffer.extend_from_slice(&self.data[self.asm_bin_offset + token.offset..len]);
&self.data[self.asm_bin_offset + token.offset
..len]
);
} }
let mut f = crate::utils::files::write_file(filename)?; let mut f = crate::utils::files::write_file(filename)?;
f.write_all(&buffer)?; f.write_all(&buffer)?;

View File

@@ -43,7 +43,7 @@ pub enum TextEncoding {
/// Script type /// Script type
pub enum OutputScriptType { pub enum OutputScriptType {
/// Text script /// Text script
Txt, M3t,
/// JSON which can be used for GalTransl /// JSON which can be used for GalTransl
Json, Json,
} }
@@ -51,7 +51,7 @@ pub enum OutputScriptType {
impl AsRef<str> for OutputScriptType { impl AsRef<str> for OutputScriptType {
fn as_ref(&self) -> &str { fn as_ref(&self) -> &str {
match self { match self {
OutputScriptType::Txt => "txt", OutputScriptType::M3t => "m3t",
OutputScriptType::Json => "json", OutputScriptType::Json => "json",
} }
} }