1use super::{LuaConstant, LuaNumber};
2
3use std::collections::HashSet;
4use std::sync::LazyLock;
5
6impl LuaConstant {
7 pub fn as_literal_str(&self) -> Option<&str> {
8 if let Self::String(s) = self {
9 std::str::from_utf8(s).ok()
10 } else {
11 None
12 }
13 }
14
15 pub fn as_ident_str(&self) -> Option<&str> {
16 const KEYWORDS: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
17 [
18 "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if",
19 "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until",
20 "while",
21 ]
22 .into_iter()
23 .collect()
24 });
25
26 self.as_literal_str().filter(|&s| {
27 let mut chars = s.chars();
28 !KEYWORDS.contains(s)
29 && chars
30 .next()
31 .filter(|&c| c.is_alphabetic() || c == '_')
32 .is_some()
33 && chars.all(|c| c.is_alphanumeric() || c == '_')
34 })
35 }
36
37 pub fn to_literal(&self) -> String {
38 match self {
39 Self::String(s) => {
40 format!(
41 "\"{}\"",
42 if let Ok(s) = std::str::from_utf8(s) {
43 s.into()
44 } else {
45 unsafe { std::str::from_utf8_unchecked(s) }
47 }
48 .escape_debug()
49 )
50 }
51 Self::Bool(b) => b.to_string(),
52 Self::Number(LuaNumber::Float(f)) => f.to_string(),
53 Self::Number(LuaNumber::Integer(i)) => i.to_string(),
54 Self::Null => "nil".into(),
55 Self::Proto(i) => format!("function<{i}>"),
56 Self::Table { .. } => "{}".into(),
57 }
59 }
60}