darklua_core/process/utils/
mod.rs

1mod 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}