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