From ec3088e2bf5e1e778f87580a22b3e5601376ba48 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Sun, 3 Aug 2025 11:00:54 +0800 Subject: [PATCH] Add support for old version of ast files --- src/scripts/artemis/ast/dump.rs | 98 ++++++--- src/scripts/artemis/ast/mod.rs | 304 ++++++++++++++++++++++++-- src/scripts/artemis/ast/parser.rs | 45 +++- src/scripts/artemis/ast/text.rs | 24 +- src/scripts/artemis/ast/types.rs | 349 +++++++++++++++++++++++++++++- 5 files changed, 740 insertions(+), 80 deletions(-) diff --git a/src/scripts/artemis/ast/dump.rs b/src/scripts/artemis/ast/dump.rs index 1d83eb8..c229912 100644 --- a/src/scripts/artemis/ast/dump.rs +++ b/src/scripts/artemis/ast/dump.rs @@ -34,12 +34,20 @@ impl LenChecker { } } Value::KeyVal((k, v)) => { - self.current_len += k.as_bytes().len() - + if lua_key_contains_need_escape(k) { - 7 - } else { - 3 - }; + if let Some(key) = k.as_str() { + self.current_len += key.as_bytes().len() + + if lua_key_contains_need_escape(key) { + 7 + } else { + 3 + }; + } else { + self.current_len += 1; // for '[' + if !self.check(k) { + return false; + } + self.current_len += 4; // for '] = ' + } if !self.check(v) { return false; } @@ -106,8 +114,10 @@ impl<'a> Dumper<'a> { pub fn dump(mut self, ast: &AstFile) -> std::io::Result<()> { if self.indent.is_none() { - self.writer.write(b"astver=")?; - self.dump_f64(&ast.astver)?; + if let Some(astver) = ast.astver { + self.writer.write(b"astver=")?; + self.dump_f64(&astver)?; + } if let Some(astname) = &ast.astname { self.writer.write(b"\nastname = ")?; if lua_str_contains_need_escape(astname) { @@ -123,8 +133,10 @@ impl<'a> Dumper<'a> { self.writer.write(b"\nast=")?; self.dump_value(&ast.ast)?; } else { - self.writer.write(b"astver = ")?; - self.dump_f64(&ast.astver)?; + if let Some(astver) = ast.astver { + self.writer.write(b"astver = ")?; + self.dump_f64(&astver)?; + } if let Some(astname) = &ast.astname { self.writer.write(b"\nastname = ")?; if lua_str_contains_need_escape(&astname) { @@ -162,13 +174,19 @@ impl<'a> Dumper<'a> { } } Value::KeyVal((k, v)) => { - if lua_key_contains_need_escape(k) { - self.writer.write(b"[\"")?; - self.writer.write(k.as_bytes())?; - self.writer.write(b"\"]=")?; + if let Some(k) = k.as_str() { + 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"=")?; + } } else { - self.writer.write(k.as_bytes())?; - self.writer.write(b"=")?; + self.writer.write(b"[")?; + self.dump_value(k)?; + self.writer.write(b"]=")?; } self.dump_value(v)?; } @@ -202,17 +220,25 @@ impl<'a> Dumper<'a> { } } Value::KeyVal((k, v)) => { - let bytes = k.as_bytes(); - 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; + if let Some(k) = k.as_str() { + let bytes = k.as_bytes(); + 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; + } } else { - self.writer.write(bytes)?; - self.writer.write(b" = ")?; - self.current_line_width += bytes.len() + 3; - } + self.writer.write(b"[")?; + self.current_line_width += 1; + self.dump_value(k)?; + self.writer.write(b"] = ")?; + self.current_line_width += 4; // for '] = ' + }; if v.is_array() { let tlen = self.current_line_width + self.current_indent; if tlen < self.max_line_width { @@ -280,14 +306,20 @@ impl<'a> Dumper<'a> { } } Value::KeyVal((k, v)) => { - if lua_key_contains_need_escape(k) { - self.writer.write(b"[\"")?; - self.writer.write(k.as_bytes())?; - self.writer.write(b"\"]=")?; + if let Some(k) = k.as_str() { + 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"=")?; + } } else { - self.writer.write(k.as_bytes())?; - self.writer.write(b"=")?; - } + self.writer.write(b"[")?; + self.dump_value_in_one(k)?; + self.writer.write(b"]=")?; + }; self.dump_value_in_one(v)?; } Value::Array(arr) => { diff --git a/src/scripts/artemis/ast/mod.rs b/src/scripts/artemis/ast/mod.rs index db89695..1826632 100644 --- a/src/scripts/artemis/ast/mod.rs +++ b/src/scripts/artemis/ast/mod.rs @@ -89,11 +89,136 @@ impl Script for AstScript { fn extract_messages(&self) -> Result> { let mut messages = Vec::new(); let ast = &self.ast.ast; + let mut lang: Option<&str> = self.lang.as_ref().map(|s| s.as_str()); + // old version + if ast["label"]["top"]["block"].is_null() && ast["text"].is_array() { + let text = &ast["text"]; + let mut text_index = 1i64; + for block in ast.members() { + if block.is_array() { + 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(), + }); + } + } + if !block[Key("text")].is_null() { + let tex = &text[NumKey(text_index)]; + text_index += 1; + if tex.is_array() { + let lan = match lang { + Some(l) => l, + None => { + for l in tex.kv_keys() { + if l.is_str() && l != "vo" && l != "name" { + lang = l.as_str(); + break; + } + } + match lang { + Some(l) => l, + // No text found, continue to next block + None => continue, + } + } + }; + let mut te = &tex[lan]; + if te.is_null() { + for l in tex.kv_keys() { + if l != "vo" && l != "name" { + te = &tex[l]; + break; + } + } + } + let name = &tex["name"]; + let nam = if name.is_array() { + if let Some(lang) = lang { + if let Some(n) = name[lang].as_string() { + Some(n) + } else if let Some(n) = name["name"].as_string() { + Some(n) + } else { + None + } + } else if let Some(n) = name["name"].as_string() { + Some(n) + } else { + None + } + } else { + None + }; + for item in te.members() { + let message = text::TextGenerator::new().generate(item)?; + messages.push(Message { + name: nam.clone(), + message: message.replace("", "\n").replace("", "\n"), + }); + } + } + } else if !block[Key("select")].is_null() { + let tex = &text[NumKey(text_index)]["select"]; + text_index += 1; + if tex.is_array() { + let lan = match lang { + Some(l) => l, + None => { + for l in tex.kv_keys() { + if l.is_str() && l != "vo" && l != "name" { + lang = l.as_str(); + break; + } + } + match lang { + Some(l) => l, + // No text found, continue to next block + None => continue, + } + } + }; + let mut te = &tex[lan]; + if te.is_null() { + for l in tex.kv_keys() { + if l != "vo" && l != "name" { + te = &tex[l]; + break; + } + } + } + for item in te.members() { + if let Some(select) = item.as_str() { + messages.push(Message { + name: None, + message: select.to_string(), + }); + } + } + } + } + } + } + return Ok(messages); + } let mut block_name = ast["label"]["top"]["block"] .as_str() .ok_or(anyhow::anyhow!("Missing top block name"))?; let mut block = &ast[block_name]; - let mut lang: Option<&str> = self.lang.as_ref().map(|s| s.as_str()); loop { let savetitle = &block[Key("savetitle")]; if savetitle.is_array() { @@ -122,8 +247,8 @@ impl Script for AstScript { Some(l) => l, None => { for l in text.kv_keys() { - if l != "vo" { - lang = Some(l); + if l.is_str() && l != "vo" { + lang = l.as_str(); break; } } @@ -169,8 +294,8 @@ impl Script for AstScript { Some(l) => l, None => { for l in select.kv_keys() { - if l != "vo" { - lang = Some(l); + if l.is_str() && l != "vo" { + lang = l.as_str(); break; } } @@ -224,16 +349,169 @@ impl Script for AstScript { ) -> Result<()> { let mut ast = self.ast.clone(); let root = &mut ast.ast; + let mut lang = self.lang.as_ref().map(|s| s.to_string()); + let mut mess = messages.iter(); + let mut mes = mess.next(); + if root["label"]["top"]["block"].is_null() && root["text"].is_array() { + let mut text_index = 1i64; + let len = root.len(); + for i in 0..len { + if root[i].is_array() { + if root[i][Key("savetitle")].is_array() { + let lan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("text"); + let m = match mes { + Some(m) => m, + None => return Err(anyhow::anyhow!("Not enough messages.")), + }; + let mut title = m.message.clone(); + if let Some(repl) = replacement { + for (k, v) in &repl.map { + title = title.replace(k, v); + } + } + root[i][Key("savetitle")][lan].set_string(title); + mes = mess.next(); + } + } + if !root[i][Key("text")].is_null() { + let lan = match &lang { + Some(l) => l.as_str(), + None => { + for l in root["text"][NumKey(text_index)].kv_keys() { + if l.is_str() && l != "vo" && l != "name" { + lang = l.as_string(); + break; + } + } + match lang { + Some(ref l) => l.as_str(), + // No text found, continue to next block + None => continue, + } + } + }; + if root["text"][NumKey(text_index)]["name"].is_array() { + let name = match mes { + Some(m) => m.name.clone(), + None => return Err(anyhow::anyhow!("Message name is missing.")), + }; + let mut name = match name { + Some(n) => n, + None => return Err(anyhow::anyhow!("Message name is missing.")), + }; + if let Some(repl) = replacement { + for (k, v) in &repl.map { + name = name.replace(k, v); + } + } + let nlan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("name"); + root["text"][NumKey(text_index)]["name"][nlan].set_string(name); + } + let origin_count = { + let text = &root["text"][NumKey(text_index)]; + let mut tex = &text[lan]; + if tex.is_null() { + for l in text.kv_keys() { + if l != "vo" && l != "name" { + tex = &text[l]; + break; + } + } + } + tex.len() + }; + let mut arr = Value::new_array(); + for _ in 0..origin_count { + let m = match mes { + Some(m) => m, + None => return Err(anyhow::anyhow!("Not enough messages.")), + }; + let mut text = m.message.clone(); + if let Some(repl) = replacement { + for (k, v) in &repl.map { + text = text.replace(k, v); + } + } + let v = text::TextParser::new(&text.replace("\n", "")).parse()?; + arr.push_member(v); + mes = mess.next(); + } + root["text"][NumKey(text_index)][lan] = arr; + text_index += 1; + } else if !root[i][Key("select")].is_null() { + let lan = match &lang { + Some(l) => l.as_str(), + None => { + for l in root["text"][NumKey(text_index)]["select"].kv_keys() { + if l.is_str() && l != "vo" && l != "name" { + lang = l.as_string(); + break; + } + } + match lang { + Some(ref l) => l.as_str(), + // No text found, continue to next block + None => continue, + } + } + }; + let count = { + let text = &root["text"][NumKey(text_index)]["select"]; + let mut tex = &text[lan]; + if tex.is_null() { + for l in text.kv_keys() { + if l != "vo" && l != "name" { + tex = &text[l]; + break; + } + } + } + tex.len() + }; + let mut new_select = Value::new_array(); + for _ in 0..count { + let m = match mes { + Some(m) => m, + None => return Err(anyhow::anyhow!("Not enough messages.")), + }; + let mut select_text = m.message.clone(); + if let Some(repl) = replacement { + for (k, v) in &repl.map { + select_text = select_text.replace(k, v); + } + } + new_select.push_member(Value::Str(select_text)); + mes = mess.next(); + } + root["text"][NumKey(text_index)]["select"][lan] = new_select; + text_index += 1; + } + } + if mes.is_some() || mess.next().is_some() { + return Err(anyhow::anyhow!("Not all messages were used.")); + } + let mut writer = Vec::new(); + let mut dumper = dump::Dumper::new(&mut writer); + if self.no_indent { + dumper.set_no_indent(); + } else if let Some(indent) = self.indent { + dumper.set_indent(indent); + } + dumper.set_max_line_width(self.max_line_width); + dumper.dump(&ast)?; + let data = String::from_utf8(writer)?; + let encoded = encode_string(encoding, &data, false)?; + file.write_all(&encoded)?; + file.flush()?; + return Ok(()); + } let mut block_name = root["label"]["top"]["block"] .as_string() .ok_or(anyhow::anyhow!("Missing top block name"))?; let mut block = &mut root[block_name]; - let mut mess = messages.iter(); - let mut mes = mess.next(); - let mut lang = self.lang.as_ref().map(|s| s.to_string()); loop { if block[Key("savetitle")].is_array() { - let lan = lang.as_ref().map(|s| s.as_str()).unwrap_or("text"); + let lan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("text"); let m = match mes { Some(m) => m, None => return Err(anyhow::anyhow!("Not enough messages.")), @@ -252,8 +530,8 @@ impl Script for AstScript { Some(l) => l.as_str(), None => { for l in block["text"].kv_keys() { - if l != "vo" { - lang = Some(l.to_string()); + if l.is_str() && l != "vo" { + lang = l.as_string(); break; } } @@ -328,8 +606,8 @@ impl Script for AstScript { Some(l) => l.as_str(), None => { for l in block["select"].kv_keys() { - if l != "vo" { - lang = Some(l.to_string()); + if l.is_str() && l != "vo" { + lang = l.as_string(); break; } } diff --git a/src/scripts/artemis/ast/parser.rs b/src/scripts/artemis/ast/parser.rs index a9e6503..8b2289a 100644 --- a/src/scripts/artemis/ast/parser.rs +++ b/src/scripts/artemis/ast/parser.rs @@ -28,17 +28,31 @@ impl<'a> Parser<'a> { pub fn try_parse_header(mut self) -> Result<()> { self.erase_whitespace(); - self.parse_indent(b"astver")?; - self.parse_equal()?; - self.parse_f64()?; + if self.is_indent(b"astver") { + self.parse_indent(b"astver")?; + self.parse_equal()?; + self.parse_f64()?; + } else if self.is_indent(b"astname") { + self.parse_indent(b"astname")?; + self.parse_equal()?; + } else if self.is_indent(b"ast") { + self.parse_indent(b"ast")?; + self.parse_equal()?; + } else { + return self.error("expected 'astver', 'astname' or 'ast'"); + } Ok(()) } pub fn parse(mut self) -> Result { self.erase_whitespace(); - self.parse_indent(b"astver")?; - self.parse_equal()?; - let astver = self.parse_f64()?; + let astver = if self.is_indent(b"astver") { + self.parse_indent(b"astver")?; + self.parse_equal()?; + Some(self.parse_f64()?) + } else { + None + }; self.erase_whitespace(); let mut astname = None; if self.is_indent(b"astname") { @@ -262,17 +276,26 @@ impl<'a> Parser<'a> { let key = self.get_indent()?; self.parse_equal()?; let val = self.parse_value()?; - Ok(Value::KeyVal((key.to_string(), Box::new(val)))) + Ok(Value::KeyVal((Box::new(key), Box::new(val)))) } - fn get_indent(&mut self) -> Result { + fn get_indent(&mut self) -> Result { self.erase_whitespace(); let start = self.pos; let mut is_first = true; let end = loop { match self.peek() { Some(t) => match t { - b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'[' | b']' | b'"' => self.eat_char(), + b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'"' => self.eat_char(), + b'[' => { + self.eat_char(); + let v = self.parse_value()?; + let n = self.next().ok_or(self.error2("unexpected eof"))?; + if n != b']' { + return self.error("expected ']' after key"); + } + return Ok(v); + } b'0'..=b'9' => { if is_first { return self.error("unexpected digit"); @@ -290,7 +313,9 @@ impl<'a> Parser<'a> { 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)) + Ok(Value::Str( + decode_to_string(self.encoding, data, true).map_err(|e| self.error2(e))?, + )) } fn is_indent(&self, indent: &[u8]) -> bool { diff --git a/src/scripts/artemis/ast/text.rs b/src/scripts/artemis/ast/text.rs index 965efdf..71cb881 100644 --- a/src/scripts/artemis/ast/text.rs +++ b/src/scripts/artemis/ast/text.rs @@ -81,6 +81,10 @@ impl TextGenerator { self.data.push_str(&i.to_string()); } Value::KeyVal((k, v)) => { + let k = k.as_str().ok_or(anyhow::anyhow!( + "Expected key to be a string, but found: {:?}", + k + ))?; self.data.push_str(k); self.data.push('='); match v.as_ref() { @@ -201,7 +205,7 @@ impl<'a> TextParser<'a> { | "9" => self.parse_any_number()?, _ => return self.error("Expected value after key"), }; - Value::KeyVal((key, Box::new(v))) + Value::new_kv(key, v) } else { Value::Str(key) }; @@ -368,12 +372,9 @@ fn test_gen() { Value::Str("title".to_string()), Value::Int(1), Value::Float(2.0), - Value::KeyVal(( - "name".to_string(), - Box::new(Value::Str("World".to_string())), - )), - Value::KeyVal(("int".to_string(), Box::new(Value::Int(42)))), - Value::KeyVal(("float".to_string(), Box::new(Value::Float(3.0)))), + Value::new_kv("name", "World"), + Value::new_kv("int", 42), + Value::new_kv("float", 3.0), ]), Value::Str(">World".to_string()), ]); @@ -392,12 +393,9 @@ fn test_parse() { Value::Str("title".to_string()), Value::Int(1), Value::Float(2.0), - Value::KeyVal(( - "name".to_string(), - Box::new(Value::Str("World".to_string())), - )), - Value::KeyVal(("int".to_string(), Box::new(Value::Int(42)))), - Value::KeyVal(("float".to_string(), Box::new(Value::Float(3.0)))), + Value::new_kv("name", "World"), + Value::new_kv("int", 42), + Value::new_kv("float", 3.0), ]), Value::Str(">World".to_string()), ]); diff --git a/src/scripts/artemis/ast/types.rs b/src/scripts/artemis/ast/types.rs index f79f302..0faa1de 100644 --- a/src/scripts/artemis/ast/types.rs +++ b/src/scripts/artemis/ast/types.rs @@ -7,7 +7,7 @@ pub enum Value { Float(f64), Int(i64), Str(String), - KeyVal((String, Box)), + KeyVal((Box, Box)), Array(Vec), Null, } @@ -18,10 +18,33 @@ impl From for Value { } } +impl<'a> From<&'a str> for Value { + fn from(s: &'a str) -> Self { + Value::Str(s.to_string()) + } +} + +impl From for Value { + fn from(i: i64) -> Self { + Value::Int(i) + } +} + +impl From for Value { + fn from(f: f64) -> Self { + Value::Float(f) + } +} + /// Reprsents a key in nested arrays. /// For example, in the array `{"save", text="test"}`, the key is `"save"`. pub struct Key<'a>(pub &'a str); +/// Represents a key in key value pairs. +/// For example, in the key value pair `[1] = "test"`, the key is `1`. +#[derive(Clone, Copy)] +pub struct NumKey(pub T); + impl<'a> Deref for Key<'a> { type Target = str; @@ -96,6 +119,10 @@ impl Value { matches!(self, Value::Array(_)) } + pub fn is_str(&self) -> bool { + matches!(self, Value::Str(_)) + } + pub fn is_kv(&self) -> bool { matches!(self, Value::KeyVal(_)) } @@ -104,17 +131,17 @@ impl Value { matches!(self, Value::Null) } - pub fn kv_key(&self) -> Option<&str> { + pub fn kv_key(&self) -> Option<&Value> { if let Value::KeyVal((k, _)) = self { - Some(k) + Some(&k) } else { None } } - pub fn kv_keys<'a>(&'a self) -> Box + 'a> { + pub fn kv_keys<'a>(&'a self) -> Box + 'a> { match self { - Value::KeyVal((k, _)) => Box::new(std::iter::once(k.as_str())), + Value::KeyVal((k, _)) => Box::new(std::iter::once(&**k)), Value::Array(arr) => Box::new(arr.iter().filter_map(|v| v.kv_key())), _ => Box::new(std::iter::empty()), } @@ -184,8 +211,8 @@ impl Value { Value::Array(Vec::new()) } - pub fn new_kv>(key: S, value: Value) -> Self { - Value::KeyVal((key.into(), Box::new(value))) + pub fn new_kv, V: Into>(key: K, value: V) -> Self { + Value::KeyVal((Box::new(key.into()), Box::new(value.into()))) } pub fn push_member(&mut self, value: Value) { @@ -274,7 +301,7 @@ impl<'a> IndexMut<&'a str> for Value { unreachable!() } } else { - *self = Value::KeyVal((index.to_string(), Box::new(NULL))); + *self = Value::KeyVal((Box::new(index.to_string().into()), Box::new(NULL))); if let Value::KeyVal((_, v)) = self { v } else { @@ -295,7 +322,10 @@ impl<'a> IndexMut<&'a str> for Value { } } if let Value::Array(arr) = self { - arr.push(Value::KeyVal((index.to_string(), Box::new(NULL)))); + arr.push(Value::KeyVal(( + Box::new(index.to_string().into()), + Box::new(NULL), + ))); if let Value::KeyVal((_, v)) = arr.last_mut().unwrap() { v } else { @@ -306,7 +336,10 @@ impl<'a> IndexMut<&'a str> for Value { } } _ => { - *self = Value::Array(vec![Value::KeyVal((index.to_string(), Box::new(NULL)))]); + *self = Value::Array(vec![Value::KeyVal(( + Box::new(index.to_string().into()), + Box::new(NULL), + ))]); self.index_mut(index) } } @@ -345,6 +378,237 @@ impl IndexMut for Value { } } +impl<'a> Index<&'a Value> for Value { + type Output = Value; + + fn index(&self, key: &'a Value) -> &Self::Output { + match self { + Value::KeyVal((k, v)) if k == key => v, + Value::Array(arr) => { + for item in arr.iter().rev() { + if let Value::KeyVal((k, v)) = item { + if k == key { + return v; + } + } + } + &NULL + } + _ => &NULL, + } + } +} + +impl<'a> IndexMut<&'a Value> for Value { + fn index_mut(&mut self, index: &'a Value) -> &mut Self::Output { + match &self { + Value::KeyVal((k, _)) => { + if k == index { + if let Value::KeyVal((_, v)) = self { + v + } else { + unreachable!() + } + } else { + *self = Value::KeyVal((Box::new(index.clone()), Box::new(NULL))); + if let Value::KeyVal((_, v)) = self { + v + } else { + unreachable!() + } + } + } + Value::Array(arr) => { + for (i, item) in arr.iter().enumerate().rev() { + if let Value::KeyVal((k, _)) = item { + if k == index { + if let Value::KeyVal((_, v)) = &mut self[i] { + return v; + } else { + unreachable!() + } + } + } + } + if let Value::Array(arr) = self { + arr.push(Value::KeyVal((Box::new(index.clone()), Box::new(NULL)))); + if let Value::KeyVal((_, v)) = arr.last_mut().unwrap() { + v + } else { + unreachable!() + } + } else { + unreachable!() + } + } + _ => { + *self = Value::Array(vec![Value::KeyVal(( + Box::new(index.clone()), + Box::new(NULL), + ))]); + self.index_mut(index) + } + } + } +} + +impl<'a> Index<&'a Box> for Value { + type Output = Value; + + #[inline(always)] + fn index(&self, key: &'a Box) -> &Self::Output { + self.index(&**key) + } +} + +impl Index> for Value { + type Output = Value; + + fn index(&self, key: NumKey) -> &Self::Output { + match self { + Value::KeyVal((k, v)) if k == key.0 => v, + Value::Array(arr) => { + for item in arr.iter().rev() { + if let Value::KeyVal((k, v)) = item { + if k == key.0 { + return v; + } + } + } + &NULL + } + _ => &NULL, + } + } +} + +impl IndexMut> for Value { + fn index_mut(&mut self, key: NumKey) -> &mut Self::Output { + match &self { + Value::KeyVal((k, _)) => { + if k == key.0 { + if let Value::KeyVal((_, v)) = self { + v + } else { + unreachable!() + } + } else { + *self = Value::KeyVal((Box::new(key.0.into()), Box::new(NULL))); + if let Value::KeyVal((_, v)) = self { + v + } else { + unreachable!() + } + } + } + Value::Array(arr) => { + for (i, item) in arr.iter().enumerate().rev() { + if let Value::KeyVal((k, _)) = item { + if k == key.0 { + if let Value::KeyVal((_, v)) = &mut self[i] { + return v; + } else { + unreachable!() + } + } + } + } + if let Value::Array(arr) = self { + arr.push(Value::KeyVal((Box::new(key.0.into()), Box::new(NULL)))); + if let Value::KeyVal((_, v)) = arr.last_mut().unwrap() { + v + } else { + unreachable!() + } + } else { + unreachable!() + } + } + _ => { + *self = Value::Array(vec![Value::KeyVal(( + Box::new(key.0.into()), + Box::new(NULL), + ))]); + self.index_mut(key) + } + } + } +} + +impl Index> for Value { + type Output = Value; + + fn index(&self, key: NumKey) -> &Self::Output { + match self { + Value::KeyVal((k, v)) if k == key.0 => v, + Value::Array(arr) => { + for item in arr.iter().rev() { + if let Value::KeyVal((k, v)) = item { + if k == key.0 { + return v; + } + } + } + &NULL + } + _ => &NULL, + } + } +} + +impl IndexMut> for Value { + fn index_mut(&mut self, key: NumKey) -> &mut Self::Output { + match &self { + Value::KeyVal((k, _)) => { + if k == key.0 { + if let Value::KeyVal((_, v)) = self { + v + } else { + unreachable!() + } + } else { + *self = Value::KeyVal((Box::new(key.0.into()), Box::new(NULL))); + if let Value::KeyVal((_, v)) = self { + v + } else { + unreachable!() + } + } + } + Value::Array(arr) => { + for (i, item) in arr.iter().enumerate().rev() { + if let Value::KeyVal((k, _)) = item { + if k == key.0 { + if let Value::KeyVal((_, v)) = &mut self[i] { + return v; + } else { + unreachable!() + } + } + } + } + if let Value::Array(arr) = self { + arr.push(Value::KeyVal((Box::new(key.0.into()), Box::new(NULL)))); + if let Value::KeyVal((_, v)) = arr.last_mut().unwrap() { + v + } else { + unreachable!() + } + } else { + unreachable!() + } + } + _ => { + *self = Value::Array(vec![Value::KeyVal(( + Box::new(key.0.into()), + Box::new(NULL), + ))]); + self.index_mut(key) + } + } + } +} + impl<'a, 'b> Index<&'b Key<'a>> for Value { type Output = Value; @@ -410,6 +674,55 @@ impl PartialEq for Value { } } +impl PartialEq for Box { + #[inline(always)] + fn eq(&self, other: &str) -> bool { + **self == *other + } +} + +impl PartialEq for Box { + #[inline(always)] + fn eq(&self, other: &String) -> bool { + **self == *other + } +} + +impl PartialEq for Box { + #[inline(always)] + fn eq(&self, other: &i64) -> bool { + **self == *other + } +} + +impl PartialEq for Box { + #[inline(always)] + fn eq(&self, other: &f64) -> bool { + **self == *other + } +} + +impl PartialEq for Box { + #[inline(always)] + fn eq(&self, other: &Value) -> bool { + **self == *other + } +} + +impl<'a> PartialEq for &'a Box { + #[inline(always)] + fn eq(&self, other: &i64) -> bool { + **self == *other + } +} + +impl<'a> PartialEq for &'a Box { + #[inline(always)] + fn eq(&self, other: &f64) -> bool { + **self == *other + } +} + impl PartialOrd for Value { fn partial_cmp(&self, other: &i64) -> Option { match self { @@ -428,6 +741,20 @@ impl PartialOrd for Value { } } +impl PartialOrd for Box { + #[inline(always)] + fn partial_cmp(&self, other: &i64) -> Option { + (**self).partial_cmp(other) + } +} + +impl PartialOrd for Box { + #[inline(always)] + fn partial_cmp(&self, other: &f64) -> Option { + (**self).partial_cmp(other) + } +} + #[derive(Default)] pub struct Iter<'a> { iter: std::slice::Iter<'a, Value>, @@ -486,7 +813,7 @@ impl<'a> DoubleEndedIterator for IterMut<'a> { #[derive(Clone, Debug)] pub struct AstFile { - pub astver: f64, + pub astver: Option, pub astname: Option, pub ast: Value, }