mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-06 21:08:48 +08:00
Add cstl custom export/import
This commit is contained in:
@@ -3,6 +3,7 @@ use crate::scripts::base::*;
|
||||
use crate::types::*;
|
||||
use crate::utils::encoding::*;
|
||||
use anyhow::Result;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -45,6 +46,71 @@ impl ScriptBuilder for CstlScriptBuilder {
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn can_create_file(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn create_file<'a>(
|
||||
&'a self,
|
||||
filename: &'a str,
|
||||
writer: Box<dyn WriteSeek + 'a>,
|
||||
encoding: Encoding,
|
||||
file_encoding: Encoding,
|
||||
) -> Result<()> {
|
||||
create_file(filename, writer, encoding, file_encoding)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_file<T: Write>(
|
||||
custom_filename: &str,
|
||||
mut file: T,
|
||||
encoding: Encoding,
|
||||
output_encoding: Encoding,
|
||||
) -> Result<()> {
|
||||
let input = crate::utils::files::read_file(custom_filename)?;
|
||||
let s = decode_to_string(output_encoding, &input, true)?;
|
||||
let data: BTreeMap<String, Vec<Message>> = serde_json::from_str(&s)?;
|
||||
let count = data
|
||||
.first_key_value()
|
||||
.ok_or(anyhow::anyhow!("No data found in JSON"))?
|
||||
.1
|
||||
.len();
|
||||
for (lang, mess) in &data {
|
||||
if mess.len() != count {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Language {lang} Message count mismatch: expected {}, got {}",
|
||||
count,
|
||||
mess.len()
|
||||
));
|
||||
}
|
||||
}
|
||||
file.write_all(b"CSTL")?;
|
||||
file.write_u32(0)?; // unk
|
||||
let lang_count = data.len();
|
||||
file.write_size(lang_count)?;
|
||||
for lang in data.keys() {
|
||||
let encoded = encode_string(encoding, lang, false)?;
|
||||
file.write_size(encoded.len())?;
|
||||
file.write_all(&encoded)?;
|
||||
}
|
||||
file.write_size(count)?;
|
||||
for i in 0..count {
|
||||
for mess in data.values() {
|
||||
let m = &mess[i];
|
||||
if let Some(name) = &m.name {
|
||||
let encoded_name = encode_string(encoding, name, false)?;
|
||||
file.write_size(encoded_name.len())?;
|
||||
file.write_all(&encoded_name)?;
|
||||
} else {
|
||||
file.write_size(0)?;
|
||||
}
|
||||
let encoded_mes = encode_string(encoding, &m.message, false)?;
|
||||
file.write_size(encoded_mes.len())?;
|
||||
file.write_all(&encoded_mes)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
trait CustomFn {
|
||||
@@ -173,6 +239,14 @@ impl Script for CstlScript {
|
||||
FormatOptions::None
|
||||
}
|
||||
|
||||
fn is_output_supported(&self, _: OutputScriptType) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn custom_output_extension<'a>(&'a self) -> &'a str {
|
||||
"json"
|
||||
}
|
||||
|
||||
fn extract_messages(&self) -> Result<Vec<Message>> {
|
||||
if self.langs.is_empty() || self.data.is_empty() {
|
||||
return Err(anyhow::anyhow!("CSTL script has no languages or data"));
|
||||
@@ -252,4 +326,26 @@ impl Script for CstlScript {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn custom_export(&self, filename: &std::path::Path, encoding: Encoding) -> Result<()> {
|
||||
let mut d = BTreeMap::new();
|
||||
for (lang, data) in self.langs.iter().zip(&self.data) {
|
||||
d.insert(lang, data);
|
||||
}
|
||||
let s = serde_json::to_string_pretty(&d)?;
|
||||
let s = encode_string(encoding, &s, false)?;
|
||||
let mut file = std::fs::File::create(filename)?;
|
||||
file.write_all(&s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn custom_import<'a>(
|
||||
&'a self,
|
||||
custom_filename: &'a str,
|
||||
file: Box<dyn WriteSeek + 'a>,
|
||||
encoding: Encoding,
|
||||
output_encoding: Encoding,
|
||||
) -> Result<()> {
|
||||
create_file(custom_filename, file, encoding, output_encoding)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user