mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-07 21:38:58 +08:00
Fix lua parse/dump bug
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use super::types::*;
|
||||
use crate::utils::escape::*;
|
||||
use std::io::Write;
|
||||
|
||||
struct LenChecker {
|
||||
@@ -24,9 +25,21 @@ impl LenChecker {
|
||||
}
|
||||
}
|
||||
Value::Int(i) => self.current_len += format!("{}", i).len(),
|
||||
Value::Str(s) => self.current_len += s.len() + 2,
|
||||
Value::Str(s) => {
|
||||
self.current_len += s.len()
|
||||
+ if lua_str_contains_need_escape(s) {
|
||||
4
|
||||
} else {
|
||||
2
|
||||
}
|
||||
}
|
||||
Value::KeyVal((k, v)) => {
|
||||
self.current_len += k.as_bytes().len() + 3;
|
||||
self.current_len += k.as_bytes().len()
|
||||
+ if lua_key_contains_need_escape(k) {
|
||||
7
|
||||
} else {
|
||||
3
|
||||
};
|
||||
if !self.check(v) {
|
||||
return false;
|
||||
}
|
||||
@@ -96,19 +109,35 @@ impl<'a> Dumper<'a> {
|
||||
self.writer.write(b"astver=")?;
|
||||
self.dump_f64(&ast.astver)?;
|
||||
if let Some(astname) = &ast.astname {
|
||||
self.writer.write(b"\nastname = \"")?;
|
||||
self.writer.write(astname.as_bytes())?;
|
||||
self.writer.write(b"\nastname = ")?;
|
||||
if lua_str_contains_need_escape(astname) {
|
||||
self.writer.write(b"[[")?;
|
||||
self.writer.write(astname.as_bytes())?;
|
||||
self.writer.write(b"]]")?;
|
||||
} else {
|
||||
self.writer.write(b"\"")?;
|
||||
self.writer.write(astname.as_bytes())?;
|
||||
self.writer.write(b"\"")?;
|
||||
}
|
||||
};
|
||||
self.writer.write(b"\"\nast=")?;
|
||||
self.writer.write(b"\nast=")?;
|
||||
self.dump_value(&ast.ast)?;
|
||||
} else {
|
||||
self.writer.write(b"astver = ")?;
|
||||
self.dump_f64(&ast.astver)?;
|
||||
if let Some(astname) = &ast.astname {
|
||||
self.writer.write(b"\nastname = \"")?;
|
||||
self.writer.write(astname.as_bytes())?;
|
||||
self.writer.write(b"\nastname = ")?;
|
||||
if lua_str_contains_need_escape(&astname) {
|
||||
self.writer.write(b"[[")?;
|
||||
self.writer.write(astname.as_bytes())?;
|
||||
self.writer.write(b"]]")?;
|
||||
} else {
|
||||
self.writer.write(b"\"")?;
|
||||
self.writer.write(astname.as_bytes())?;
|
||||
self.writer.write(b"\"")?;
|
||||
}
|
||||
};
|
||||
self.writer.write(b"\"\nast = ")?;
|
||||
self.writer.write(b"\nast = ")?;
|
||||
self.current_line_width = 6;
|
||||
self.dump_value(&ast.ast)?;
|
||||
}
|
||||
@@ -122,13 +151,25 @@ impl<'a> Dumper<'a> {
|
||||
Value::Float(f) => self.dump_f64(f)?,
|
||||
Value::Int(i) => write!(self.writer, "{}", i)?,
|
||||
Value::Str(s) => {
|
||||
self.writer.write(b"\"")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"\"")?;
|
||||
if lua_str_contains_need_escape(s) {
|
||||
self.writer.write(b"[[")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"]]")?;
|
||||
} else {
|
||||
self.writer.write(b"\"")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"\"")?;
|
||||
}
|
||||
}
|
||||
Value::KeyVal((k, v)) => {
|
||||
self.writer.write(k.as_bytes())?;
|
||||
self.writer.write(b"=")?;
|
||||
if lua_key_contains_need_escape(k) {
|
||||
self.writer.write(b"[\"")?;
|
||||
self.writer.write(k.as_bytes())?;
|
||||
self.writer.write(b"\"]=")?;
|
||||
} else {
|
||||
self.writer.write(k.as_bytes())?;
|
||||
self.writer.write(b"=")?;
|
||||
}
|
||||
self.dump_value(v)?;
|
||||
}
|
||||
Value::Array(arr) => {
|
||||
@@ -150,15 +191,28 @@ impl<'a> Dumper<'a> {
|
||||
Value::Float(f) => self.dump_f64(f)?,
|
||||
Value::Int(i) => write!(self.writer, "{}", i)?,
|
||||
Value::Str(s) => {
|
||||
self.writer.write(b"\"")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"\"")?;
|
||||
if lua_str_contains_need_escape(s) {
|
||||
self.writer.write(b"[[")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"]]")?;
|
||||
} else {
|
||||
self.writer.write(b"\"")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"\"")?;
|
||||
}
|
||||
}
|
||||
Value::KeyVal((k, v)) => {
|
||||
let bytes = k.as_bytes();
|
||||
self.writer.write(bytes)?;
|
||||
self.writer.write(b" = ")?;
|
||||
self.current_line_width += bytes.len() + 3;
|
||||
if lua_key_contains_need_escape(k) {
|
||||
self.writer.write(b"[\"")?;
|
||||
self.writer.write(bytes)?;
|
||||
self.writer.write(b"\"] = ")?;
|
||||
self.current_line_width += bytes.len() + 7;
|
||||
} else {
|
||||
self.writer.write(bytes)?;
|
||||
self.writer.write(b" = ")?;
|
||||
self.current_line_width += bytes.len() + 3;
|
||||
}
|
||||
if v.is_array() {
|
||||
let tlen = self.current_line_width + self.current_indent;
|
||||
if tlen < self.max_line_width {
|
||||
@@ -215,14 +269,25 @@ impl<'a> Dumper<'a> {
|
||||
Value::Float(f) => self.dump_f64(f)?,
|
||||
Value::Int(i) => write!(self.writer, "{}", i)?,
|
||||
Value::Str(s) => {
|
||||
self.writer.write(b"\"")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"\"")?;
|
||||
if lua_str_contains_need_escape(s) {
|
||||
self.writer.write(b"[[")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"]]")?;
|
||||
} else {
|
||||
self.writer.write(b"\"")?;
|
||||
self.writer.write(s.as_bytes())?;
|
||||
self.writer.write(b"\"")?;
|
||||
}
|
||||
}
|
||||
Value::KeyVal((k, v)) => {
|
||||
let bytes = k.as_bytes();
|
||||
self.writer.write(bytes)?;
|
||||
self.writer.write(b"=")?;
|
||||
if lua_key_contains_need_escape(k) {
|
||||
self.writer.write(b"[\"")?;
|
||||
self.writer.write(k.as_bytes())?;
|
||||
self.writer.write(b"\"]=")?;
|
||||
} else {
|
||||
self.writer.write(k.as_bytes())?;
|
||||
self.writer.write(b"=")?;
|
||||
}
|
||||
self.dump_value_in_one(v)?;
|
||||
}
|
||||
Value::Array(arr) => {
|
||||
|
||||
@@ -50,6 +50,7 @@ pub struct AstScript {
|
||||
indent: Option<usize>,
|
||||
max_line_width: usize,
|
||||
no_indent: bool,
|
||||
lang: Option<String>,
|
||||
}
|
||||
|
||||
impl AstScript {
|
||||
@@ -61,6 +62,7 @@ impl AstScript {
|
||||
indent: config.artemis_indent,
|
||||
max_line_width: config.artemis_max_line_width,
|
||||
no_indent: config.artemis_no_indent,
|
||||
lang: config.artemis_ast_lang.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -81,13 +83,28 @@ impl Script for AstScript {
|
||||
.as_str()
|
||||
.ok_or(anyhow::anyhow!("Missing top block name"))?;
|
||||
let mut block = &ast[block_name];
|
||||
let mut lang = None;
|
||||
let mut lang: Option<&str> = self.lang.as_ref().map(|s| s.as_str());
|
||||
loop {
|
||||
if let Some(save_title) = block[Key("savetitle")]["text"].as_str() {
|
||||
messages.push(Message {
|
||||
name: None,
|
||||
message: save_title.to_string(),
|
||||
});
|
||||
let savetitle = &block[Key("savetitle")];
|
||||
if savetitle.is_array() {
|
||||
if let Some(lang) = lang {
|
||||
if let Some(title) = savetitle[lang].as_str() {
|
||||
messages.push(Message {
|
||||
name: None,
|
||||
message: title.to_string(),
|
||||
});
|
||||
} else if let Some(title) = savetitle["text"].as_str() {
|
||||
messages.push(Message {
|
||||
name: None,
|
||||
message: title.to_string(),
|
||||
});
|
||||
}
|
||||
} else if let Some(title) = savetitle["text"].as_str() {
|
||||
messages.push(Message {
|
||||
name: None,
|
||||
message: title.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
let text = &block["text"];
|
||||
if text.is_array() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::types::*;
|
||||
use crate::types::*;
|
||||
use crate::utils::encoding::*;
|
||||
use crate::utils::escape::unescape_lua_str;
|
||||
use anyhow::Result;
|
||||
|
||||
pub struct Parser<'a> {
|
||||
@@ -61,6 +62,19 @@ impl<'a> Parser<'a> {
|
||||
match self.peek() {
|
||||
Some(t) => match t {
|
||||
b'"' => return self.parse_str().map(|x| Value::Str(x.to_string())),
|
||||
b'[' => {
|
||||
self.eat_char();
|
||||
match self.peek().ok_or(self.error2("unexpected eof"))? {
|
||||
b'[' => {
|
||||
self.pos -= 1; // Rewind to the first '['
|
||||
self.parse_raw_str().map(|x| Value::Str(x))
|
||||
}
|
||||
_ => {
|
||||
self.pos -= 1;
|
||||
self.parse_key_val()
|
||||
}
|
||||
}
|
||||
}
|
||||
b'-' | b'.' | b'0'..=b'9' => return self.parse_any_number(),
|
||||
b'n' => {
|
||||
if self.is_indent(b"nil") {
|
||||
@@ -70,7 +84,7 @@ impl<'a> Parser<'a> {
|
||||
self.parse_key_val()
|
||||
}
|
||||
}
|
||||
b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'[' | b']' => return self.parse_key_val(),
|
||||
b'_' | b'a'..=b'z' | b'A'..=b'Z' | b']' => return self.parse_key_val(),
|
||||
b'{' => return self.parse_array(),
|
||||
_ => return self.error(format!("unexpected token: {}", t)),
|
||||
},
|
||||
@@ -146,12 +160,40 @@ impl<'a> Parser<'a> {
|
||||
self.erase_whitespace();
|
||||
self.parse_indent(b"\"")?;
|
||||
let start = self.pos;
|
||||
let mut pc = None;
|
||||
let end = loop {
|
||||
match self.next() {
|
||||
Some(c) => {
|
||||
if c == b'"' {
|
||||
break self.pos - 1;
|
||||
if pc.is_none_or(|x| x != b'\\') {
|
||||
break self.pos - 1;
|
||||
}
|
||||
}
|
||||
pc = Some(c);
|
||||
}
|
||||
None => return self.error("unexpected eof"),
|
||||
}
|
||||
};
|
||||
Ok(unescape_lua_str(
|
||||
&decode_to_string(self.encoding, &self.str[start..end], true)
|
||||
.map_err(|e| self.error2(e))?,
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_raw_str(&mut self) -> Result<String> {
|
||||
self.erase_whitespace();
|
||||
self.parse_indent(b"[[")?;
|
||||
let start = self.pos;
|
||||
let mut pc = None;
|
||||
let end = loop {
|
||||
match self.next() {
|
||||
Some(c) => {
|
||||
if c == b']' {
|
||||
if pc.is_some_and(|x| x == b']') {
|
||||
break self.pos - 2;
|
||||
}
|
||||
}
|
||||
pc = Some(c);
|
||||
}
|
||||
None => return self.error("unexpected eof"),
|
||||
}
|
||||
@@ -213,7 +255,7 @@ impl<'a> Parser<'a> {
|
||||
let end = loop {
|
||||
match self.peek() {
|
||||
Some(t) => match t {
|
||||
b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'[' | b']' => self.eat_char(),
|
||||
b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'[' | b']' | b'"' => self.eat_char(),
|
||||
b'0'..=b'9' => {
|
||||
if is_first {
|
||||
return self.error("unexpected digit");
|
||||
@@ -227,7 +269,11 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
is_first = false;
|
||||
};
|
||||
decode_to_string(self.encoding, &self.str[start..end], true).map_err(|e| self.error2(e))
|
||||
let mut data = &self.str[start..end];
|
||||
if data.starts_with(b"[\"") && data.ends_with(b"\"]") {
|
||||
data = &data[2..data.len() - 2];
|
||||
}
|
||||
decode_to_string(self.encoding, data, true).map_err(|e| self.error2(e))
|
||||
}
|
||||
|
||||
fn is_indent(&self, indent: &[u8]) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user