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 output_scripts;
pub mod scripts;
pub mod types;
pub mod utils;
@@ -82,7 +83,10 @@ pub fn parse_script(
filename: &str,
arg: &args::Arg,
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 {
Some(typ) => {
for builder in scripts::BUILDER.iter() {
@@ -160,7 +164,13 @@ pub fn export_script(
let mut f = utils::files::write_file(&f)?;
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(())
}
@@ -189,6 +199,10 @@ pub fn import_script(
} else {
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 {
types::OutputScriptType::Json => {
let enc = get_output_encoding(arg);
@@ -196,8 +210,12 @@ pub fn import_script(
let s = utils::encoding::decode_to_string(enc, &b)?;
serde_json::from_str::<Vec<types::Message>>(&s)?
}
_ => {
return Err(anyhow::anyhow!("Unsupported script type"));
types::OutputScriptType::M3t => {
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() {
@@ -244,8 +262,7 @@ fn main() {
std::fs::create_dir_all(op).unwrap();
}
}
None => {
}
None => {}
}
}
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.data.len(),
);
buffer.extend_from_slice(
&self.data[self.asm_bin_offset + token.offset
..len]
);
buffer.extend_from_slice(&self.data[self.asm_bin_offset + token.offset..len]);
}
let mut f = crate::utils::files::write_file(filename)?;
f.write_all(&buffer)?;

View File

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