msg_tool\scripts\artemis\ast/
mod.rs1mod dump;
3mod parser;
4mod text;
5mod types;
6
7use crate::scripts::base::*;
8use crate::types::*;
9use crate::utils::encoding::*;
10use anyhow::Result;
11use std::io::Write;
12
13pub use dump::Dumper;
14pub use parser::Parser;
15pub use types::*;
16
17#[derive(Debug)]
18pub struct AstScriptBuilder {}
20
21impl AstScriptBuilder {
22 pub fn new() -> Self {
24 AstScriptBuilder {}
25 }
26}
27
28impl ScriptBuilder for AstScriptBuilder {
29 fn default_encoding(&self) -> Encoding {
30 Encoding::Utf8
31 }
32
33 fn build_script(
34 &self,
35 buf: Vec<u8>,
36 _filename: &str,
37 encoding: Encoding,
38 _archive_encoding: Encoding,
39 config: &ExtraConfig,
40 _archive: Option<&Box<dyn Script>>,
41 ) -> Result<Box<dyn Script>> {
42 Ok(Box::new(AstScript::new(buf, encoding, config)?))
43 }
44
45 fn extensions(&self) -> &'static [&'static str] {
46 &["ast"]
47 }
48
49 fn script_type(&self) -> &'static ScriptType {
50 &ScriptType::Artemis
51 }
52
53 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
54 let parser = parser::Parser::new(&buf[..buf_len], Encoding::Utf8);
55 if parser.try_parse_header().is_ok() {
56 Some(15)
57 } else {
58 None
59 }
60 }
61}
62
63#[derive(Debug)]
64pub struct AstScript {
66 ast: AstFile,
67 indent: Option<usize>,
68 max_line_width: usize,
69 no_indent: bool,
70 lang: Option<String>,
71}
72
73impl AstScript {
74 pub fn new(buf: Vec<u8>, encoding: Encoding, config: &ExtraConfig) -> Result<Self> {
80 let parser = parser::Parser::new(&buf, encoding);
81 let ast = parser.parse()?;
82 Ok(AstScript {
83 ast,
84 indent: config.artemis_indent,
85 max_line_width: config.artemis_max_line_width,
86 no_indent: config.artemis_no_indent,
87 lang: config.artemis_ast_lang.clone(),
88 })
89 }
90}
91
92impl Script for AstScript {
93 fn default_output_script_type(&self) -> OutputScriptType {
94 OutputScriptType::Json
95 }
96
97 fn default_format_type(&self) -> FormatOptions {
98 FormatOptions::None
99 }
100
101 fn extract_messages(&self) -> Result<Vec<Message>> {
102 let mut messages = Vec::new();
103 let ast = &self.ast.ast;
104 let mut lang: Option<&str> = self.lang.as_ref().map(|s| s.as_str());
105 if ast["label"]["top"]["block"].is_null() && ast["text"].is_array() {
107 let text = &ast["text"];
108 let mut text_index = 1i64;
109 for block in ast.members() {
110 if block.is_array() {
111 let savetitle = &block[Key("savetitle")];
112 if savetitle.is_array() {
113 if let Some(lang) = lang {
114 if let Some(title) = savetitle[lang].as_str() {
115 messages.push(Message {
116 name: None,
117 message: title.to_string(),
118 });
119 } else if let Some(title) = savetitle["text"].as_str() {
120 messages.push(Message {
121 name: None,
122 message: title.to_string(),
123 });
124 }
125 } else if let Some(title) = savetitle["text"].as_str() {
126 messages.push(Message {
127 name: None,
128 message: title.to_string(),
129 });
130 }
131 }
132 if !block[Key("text")].is_null() {
133 let tex = &text[NumKey(text_index)];
134 text_index += 1;
135 if tex.is_array() {
136 let lan = match lang {
137 Some(l) => l,
138 None => {
139 for l in tex.kv_keys() {
140 if l.is_str() && l != "vo" && l != "name" {
141 lang = l.as_str();
142 break;
143 }
144 }
145 match lang {
146 Some(l) => l,
147 None => continue,
149 }
150 }
151 };
152 let mut te = &tex[lan];
153 if te.is_null() {
154 for l in tex.kv_keys() {
155 if l != "vo" && l != "name" {
156 te = &tex[l];
157 break;
158 }
159 }
160 }
161 let name = &tex["name"];
162 let nam = if name.is_array() {
163 if let Some(lang) = lang {
164 if let Some(n) = name[lang].as_string() {
165 Some(n)
166 } else if let Some(n) = name["name"].as_string() {
167 Some(n)
168 } else {
169 None
170 }
171 } else if let Some(n) = name["name"].as_string() {
172 Some(n)
173 } else {
174 None
175 }
176 } else {
177 None
178 };
179 for item in te.members() {
180 let message = text::TextGenerator::new().generate(item)?;
181 messages.push(Message {
182 name: nam.clone(),
183 message: message.replace("<rt2>", "\n").replace("<ret2>", "\n"),
184 });
185 }
186 }
187 } else if !block[Key("select")].is_null() {
188 let tex = &text[NumKey(text_index)]["select"];
189 text_index += 1;
190 if tex.is_array() {
191 let lan = match lang {
192 Some(l) => l,
193 None => {
194 for l in tex.kv_keys() {
195 if l.is_str() && l != "vo" && l != "name" {
196 lang = l.as_str();
197 break;
198 }
199 }
200 match lang {
201 Some(l) => l,
202 None => continue,
204 }
205 }
206 };
207 let mut te = &tex[lan];
208 if te.is_null() {
209 for l in tex.kv_keys() {
210 if l != "vo" && l != "name" {
211 te = &tex[l];
212 break;
213 }
214 }
215 }
216 for item in te.members() {
217 if let Some(select) = item.as_str() {
218 messages.push(Message {
219 name: None,
220 message: select.to_string(),
221 });
222 }
223 }
224 }
225 }
226 }
227 }
228 return Ok(messages);
229 }
230 let mut block_name = ast["label"]["top"]["block"]
231 .as_str()
232 .ok_or(anyhow::anyhow!("Missing top block name"))?;
233 let mut block = &ast[block_name];
234 loop {
235 let savetitle = &block[Key("savetitle")];
236 if savetitle.is_array() {
237 if let Some(lang) = lang {
238 if let Some(title) = savetitle[lang].as_str() {
239 messages.push(Message {
240 name: None,
241 message: title.to_string(),
242 });
243 } else if let Some(title) = savetitle["text"].as_str() {
244 messages.push(Message {
245 name: None,
246 message: title.to_string(),
247 });
248 }
249 } else if let Some(title) = savetitle["text"].as_str() {
250 messages.push(Message {
251 name: None,
252 message: title.to_string(),
253 });
254 }
255 }
256 let text = &block["text"];
257 if text.is_array() {
258 let lan = match lang {
259 Some(l) => l,
260 None => {
261 for l in text.kv_keys() {
262 if l.is_str() && l != "vo" {
263 lang = l.as_str();
264 break;
265 }
266 }
267 match lang {
268 Some(l) => l,
269 None => {
271 block_name = match block["linknext"].as_str() {
272 Some(name) => name,
273 None => break,
274 };
275 block = &ast[block_name];
276 continue;
277 }
278 }
279 }
280 };
281 let mut tex = &text[lan];
282 if tex.is_null() {
283 for l in text.kv_keys() {
284 if l != "vo" {
285 tex = &text[l];
286 break;
287 }
288 }
289 }
290 for item in tex.members() {
291 let name = item["name"].last_member().as_string();
292 let message = text::TextGenerator::new().generate(item)?;
293 messages.push(Message {
294 name: name,
295 message: message
296 .replace("<rt2>", "\n")
297 .replace("<ret2>", "\n")
298 .trim_end_matches("\n")
299 .to_string(),
300 });
301 }
302 }
303 let select = &block["select"];
304 if select.is_array() {
305 let lan = match lang {
306 Some(l) => l,
307 None => {
308 for l in select.kv_keys() {
309 if l.is_str() && l != "vo" {
310 lang = l.as_str();
311 break;
312 }
313 }
314 match lang {
315 Some(l) => l,
316 None => {
318 block_name = match block["linknext"].as_str() {
319 Some(name) => name,
320 None => break,
321 };
322 block = &ast[block_name];
323 continue;
324 }
325 }
326 }
327 };
328 let mut select_text = &select[lan];
329 if select_text.is_null() {
330 for l in select.kv_keys() {
331 if l != "vo" {
332 select_text = &select[l];
333 break;
334 }
335 }
336 }
337 for item in select_text.members() {
338 if let Some(select) = item.as_str() {
339 messages.push(Message {
340 name: None,
341 message: select.to_string(),
342 });
343 }
344 }
345 }
346 block_name = match block["linknext"].as_str() {
347 Some(name) => name,
348 None => break,
349 };
350 block = &ast[block_name];
351 }
352 Ok(messages)
353 }
354
355 fn import_messages<'a>(
356 &'a self,
357 messages: Vec<Message>,
358 mut file: Box<dyn WriteSeek + 'a>,
359 _filename: &str,
360 encoding: Encoding,
361 replacement: Option<&'a ReplacementTable>,
362 ) -> Result<()> {
363 let mut ast = self.ast.clone();
364 let root = &mut ast.ast;
365 let mut lang = self.lang.as_ref().map(|s| s.to_string());
366 let mut mess = messages.iter();
367 let mut mes = mess.next();
368 if root["label"]["top"]["block"].is_null() && root["text"].is_array() {
369 let mut text_index = 1i64;
370 let len = root.len();
371 for i in 0..len {
372 if root[i].is_array() {
373 if root[i][Key("savetitle")].is_array() {
374 let lan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("text");
375 let m = match mes {
376 Some(m) => m,
377 None => return Err(anyhow::anyhow!("Not enough messages.")),
378 };
379 let mut title = m.message.clone();
380 if let Some(repl) = replacement {
381 for (k, v) in &repl.map {
382 title = title.replace(k, v);
383 }
384 }
385 root[i][Key("savetitle")][lan].set_string(title);
386 mes = mess.next();
387 }
388 }
389 if !root[i][Key("text")].is_null() {
390 let lan = match &lang {
391 Some(l) => l.as_str(),
392 None => {
393 for l in root["text"][NumKey(text_index)].kv_keys() {
394 if l.is_str() && l != "vo" && l != "name" {
395 lang = l.as_string();
396 break;
397 }
398 }
399 match lang {
400 Some(ref l) => l.as_str(),
401 None => continue,
403 }
404 }
405 };
406 if root["text"][NumKey(text_index)]["name"].is_array() {
407 let name = match mes {
408 Some(m) => m.name.clone(),
409 None => return Err(anyhow::anyhow!("Message name is missing.")),
410 };
411 let mut name = match name {
412 Some(n) => n,
413 None => return Err(anyhow::anyhow!("Message name is missing.")),
414 };
415 if let Some(repl) = replacement {
416 for (k, v) in &repl.map {
417 name = name.replace(k, v);
418 }
419 }
420 let nlan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("name");
421 root["text"][NumKey(text_index)]["name"][nlan].set_string(name);
422 }
423 let origin_count = {
424 let text = &root["text"][NumKey(text_index)];
425 let mut tex = &text[lan];
426 if tex.is_null() {
427 for l in text.kv_keys() {
428 if l != "vo" && l != "name" {
429 tex = &text[l];
430 break;
431 }
432 }
433 }
434 tex.len()
435 };
436 let mut arr = Value::new_array();
437 for _ in 0..origin_count {
438 let m = match mes {
439 Some(m) => m,
440 None => return Err(anyhow::anyhow!("Not enough messages.")),
441 };
442 let mut text = m.message.clone();
443 if let Some(repl) = replacement {
444 for (k, v) in &repl.map {
445 text = text.replace(k, v);
446 }
447 }
448 let v = text::TextParser::new(&text.replace("\n", "<rt2>")).parse()?;
449 arr.push_member(v);
450 mes = mess.next();
451 }
452 root["text"][NumKey(text_index)][lan] = arr;
453 text_index += 1;
454 } else if !root[i][Key("select")].is_null() {
455 let lan = match &lang {
456 Some(l) => l.as_str(),
457 None => {
458 for l in root["text"][NumKey(text_index)]["select"].kv_keys() {
459 if l.is_str() && l != "vo" && l != "name" {
460 lang = l.as_string();
461 break;
462 }
463 }
464 match lang {
465 Some(ref l) => l.as_str(),
466 None => continue,
468 }
469 }
470 };
471 let count = {
472 let text = &root["text"][NumKey(text_index)]["select"];
473 let mut tex = &text[lan];
474 if tex.is_null() {
475 for l in text.kv_keys() {
476 if l != "vo" && l != "name" {
477 tex = &text[l];
478 break;
479 }
480 }
481 }
482 tex.len()
483 };
484 let mut new_select = Value::new_array();
485 for _ in 0..count {
486 let m = match mes {
487 Some(m) => m,
488 None => return Err(anyhow::anyhow!("Not enough messages.")),
489 };
490 let mut select_text = m.message.clone();
491 if let Some(repl) = replacement {
492 for (k, v) in &repl.map {
493 select_text = select_text.replace(k, v);
494 }
495 }
496 new_select.push_member(Value::Str(select_text));
497 mes = mess.next();
498 }
499 root["text"][NumKey(text_index)]["select"][lan] = new_select;
500 text_index += 1;
501 }
502 }
503 if mes.is_some() || mess.next().is_some() {
504 return Err(anyhow::anyhow!("Not all messages were used."));
505 }
506 let mut writer = Vec::new();
507 let mut dumper = dump::Dumper::new(&mut writer);
508 if self.no_indent {
509 dumper.set_no_indent();
510 } else if let Some(indent) = self.indent {
511 dumper.set_indent(indent);
512 }
513 dumper.set_max_line_width(self.max_line_width);
514 dumper.dump(&ast)?;
515 let data = String::from_utf8(writer)?;
516 let encoded = encode_string(encoding, &data, false)?;
517 file.write_all(&encoded)?;
518 file.flush()?;
519 return Ok(());
520 }
521 let mut block_name = root["label"]["top"]["block"]
522 .as_string()
523 .ok_or(anyhow::anyhow!("Missing top block name"))?;
524 let mut block = &mut root[block_name];
525 loop {
526 if block[Key("savetitle")].is_array() {
527 let lan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("text");
528 let m = match mes {
529 Some(m) => m,
530 None => return Err(anyhow::anyhow!("Not enough messages.")),
531 };
532 let mut title = m.message.clone();
533 if let Some(repl) = replacement {
534 for (k, v) in &repl.map {
535 title = title.replace(k, v);
536 }
537 }
538 block[Key("savetitle")][lan].set_string(title);
539 mes = mess.next();
540 }
541 if block["text"].is_array() {
542 let lan = match &lang {
543 Some(l) => l.as_str(),
544 None => {
545 for l in block["text"].kv_keys() {
546 if l.is_str() && l != "vo" {
547 lang = l.as_string();
548 break;
549 }
550 }
551 match lang {
552 Some(ref l) => l.as_str(),
553 None => {
555 block_name = match block["linknext"].as_string() {
556 Some(name) => name,
557 None => break,
558 };
559 block = &mut root[block_name];
560 continue;
561 }
562 }
563 }
564 };
565 let origin_names: Vec<_> = {
566 let mut tex = &block["text"][lan];
567 if tex.is_null() {
568 for l in block["text"].kv_keys() {
569 if l != "vo" {
570 tex = &block["text"][l];
571 break;
572 }
573 }
574 }
575 tex.members().map(|m| m["name"].clone()).collect()
576 };
577 let mut arr = Value::new_array();
578 for name in origin_names {
579 let m = match mes {
580 Some(m) => m,
581 None => return Err(anyhow::anyhow!("Not enough messages.")),
582 };
583 let mut text = m.message.clone();
584 if let Some(repl) = replacement {
585 for (k, v) in &repl.map {
586 text = text.replace(k, v);
587 }
588 }
589 if !text.ends_with("\n") {
590 text.push('\n');
591 }
592 let mut v = text::TextParser::new(&text.replace("\n", "<rt2>")).parse()?;
593 if name.is_array() {
594 let mut n = match &m.name {
595 Some(n) => n.to_string(),
596 None => return Err(anyhow::anyhow!("Message name is missing.")),
597 };
598 if let Some(repl) = replacement {
599 for (k, v) in &repl.map {
600 n = n.replace(k, v);
601 }
602 }
603 v.insert_member(0, Value::new_kv("name", name));
604 if v["name"].len() <= 1 {
605 if v["name"][0] != n {
606 v["name"].push_member(Value::Str(n));
607 }
608 } else {
609 v["name"].last_member_mut().set_string(n);
610 }
611 }
612 arr.push_member(v);
613 mes = mess.next();
614 }
615 block["text"][lan] = arr;
616 }
617 if block["select"].is_array() {
618 let lan = match &lang {
619 Some(l) => l.as_str(),
620 None => {
621 for l in block["select"].kv_keys() {
622 if l.is_str() && l != "vo" {
623 lang = l.as_string();
624 break;
625 }
626 }
627 match lang {
628 Some(ref l) => l.as_str(),
629 None => {
631 block_name = match block["linknext"].as_string() {
632 Some(name) => name,
633 None => break,
634 };
635 block = &mut root[block_name];
636 continue;
637 }
638 }
639 }
640 };
641 let select_count = {
642 let mut select = &block["select"][lan];
643 if select.is_null() {
644 for l in block["select"].kv_keys() {
645 if l != "vo" {
646 select = &block["select"][l];
647 break;
648 }
649 }
650 }
651 select.len()
652 };
653 let mut new_select = Value::new_array();
654 for _ in 0..select_count {
655 let m = match mes {
656 Some(m) => m,
657 None => return Err(anyhow::anyhow!("Not enough messages.")),
658 };
659 let mut select_text = m.message.clone();
660 if let Some(repl) = replacement {
661 for (k, v) in &repl.map {
662 select_text = select_text.replace(k, v);
663 }
664 }
665 new_select.push_member(Value::Str(select_text));
666 mes = mess.next();
667 }
668 block["select"][lan] = new_select;
669 }
670 block_name = match block["linknext"].as_string() {
671 Some(name) => name,
672 None => break,
673 };
674 block = &mut root[block_name];
675 }
676 if mes.is_some() || mess.next().is_some() {
677 return Err(anyhow::anyhow!("Not all messages were used."));
678 }
679 let mut writer = Vec::new();
680 let mut dumper = dump::Dumper::new(&mut writer);
681 if self.no_indent {
682 dumper.set_no_indent();
683 } else if let Some(indent) = self.indent {
684 dumper.set_indent(indent);
685 }
686 dumper.set_max_line_width(self.max_line_width);
687 dumper.dump(&ast)?;
688 let data = String::from_utf8(writer)?;
689 let encoded = encode_string(encoding, &data, false)?;
690 file.write_all(&encoded)?;
691 file.flush()?;
692 Ok(())
693 }
694}
695
696pub fn is_this_format(_filename: &str, buf: &[u8], buf_len: usize) -> bool {
702 let parser = parser::Parser::new(&buf[..buf_len], Encoding::Utf8);
703 parser.try_parse_header().is_ok()
704}