darklua_core/process/utils/
mod.rs1mod permutator;
2
3pub(crate) use permutator::Permutator;
4
5pub(crate) type CharPermutator = Permutator<std::str::Chars<'static>>;
6
7pub(crate) fn identifier_permutator() -> CharPermutator {
8 Permutator::new("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789".chars())
9}
10
11pub(crate) fn generate_identifier(permutator: &mut CharPermutator) -> String {
12 permutator
13 .find(|identifier| is_valid_identifier(identifier))
14 .expect("the permutator should always ultimately return a valid identifier")
15}
16
17pub(crate) const KEYWORDS: [&str; 21] = [
18 "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local",
19 "nil", "not", "or", "repeat", "return", "then", "true", "until", "while",
20];
21
22macro_rules! matches_any_keyword {
23 () => {
24 "and"
25 | "break"
26 | "do"
27 | "else"
28 | "elseif"
29 | "end"
30 | "false"
31 | "for"
32 | "function"
33 | "if"
34 | "in"
35 | "local"
36 | "nil"
37 | "not"
38 | "or"
39 | "repeat"
40 | "return"
41 | "then"
42 | "true"
43 | "until"
44 | "while"
45 };
46}
47
48pub(crate) fn is_valid_identifier(identifier: &str) -> bool {
49 !identifier.is_empty()
50 && identifier.is_ascii()
51 && identifier
52 .char_indices()
53 .all(|(i, c)| c.is_alphabetic() || c == '_' || (c.is_ascii_digit() && i > 0))
54 && !matches!(identifier, matches_any_keyword!())
55}
56
57#[cfg(test)]
58mod test {
59 use super::*;
60 #[test]
61 fn is_valid_identifier_is_true() {
62 assert!(is_valid_identifier("hello"));
63 assert!(is_valid_identifier("foo"));
64 assert!(is_valid_identifier("bar"));
65 assert!(is_valid_identifier("VAR"));
66 assert!(is_valid_identifier("_VAR"));
67 assert!(is_valid_identifier("_0"));
68 }
69
70 #[test]
71 fn is_valid_identifier_is_false() {
72 assert!(!is_valid_identifier(""));
73 assert!(!is_valid_identifier("$hello"));
74 assert!(!is_valid_identifier(" "));
75 assert!(!is_valid_identifier("5"));
76 assert!(!is_valid_identifier("1bar"));
77 assert!(!is_valid_identifier("var "));
78 assert!(!is_valid_identifier("sp ace"));
79 }
80
81 #[test]
82 fn keywords_are_not_valid_identifiers() {
83 for keyword in KEYWORDS {
84 assert!(!is_valid_identifier(keyword));
85 }
86 }
87}