mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-06 04:48:54 +08:00
Add import support for escude list
This commit is contained in:
17
src/main.rs
17
src/main.rs
@@ -548,10 +548,13 @@ pub fn import_script(
|
||||
) -> anyhow::Result<types::ScriptResult> {
|
||||
eprintln!("Importing {}", filename);
|
||||
let (script, builder) = parse_script(filename, arg, config)?;
|
||||
let of = match &arg.output_type {
|
||||
let mut of = match &arg.output_type {
|
||||
Some(t) => t.clone(),
|
||||
None => script.default_output_script_type(),
|
||||
};
|
||||
if !script.is_output_supported(of) {
|
||||
of = script.default_output_script_type();
|
||||
}
|
||||
let out_f = if is_dir {
|
||||
let f = std::path::PathBuf::from(filename);
|
||||
let mut pb = std::path::PathBuf::from(&imp_cfg.output);
|
||||
@@ -581,12 +584,11 @@ pub fn import_script(
|
||||
let mut parser = output_scripts::m3t::M3tParser::new(&s);
|
||||
parser.parse()?
|
||||
}
|
||||
_ => {
|
||||
eprintln!("Unsupported output script type for import: {:?}", of);
|
||||
return Ok(types::ScriptResult::Ignored);
|
||||
types::OutputScriptType::Custom => {
|
||||
Vec::new() // Custom scripts handle their own messages
|
||||
}
|
||||
};
|
||||
if mes.is_empty() {
|
||||
if !of.is_custom() && mes.is_empty() {
|
||||
eprintln!("No messages found");
|
||||
return Ok(types::ScriptResult::Ignored);
|
||||
}
|
||||
@@ -602,6 +604,11 @@ pub fn import_script(
|
||||
} else {
|
||||
imp_cfg.patched.clone()
|
||||
};
|
||||
if of.is_custom() {
|
||||
let enc = get_output_encoding(arg);
|
||||
script.custom_import_filename(&out_f, &patched_f, encoding, enc)?;
|
||||
return Ok(types::ScriptResult::Ok);
|
||||
}
|
||||
let fmt = match imp_cfg.patched_format {
|
||||
Some(fmt) => match fmt {
|
||||
types::FormatType::Fixed => types::FormatOptions::Fixed {
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
use crate::types::*;
|
||||
use anyhow::Result;
|
||||
use std::io::{Read, Seek};
|
||||
use std::io::{Read, Seek, Write};
|
||||
|
||||
pub trait ReadSeek: Read + Seek + std::fmt::Debug {}
|
||||
|
||||
pub trait WriteSeek: Write + Seek {}
|
||||
|
||||
impl<T: Read + Seek + std::fmt::Debug> ReadSeek for T {}
|
||||
|
||||
impl<T: Write + Seek> WriteSeek for T {}
|
||||
|
||||
pub trait ScriptBuilder: std::fmt::Debug {
|
||||
fn default_encoding(&self) -> Encoding;
|
||||
|
||||
@@ -114,6 +118,29 @@ pub trait Script: std::fmt::Debug {
|
||||
))
|
||||
}
|
||||
|
||||
fn custom_import(
|
||||
&self,
|
||||
_custom_filename: &str,
|
||||
_file: Box<dyn WriteSeek>,
|
||||
_encoding: Encoding,
|
||||
_output_encoding: Encoding,
|
||||
) -> Result<()> {
|
||||
Err(anyhow::anyhow!(
|
||||
"This script type does not support custom import."
|
||||
))
|
||||
}
|
||||
|
||||
fn custom_import_filename(
|
||||
&self,
|
||||
custom_filename: &str,
|
||||
filename: &str,
|
||||
encoding: Encoding,
|
||||
output_encoding: Encoding,
|
||||
) -> Result<()> {
|
||||
let f = std::fs::File::create(filename)?;
|
||||
self.custom_import(custom_filename, Box::new(f), encoding, output_encoding)
|
||||
}
|
||||
|
||||
fn is_archive(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::ext::io::*;
|
||||
use crate::scripts::base::*;
|
||||
use crate::types::*;
|
||||
use crate::utils::encoding::encode_string;
|
||||
use crate::utils::struct_pack::*;
|
||||
use crate::{ext::io::*, utils::encoding::decode_to_string};
|
||||
use anyhow::Result;
|
||||
use msg_tool_macro::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -283,6 +283,38 @@ impl Script for EscudeBinList {
|
||||
writer.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn custom_import(
|
||||
&self,
|
||||
custom_filename: &str,
|
||||
mut writer: Box<dyn WriteSeek>,
|
||||
encoding: Encoding,
|
||||
output_encoding: Encoding,
|
||||
) -> Result<()> {
|
||||
let input = crate::utils::files::read_file(custom_filename)?;
|
||||
let s = decode_to_string(output_encoding, &input)?;
|
||||
let entries: Vec<ListEntry> = serde_json::from_str(&s)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to read Escude list from JSON: {}", e))?;
|
||||
writer.write_all(b"LIST")?;
|
||||
writer.write_u32(0)?; // Placeholder for size
|
||||
let mut total_size = 0;
|
||||
for entry in entries {
|
||||
let cur_pos = writer.stream_position()?;
|
||||
writer.write_u32(entry.id)?;
|
||||
writer.write_u32(0)?; // Placeholder for size
|
||||
entry.data.pack(&mut writer, false, encoding)?;
|
||||
let end_pos = writer.stream_position()?;
|
||||
let size = (end_pos - cur_pos - 8) as u32; // 8 bytes for id and size
|
||||
writer.seek(std::io::SeekFrom::Start(cur_pos + 4))?; // Seek to size position
|
||||
writer.write_u32(size)?;
|
||||
writer.seek(std::io::SeekFrom::Start(end_pos))?; // Seek to end
|
||||
total_size += size + 8;
|
||||
}
|
||||
writer.seek(std::io::SeekFrom::Start(4))?; // Seek back to size position
|
||||
writer.write_u32(total_size)?;
|
||||
writer.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
|
||||
|
||||
@@ -83,6 +83,9 @@ pub fn decode_to_string(cp: u32, data: &[u8]) -> Result<String, WinError> {
|
||||
}
|
||||
|
||||
pub fn encode_string(cp: u32, data: &str, check: bool) -> Result<Vec<u8>, WinError> {
|
||||
if data.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let wstr = data.encode_utf16().collect::<Vec<u16>>();
|
||||
let needed_len = unsafe {
|
||||
WideCharToMultiByte(
|
||||
|
||||
Reference in New Issue
Block a user