1use clap::ValueEnum;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
7#[serde(untagged, rename_all = "camelCase")]
8pub enum Encoding {
10 Auto,
12 Utf8,
14 Cp932,
16 Gb2312,
18 Utf16LE,
20 Utf16BE,
22 #[cfg(windows)]
24 CodePage(u32),
25}
26
27impl Default for Encoding {
28 fn default() -> Self {
29 Encoding::Utf8
30 }
31}
32
33impl Encoding {
34 pub fn is_jis(&self) -> bool {
36 match self {
37 Self::Cp932 => true,
38 #[cfg(windows)]
39 Self::CodePage(code_page) => *code_page == 932,
40 _ => false,
41 }
42 }
43
44 pub fn is_utf16le(&self) -> bool {
46 match self {
47 Self::Utf16LE => true,
48 #[cfg(windows)]
49 Self::CodePage(code_page) => *code_page == 1200,
50 _ => false,
51 }
52 }
53
54 pub fn is_utf16be(&self) -> bool {
56 match self {
57 Self::Utf16BE => true,
58 #[cfg(windows)]
59 Self::CodePage(code_page) => *code_page == 1201,
60 _ => false,
61 }
62 }
63
64 pub fn is_utf8(&self) -> bool {
66 match self {
67 Self::Utf8 => true,
68 #[cfg(windows)]
69 Self::CodePage(code_page) => *code_page == 65001,
70 _ => false,
71 }
72 }
73
74 pub fn charset(&self) -> Option<&'static str> {
76 match self {
77 Self::Auto => None,
78 Self::Utf8 => Some("UTF-8"),
79 Self::Cp932 => Some("shift_jis"),
80 Self::Gb2312 => Some("gbk"),
81 Self::Utf16LE => Some("utf-16le"),
82 Self::Utf16BE => Some("utf-16be"),
83 #[cfg(windows)]
84 Self::CodePage(code_page) => match *code_page {
85 932 => Some("shift_jis"),
86 65001 => Some("utf-8"),
87 1200 => Some("utf-16le"),
88 936 => Some("gbk"),
89 _ => None,
90 },
91 }
92 }
93}
94
95#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
96pub enum TextEncoding {
98 Default,
100 Auto,
102 Utf8,
104 #[value(alias("jis"))]
105 Cp932,
107 #[value(alias("gbk"))]
108 Gb2312,
110}
111
112#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
113pub enum OutputScriptType {
115 M3t,
117 M3ta,
119 M3tTxt,
121 Json,
123 Yaml,
125 Pot,
127 Po,
129 Custom,
131}
132
133impl OutputScriptType {
134 pub fn is_custom(&self) -> bool {
136 matches!(self, OutputScriptType::Custom)
137 }
138
139 pub fn is_m3t(&self) -> bool {
141 matches!(
142 self,
143 OutputScriptType::M3t | OutputScriptType::M3ta | OutputScriptType::M3tTxt
144 )
145 }
146
147 pub fn is_src_supported(&self) -> bool {
149 matches!(
150 self,
151 OutputScriptType::M3t
152 | OutputScriptType::M3ta
153 | OutputScriptType::M3tTxt
154 | OutputScriptType::Po
155 | OutputScriptType::Pot
156 )
157 }
158}
159
160impl AsRef<str> for OutputScriptType {
161 fn as_ref(&self) -> &str {
163 match self {
164 OutputScriptType::M3t => "m3t",
165 OutputScriptType::M3ta => "m3ta",
166 OutputScriptType::M3tTxt => "txt",
167 OutputScriptType::Json => "json",
168 OutputScriptType::Yaml => "yaml",
169 OutputScriptType::Pot => "pot",
170 OutputScriptType::Po => "po",
171 OutputScriptType::Custom => "",
172 }
173 }
174}
175
176#[cfg(feature = "circus")]
177#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
178pub enum CircusMesType {
180 Ffexa,
182 Ffexs,
184 Ef,
186 Dcos,
188 Ktlep,
190 Dcws,
192 Dcsv,
194 Dcpc,
196 Dcmems,
198 Dcdx,
200 Dcas,
202 Dcbs,
204 Dc2fl,
206 Dc2bs,
208 Dc2dm,
210 Dc2fy,
212 Dc2cckko,
214 Dc2ccotm,
216 Dc2sc,
218 Dc2ty,
220 Dc2pc,
222 Dc3rx,
224 Dc3pp,
226 Dc3wy,
228 Dc3dd,
230 Dc4,
232 Dc4ph,
234 Ds,
236 Dsif,
238 Tmpl,
240 Nightshade,
242}
243
244#[cfg(feature = "circus")]
245impl AsRef<str> for CircusMesType {
246 fn as_ref(&self) -> &str {
248 match self {
249 CircusMesType::Ffexa => "ffexa",
250 CircusMesType::Ffexs => "ffexs",
251 CircusMesType::Ef => "ef",
252 CircusMesType::Dcos => "dcos",
253 CircusMesType::Ktlep => "ktlep",
254 CircusMesType::Dcws => "dcws",
255 CircusMesType::Dcsv => "dcsv",
256 CircusMesType::Dcpc => "dcpc",
257 CircusMesType::Dcmems => "dcmems",
258 CircusMesType::Dcdx => "dcdx",
259 CircusMesType::Dcas => "dcas",
260 CircusMesType::Dcbs => "dcbs",
261 CircusMesType::Dc2fl => "dc2fl",
262 CircusMesType::Dc2bs => "dc2bs",
263 CircusMesType::Dc2dm => "dc2dm",
264 CircusMesType::Dc2fy => "dc2fy",
265 CircusMesType::Dc2cckko => "dc2cckko",
266 CircusMesType::Dc2ccotm => "dc2ccotm",
267 CircusMesType::Dc2sc => "dc2sc",
268 CircusMesType::Dc2ty => "dc2ty",
269 CircusMesType::Dc2pc => "dc2pc",
270 CircusMesType::Dc3rx => "dc3rx",
271 CircusMesType::Dc3pp => "dc3pp",
272 CircusMesType::Dc3wy => "dc3wy",
273 CircusMesType::Dc3dd => "dc3dd",
274 CircusMesType::Dc4 => "dc4",
275 CircusMesType::Dc4ph => "dc4ph",
276 CircusMesType::Ds => "ds",
277 CircusMesType::Dsif => "dsif",
278 CircusMesType::Tmpl => "tmpl",
279 CircusMesType::Nightshade => "nightshade",
280 }
281 }
282}
283
284#[derive(Debug, Clone, msg_tool_macro::Default)]
286pub struct ExtraConfig {
287 #[cfg(feature = "circus")]
288 pub circus_mes_type: Option<CircusMesType>,
290 #[cfg(feature = "escude-arc")]
291 pub escude_fake_compress: bool,
293 #[cfg(feature = "escude")]
294 pub escude_enum_scr: Option<String>,
296 #[cfg(feature = "bgi")]
297 pub bgi_import_duplicate: bool,
300 #[cfg(feature = "bgi")]
301 pub bgi_disable_append: bool,
304 #[cfg(feature = "image")]
305 pub image_type: Option<ImageOutputType>,
307 #[cfg(all(feature = "bgi-arc", feature = "bgi-img"))]
308 pub bgi_is_sysgrp_arc: Option<bool>,
310 #[cfg(feature = "bgi-img")]
311 pub bgi_img_scramble: Option<bool>,
314 #[cfg(feature = "cat-system-arc")]
315 pub cat_system_int_encrypt_password: Option<String>,
317 #[cfg(feature = "cat-system-img")]
318 pub cat_system_image_canvas: bool,
320 #[cfg(feature = "kirikiri")]
321 pub kirikiri_language_index: Option<usize>,
323 #[cfg(feature = "kirikiri")]
324 pub kirikiri_export_chat: bool,
327 #[cfg(feature = "kirikiri")]
328 pub kirikiri_chat_key: Option<Vec<String>>,
331 #[cfg(feature = "kirikiri")]
332 pub kirikiri_chat_json:
335 Option<std::sync::Arc<HashMap<String, HashMap<String, (String, usize)>>>>,
336 #[cfg(feature = "kirikiri")]
337 pub kirikiri_languages: Option<std::sync::Arc<Vec<String>>>,
339 #[cfg(feature = "kirikiri")]
340 pub kirikiri_remove_empty_lines: bool,
342 #[cfg(feature = "kirikiri")]
343 pub kirikiri_name_commands: std::sync::Arc<std::collections::HashSet<String>>,
345 #[cfg(feature = "kirikiri")]
346 pub kirikiri_message_commands: std::sync::Arc<std::collections::HashSet<String>>,
348 #[cfg(feature = "bgi-arc")]
349 pub bgi_compress_file: bool,
351 #[cfg(feature = "bgi-arc")]
352 #[default(3)]
353 pub bgi_compress_min_len: usize,
355 #[cfg(feature = "emote-img")]
356 pub emote_pimg_overlay: Option<bool>,
358 #[cfg(feature = "artemis-arc")]
359 pub artemis_arc_disable_xor: bool,
361 #[cfg(feature = "artemis")]
362 pub artemis_indent: Option<usize>,
365 #[cfg(feature = "artemis")]
366 pub artemis_no_indent: bool,
368 #[cfg(feature = "artemis")]
369 #[default(100)]
370 pub artemis_max_line_width: usize,
372 #[cfg(feature = "artemis")]
373 pub artemis_ast_lang: Option<String>,
376 #[cfg(feature = "cat-system")]
377 pub cat_system_cstl_lang: Option<String>,
380 #[cfg(feature = "flate2")]
381 #[default(6)]
382 pub zlib_compression_level: u32,
384 #[cfg(feature = "image")]
385 pub png_compression_level: PngCompressionLevel,
387 #[cfg(feature = "circus-img")]
388 pub circus_crx_keep_original_bpp: bool,
390 #[cfg(feature = "circus-img")]
391 pub circus_crx_zstd: bool,
393 #[cfg(feature = "zstd")]
394 #[default(3)]
395 pub zstd_compression_level: i32,
397 #[cfg(feature = "circus-img")]
398 pub circus_crx_mode: crate::scripts::circus::image::crx::CircusCrxMode,
400 #[cfg(feature = "ex-hibit")]
401 pub ex_hibit_rld_xor_key: Option<u32>,
404 #[cfg(feature = "ex-hibit")]
405 pub ex_hibit_rld_def_xor_key: Option<u32>,
407 #[cfg(feature = "ex-hibit")]
408 pub ex_hibit_rld_keys: Option<Box<[u32; 0x100]>>,
410 #[cfg(feature = "ex-hibit")]
411 pub ex_hibit_rld_def_keys: Option<Box<[u32; 0x100]>>,
413 #[cfg(feature = "mozjpeg")]
414 #[default(80)]
415 pub jpeg_quality: u8,
417 #[cfg(feature = "webp")]
418 pub webp_lossless: bool,
420 #[cfg(feature = "webp")]
421 #[default(80)]
422 pub webp_quality: u8,
424 #[cfg(feature = "circus-img")]
425 pub circus_crx_canvas: bool,
427 pub custom_yaml: bool,
429 #[cfg(feature = "entis-gls")]
430 pub entis_gls_srcxml_lang: Option<String>,
433 #[cfg(feature = "will-plus")]
434 pub will_plus_ws2_no_disasm: bool,
438 #[cfg(feature = "artemis-panmimisoft")]
439 pub artemis_panmimisoft_txt_blacklist_names: std::sync::Arc<std::collections::HashSet<String>>,
442 #[cfg(feature = "artemis-panmimisoft")]
443 pub artemis_panmimisoft_txt_lang: Option<String>,
446 #[cfg(feature = "artemis-panmimisoft")]
447 pub artemis_panmimisoft_txt_multi_lang: bool,
450 #[cfg(feature = "lossless-audio")]
451 pub lossless_audio_fmt: LosslessAudioFormat,
453 #[cfg(feature = "audio-flac")]
454 #[default(5)]
455 pub flac_compression_level: u32,
457 #[cfg(feature = "artemis")]
458 #[default(true)]
459 pub artemis_asb_format_lua: bool,
461 #[cfg(feature = "kirikiri")]
462 pub kirikiri_title: bool,
464 #[cfg(feature = "favorite")]
465 #[default(true)]
466 pub favorite_hcb_filter_ascii: bool,
468 #[cfg(feature = "bgi-img")]
469 #[default(get_default_threads())]
470 pub bgi_img_workers: usize,
473 #[cfg(feature = "image-jxl")]
474 #[default(true)]
475 pub jxl_lossless: bool,
477 #[cfg(feature = "image-jxl")]
478 #[default(1.0)]
479 pub jxl_distance: f32,
482 #[cfg(feature = "image-jxl")]
483 #[default(1)]
484 pub jxl_workers: usize,
487 #[cfg(feature = "emote-img")]
488 #[default(true)]
489 pub psb_process_tlg: bool,
491 #[cfg(feature = "softpal-img")]
492 #[default(true)]
493 pub pgd_fake_compress: bool,
496 #[cfg(feature = "softpal")]
497 pub softpal_add_message_index: bool,
499 #[cfg(feature = "kirikiri")]
500 #[default(true)]
501 pub kirikiri_chat_multilang: bool,
504 #[cfg(feature = "kirikiri-arc")]
505 #[default(true)]
506 pub xp3_simple_crypt: bool,
508 #[cfg(feature = "kirikiri-arc")]
509 #[default(true)]
510 pub xp3_mdf_decompress: bool,
512 #[cfg(feature = "kirikiri-arc")]
513 pub xp3_segmenter: crate::scripts::kirikiri::archive::xp3::SegmenterConfig,
515 #[cfg(feature = "kirikiri-arc")]
516 #[default(true)]
517 pub xp3_compress_files: bool,
519 #[cfg(feature = "kirikiri-arc")]
520 #[default(true)]
521 pub xp3_compress_index: bool,
523 #[cfg(feature = "kirikiri-arc")]
524 #[default(num_cpus::get())]
525 pub xp3_compress_workers: usize,
527 #[cfg(feature = "kirikiri-arc")]
528 pub xp3_zstd: bool,
530 #[cfg(feature = "kirikiri-arc")]
531 pub xp3_zopfli: bool,
533 #[cfg(feature = "kirikiri-arc")]
534 #[default(1)]
535 pub xp3_pack_workers: usize,
538 #[cfg(feature = "kirikiri-arc")]
539 pub xp3_no_adler: bool,
542 #[cfg(feature = "kirikiri")]
543 pub kirikiri_language_insert: bool,
545 #[cfg(feature = "musica-arc")]
546 pub musica_game_title: Option<String>,
548 #[cfg(feature = "musica-arc")]
549 pub musica_xor_key: Option<u8>,
551 #[cfg(feature = "musica-arc")]
552 pub musica_compress: bool,
554 #[cfg(feature = "bgi")]
555 pub bgi_add_space: bool,
558 #[cfg(feature = "escude")]
559 pub escude_op: Option<crate::scripts::escude::script::EscudeOp>,
561 #[cfg(feature = "zopfli")]
562 #[default(std::num::NonZeroU64::new(15).unwrap())]
563 pub zopfli_iteration_count: std::num::NonZeroU64,
567 #[cfg(feature = "zopfli")]
568 #[default(std::num::NonZeroU64::new(u64::MAX).unwrap())]
569 pub zopfli_iterations_without_improvement: std::num::NonZeroU64,
572 #[cfg(feature = "zopfli")]
573 #[default(15)]
574 pub zopfli_maximum_block_splits: u16,
577 #[cfg(feature = "entis-gls")]
578 pub entis_gls_csx_disasm: bool,
580 #[cfg(feature = "entis-gls")]
581 #[default(String::from("/"))]
582 pub entis_gls_csx_lf: String,
584 #[cfg(feature = "entis-gls")]
585 pub entis_gls_csx_ver: Option<crate::scripts::entis_gls::csx::CSXScriptVersion>,
588 #[cfg(feature = "entis-gls")]
589 pub entis_gls_csx_v2_ver: Option<crate::scripts::entis_gls::csx::CSXScriptV2FullVer>,
592 #[cfg(feature = "entis-gls")]
593 pub entis_gls_csx_no_part_label: bool,
595 #[cfg(feature = "qlie-img")]
596 #[default(true)]
597 pub qlie_abmp10_process_abmp10: bool,
599 #[cfg(feature = "qlie-arc")]
600 pub qlie_pack_keyfile: Option<String>,
602 #[cfg(feature = "qlie-arc")]
603 pub qlie_pack_compress_files: bool,
605 #[cfg(feature = "qlie-img")]
606 pub qlie_dpng_use_raw_png: bool,
609 #[cfg(feature = "qlie-img")]
610 pub qlie_dpng_psd: bool,
612 #[cfg(feature = "utils-psd")]
613 #[default(true)]
614 pub psd_compress: bool,
616 #[cfg(feature = "emote-img")]
617 pub emote_pimg_psd: bool,
619 #[cfg(feature = "kirikiri")]
620 pub kirikiri_ks_hitret: Option<bool>,
622 #[cfg(feature = "kirikiri")]
623 pub kirikiri_ks_lf: Option<String>,
625 #[cfg(feature = "kirikiri")]
626 pub kirikiri_message_tags: std::sync::Arc<std::collections::HashSet<String>>,
628 #[cfg(feature = "kirikiri")]
629 pub kirikiri_ks_bom: Option<BomType>,
631 #[cfg(feature = "emote-img")]
632 pub bc7: crate::scripts::emote::psb::BC7Config,
634}
635
636#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
637pub enum ScriptType {
639 #[cfg(feature = "artemis")]
640 Artemis,
642 #[cfg(feature = "artemis")]
643 ArtemisAsb,
645 #[cfg(feature = "artemis")]
646 ArtemisTxt,
648 #[cfg(feature = "artemis-panmimisoft")]
649 ArtemisPanmimisoftTxt,
651 #[cfg(feature = "artemis-arc")]
652 #[value(alias("pfs"))]
653 ArtemisArc,
655 #[cfg(feature = "artemis-arc")]
656 #[value(alias("pf2"))]
657 ArtemisPf2,
659 #[cfg(feature = "bgi")]
660 #[value(alias("ethornell"))]
661 BGI,
663 #[cfg(feature = "bgi")]
664 #[value(alias("ethornell-bsi"))]
665 BGIBsi,
667 #[cfg(feature = "bgi")]
668 #[value(alias("ethornell-bp"))]
669 BGIBp,
671 #[cfg(feature = "bgi-arc")]
672 #[value(alias = "ethornell-arc-v1")]
673 BGIArcV1,
675 #[cfg(feature = "bgi-arc")]
676 #[value(alias = "ethornell-arc-v2", alias = "bgi-arc", alias = "ethornell-arc")]
677 BGIArcV2,
679 #[cfg(feature = "bgi-arc")]
680 #[value(alias("ethornell-dsc"))]
681 BGIDsc,
683 #[cfg(feature = "bgi-audio")]
684 #[value(alias("ethornell-audio"))]
685 BGIAudio,
687 #[cfg(feature = "bgi-img")]
688 #[value(alias("ethornell-img"))]
689 BGIImg,
691 #[cfg(feature = "bgi-img")]
692 #[value(alias("ethornell-cbg"))]
693 BGICbg,
695 #[cfg(feature = "cat-system")]
696 CatSystem,
698 #[cfg(feature = "cat-system")]
699 CatSystemCstl,
701 #[cfg(feature = "cat-system-arc")]
702 CatSystemInt,
704 #[cfg(feature = "cat-system-img")]
705 CatSystemHg3,
707 #[cfg(feature = "circus")]
708 Circus,
710 #[cfg(feature = "circus-arc")]
711 CircusCrm,
713 #[cfg(feature = "circus-arc")]
714 CircusDat,
716 #[cfg(feature = "circus-arc")]
717 CircusPck,
719 #[cfg(feature = "circus-audio")]
720 CircusPcm,
722 #[cfg(feature = "circus-img")]
723 CircusCrx,
725 #[cfg(feature = "circus-img")]
726 CircusCrxd,
728 #[cfg(feature = "emote-img")]
729 #[value(alias("psb"))]
730 EmotePsb,
732 #[cfg(feature = "emote-img")]
733 #[value(alias("pimg"))]
734 EmotePimg,
736 #[cfg(feature = "emote-img")]
737 #[value(alias("dref"))]
738 EmoteDref,
740 #[cfg(feature = "entis-gls")]
741 EntisGls,
743 #[cfg(feature = "entis-gls")]
744 EntisGlsCsx,
746 #[cfg(feature = "escude-arc")]
747 EscudeArc,
749 #[cfg(feature = "escude")]
750 Escude,
752 #[cfg(feature = "escude")]
753 EscudeList,
755 #[cfg(feature = "ex-hibit")]
756 ExHibit,
758 #[cfg(feature = "ex-hibit-arc")]
759 ExHibitGrp,
761 #[cfg(feature = "favorite")]
762 Favorite,
764 #[cfg(feature = "hexen-haus")]
765 HexenHaus,
767 #[cfg(feature = "hexen-haus-arc")]
768 HexenHausArcc,
770 #[cfg(feature = "hexen-haus-arc")]
771 HexenHausOdio,
773 #[cfg(feature = "hexen-haus-arc")]
774 HexenHausWag,
776 #[cfg(feature = "hexen-haus-img")]
777 HexenHausPng,
779 #[cfg(feature = "kirikiri")]
780 #[value(alias("kr-scn"))]
781 KirikiriScn,
783 #[cfg(feature = "kirikiri")]
784 #[value(alias("kr-simple-crypt"))]
785 KirikiriSimpleCrypt,
787 #[cfg(feature = "kirikiri")]
788 #[value(alias = "kr", alias = "kr-ks", alias = "kirikiri-ks")]
789 Kirikiri,
791 #[cfg(feature = "kirikiri-arc")]
792 #[value(alias = "kr-xp3", alias = "xp3")]
793 KirikiriXp3,
795 #[cfg(feature = "kirikiri-img")]
796 #[value(alias("kr-tlg"))]
797 KirikiriTlg,
799 #[cfg(feature = "kirikiri")]
800 #[value(alias("kr-mdf"))]
801 KirikiriMdf,
803 #[cfg(feature = "kirikiri")]
804 #[value(alias("kr-tjs2"))]
805 KirikiriTjs2,
807 #[cfg(feature = "kirikiri")]
808 #[value(alias("kr-tjs-ns0"))]
809 KirikiriTjsNs0,
811 #[cfg(feature = "musica")]
812 Musica,
814 #[cfg(feature = "musica-arc")]
815 MusicaPaz,
817 #[cfg(feature = "qlie")]
818 Qlie,
820 #[cfg(feature = "qlie-arc")]
821 QliePack,
823 #[cfg(feature = "qlie-img")]
824 QlieDpng,
826 #[cfg(feature = "qlie-img")]
827 #[value(alias = "qlie-abmp11", alias = "qlie-abmp12")]
828 QlieAbmp10,
830 #[cfg(feature = "silky")]
831 Silky,
833 #[cfg(feature = "silky")]
834 SilkyMap,
836 #[cfg(feature = "softpal")]
837 Softpal,
839 #[cfg(feature = "softpal-arc")]
840 SoftpalPac,
842 #[cfg(feature = "softpal-arc")]
843 SoftpalPacAmuse,
845 #[cfg(feature = "softpal-img")]
846 #[value(alias = "pgd-ge", alias = "pgd")]
847 SoftpalPgdGe,
849 #[cfg(feature = "softpal-img")]
850 #[value(alias = "softpal-pgd2", alias = "pgd3", alias = "pgd2")]
851 SoftpalPgd3,
853 #[cfg(feature = "will-plus")]
854 #[value(alias("adv-hd-ws2"))]
855 WillPlusWs2,
857 #[cfg(feature = "will-plus-img")]
858 #[value(alias("adv-hd-wip"))]
859 WillPlusWip,
861 #[cfg(feature = "yaneurao-itufuru")]
862 #[value(alias("itufuru"))]
863 YaneuraoItufuru,
865 #[cfg(feature = "yaneurao-itufuru")]
866 #[value(alias("itufuru-arc"))]
867 YaneuraoItufuruArc,
869}
870
871#[derive(Clone, Debug, Serialize, Deserialize)]
872pub struct Message {
874 #[serde(skip_serializing_if = "Option::is_none")]
875 pub name: Option<String>,
877 pub message: String,
879}
880
881impl Message {
882 pub fn new(message: String, name: Option<String>) -> Self {
884 Message { message, name }
885 }
886}
887
888#[derive(Clone, Debug)]
889pub struct ExtendedMessage {
891 pub name: Option<String>,
893 pub source: String,
895 pub translated: String,
897 pub llm: Option<String>,
899}
900
901pub enum ScriptResult {
903 Ok,
905 Ignored,
908 Uncount,
911}
912
913#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
914pub enum FormatType {
916 Fixed,
918 None,
920}
921
922#[derive(Clone)]
923pub enum FormatOptions {
925 Fixed {
927 length: usize,
929 keep_original: bool,
931 break_words: bool,
933 insert_fullwidth_space_at_line_start: bool,
935 break_with_sentence: bool,
937 #[cfg(feature = "jieba")]
938 break_chinese_words: bool,
940 #[cfg(feature = "jieba")]
941 jieba_dict: Option<String>,
943 no_remove_space_at_line_start: bool,
945 },
946 None,
948}
949
950#[derive(Debug, Serialize, Deserialize)]
951pub struct NameTableCell {
953 #[serde(rename = "JP_Name")]
954 pub jp_name: String,
956 #[serde(rename = "CN_Name")]
957 pub cn_name: String,
959 #[serde(rename = "Count")]
960 pub count: usize,
962}
963
964#[derive(Debug, Serialize, Deserialize)]
965pub struct ReplacementTable {
967 #[serde(flatten)]
968 pub map: HashMap<String, String>,
970}
971
972#[cfg(feature = "image")]
973#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
974pub enum ImageColorType {
976 Grayscale,
978 Rgb,
980 Rgba,
982 Bgr,
984 Bgra,
986}
987
988#[cfg(feature = "image")]
989impl ImageColorType {
990 pub fn bpp(&self, depth: u8) -> u16 {
992 match self {
993 ImageColorType::Grayscale => depth as u16,
994 ImageColorType::Rgb => depth as u16 * 3,
995 ImageColorType::Rgba => depth as u16 * 4,
996 ImageColorType::Bgr => depth as u16 * 3,
997 ImageColorType::Bgra => depth as u16 * 4,
998 }
999 }
1000}
1001
1002#[cfg(feature = "image")]
1003#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
1004pub enum ImageOutputType {
1006 Png,
1008 #[cfg(feature = "image-jpg")]
1009 Jpg,
1011 #[cfg(feature = "image-webp")]
1012 Webp,
1014 #[cfg(feature = "image-jxl")]
1015 Jxl,
1017}
1018
1019#[cfg(feature = "image")]
1020impl TryFrom<&str> for ImageOutputType {
1021 type Error = anyhow::Error;
1022
1023 fn try_from(value: &str) -> Result<Self, Self::Error> {
1026 match value.to_ascii_lowercase().as_str() {
1027 "png" => Ok(ImageOutputType::Png),
1028 #[cfg(feature = "image-jpg")]
1029 "jpg" => Ok(ImageOutputType::Jpg),
1030 #[cfg(feature = "image-jpg")]
1031 "jpeg" => Ok(ImageOutputType::Jpg),
1032 #[cfg(feature = "image-webp")]
1033 "webp" => Ok(ImageOutputType::Webp),
1034 #[cfg(feature = "image-jxl")]
1035 "jxl" => Ok(ImageOutputType::Jxl),
1036 _ => Err(anyhow::anyhow!("Unsupported image output type: {}", value)),
1037 }
1038 }
1039}
1040
1041#[cfg(feature = "image")]
1042impl TryFrom<&std::path::Path> for ImageOutputType {
1043 type Error = anyhow::Error;
1044
1045 fn try_from(value: &std::path::Path) -> Result<Self, Self::Error> {
1046 if let Some(ext) = value.extension() {
1047 Self::try_from(ext.to_string_lossy().as_ref())
1048 } else {
1049 Err(anyhow::anyhow!("No extension found in path"))
1050 }
1051 }
1052}
1053
1054#[cfg(feature = "image")]
1055impl AsRef<str> for ImageOutputType {
1056 fn as_ref(&self) -> &str {
1058 match self {
1059 ImageOutputType::Png => "png",
1060 #[cfg(feature = "image-jpg")]
1061 ImageOutputType::Jpg => "jpg",
1062 #[cfg(feature = "image-webp")]
1063 ImageOutputType::Webp => "webp",
1064 #[cfg(feature = "image-jxl")]
1065 ImageOutputType::Jxl => "jxl",
1066 }
1067 }
1068}
1069
1070#[cfg(feature = "image")]
1071#[derive(Clone, Debug)]
1072pub struct ImageData {
1074 pub width: u32,
1076 pub height: u32,
1078 pub color_type: ImageColorType,
1080 pub depth: u8,
1082 pub data: Vec<u8>,
1084}
1085
1086#[cfg(feature = "image")]
1087#[derive(Clone, Debug)]
1088pub struct ImageDataWithName {
1090 pub name: String,
1092 pub data: ImageData,
1094}
1095
1096#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
1097pub enum BomType {
1099 None,
1101 Utf8,
1103 Utf16LE,
1105 Utf16BE,
1107}
1108
1109impl BomType {
1110 pub fn as_bytes(&self) -> &'static [u8] {
1112 match self {
1113 BomType::None => &[],
1114 BomType::Utf8 => b"\xEF\xBB\xBF",
1115 BomType::Utf16LE => b"\xFF\xFE",
1116 BomType::Utf16BE => b"\xFE\xFF",
1117 }
1118 }
1119}
1120
1121#[cfg(feature = "image")]
1122#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
1123pub enum PngCompressionLevel {
1125 #[value(alias = "n")]
1126 NoCompression,
1128 #[value(alias = "d")]
1129 Default,
1131 Fastest,
1137 #[value(alias = "f")]
1138 Fast,
1140 #[value(alias = "b")]
1141 Best,
1143 #[value(alias = "h")]
1144 High,
1146}
1147
1148#[cfg(feature = "image")]
1149impl Default for PngCompressionLevel {
1150 fn default() -> Self {
1151 PngCompressionLevel::Default
1152 }
1153}
1154
1155#[cfg(feature = "image")]
1156impl PngCompressionLevel {
1157 pub fn to_compression(&self) -> png::Compression {
1159 match self {
1160 PngCompressionLevel::NoCompression => png::Compression::NoCompression,
1161 PngCompressionLevel::Fastest => png::Compression::Fastest,
1162 PngCompressionLevel::Default => png::Compression::Balanced,
1163 PngCompressionLevel::Fast => png::Compression::Fast,
1164 PngCompressionLevel::Best => png::Compression::High,
1165 PngCompressionLevel::High => png::Compression::High,
1166 }
1167 }
1168}
1169
1170#[cfg(feature = "lossless-audio")]
1171#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
1172pub enum LosslessAudioFormat {
1174 Wav,
1176 #[cfg(feature = "audio-flac")]
1177 Flac,
1179}
1180
1181#[cfg(feature = "lossless-audio")]
1182impl Default for LosslessAudioFormat {
1183 fn default() -> Self {
1184 LosslessAudioFormat::Wav
1185 }
1186}
1187
1188#[cfg(feature = "lossless-audio")]
1189impl TryFrom<&str> for LosslessAudioFormat {
1190 type Error = anyhow::Error;
1191 fn try_from(value: &str) -> Result<Self, Self::Error> {
1194 match value.to_ascii_lowercase().as_str() {
1195 "wav" => Ok(LosslessAudioFormat::Wav),
1196 #[cfg(feature = "audio-flac")]
1197 "flac" => Ok(LosslessAudioFormat::Flac),
1198 _ => Err(anyhow::anyhow!(
1199 "Unsupported lossless audio format: {}",
1200 value
1201 )),
1202 }
1203 }
1204}
1205
1206#[cfg(feature = "lossless-audio")]
1207impl TryFrom<&std::path::Path> for LosslessAudioFormat {
1208 type Error = anyhow::Error;
1209
1210 fn try_from(value: &std::path::Path) -> Result<Self, Self::Error> {
1211 if let Some(ext) = value.extension() {
1212 Self::try_from(ext.to_string_lossy().as_ref())
1213 } else {
1214 Err(anyhow::anyhow!("No extension found in path"))
1215 }
1216 }
1217}
1218
1219#[cfg(feature = "lossless-audio")]
1220impl AsRef<str> for LosslessAudioFormat {
1221 fn as_ref(&self) -> &str {
1223 match self {
1224 LosslessAudioFormat::Wav => "wav",
1225 #[cfg(feature = "audio-flac")]
1226 LosslessAudioFormat::Flac => "flac",
1227 }
1228 }
1229}
1230
1231#[allow(unused)]
1232pub(crate) fn get_default_threads() -> usize {
1233 num_cpus::get().max(2) / 2
1234}