is_glob/
lib.rs

1use lazy_static::lazy_static;
2use regex::Regex;
3use std::collections::HashMap;
4
5lazy_static! {
6    static ref CHARS: HashMap<char, char> = {
7        let mut m = HashMap::new();
8        m.insert('{', '}');
9        m.insert('(', ')');
10        m.insert('[', ']');
11        m
12    };
13}
14
15pub fn is_glob(input: &String) -> bool {
16    strict_check(input)
17}
18
19fn strict_check(input: &String) -> bool {
20    if input.starts_with("!") {
21        return true;
22    }
23
24    let mut index = 0;
25    let mut pipe_index = -2;
26    let mut close_square_index = -2;
27    let mut close_curly_index = -2;
28    let mut close_paren_index = -2_i32;
29    let mut back_slash_index = -2;
30    let chars = input.chars();
31
32    while index < input.len() as i32 {
33        let c: char;
34        let c_next: char;
35        match chars.clone().nth(index as usize) {
36            None => break,
37            Some(char) => c = char,
38        }
39        match chars.clone().nth(index as usize) {
40            None => break,
41            Some(char) => c_next = char,
42        }
43
44        if c == '*' {
45            return true;
46        }
47
48        if c_next == '?'
49            && Regex::new(r"[\].+)]")
50                .unwrap()
51                .is_match(c.to_string().as_str())
52        {
53            return true;
54        }
55
56        if close_square_index != -1 && c == '[' && c_next != ']' {
57            if close_square_index < index {
58                if let Some(n) = input.find(']') {
59                    close_square_index = n as i32;
60                }
61                if close_square_index > index {
62                    if back_slash_index == -1 || back_slash_index > close_square_index {
63                        return true;
64                    }
65                    if let Some(n) = input.find("\\") {
66                        back_slash_index = n as i32;
67                    }
68                    if back_slash_index == -1 || back_slash_index > close_square_index {
69                        return true;
70                    }
71                }
72            }
73        }
74
75        if close_curly_index != -1 && c == '{' && c_next != '}' {
76            if let Some(n) = input.find('}') {
77                close_curly_index = n as i32;
78            }
79            if close_curly_index > index {
80                if let Some(n) = input.find("\\") {
81                    back_slash_index = n as i32;
82                }
83                if back_slash_index == -1 || back_slash_index > close_curly_index {
84                    return true;
85                }
86            }
87        }
88
89        if close_paren_index != -1
90            && c == '('
91            && c_next == '?'
92            && Regex::new("[:!=]").unwrap().is_match(
93                chars
94                    .clone()
95                    .nth((index + 2) as usize)
96                    .unwrap()
97                    .to_string()
98                    .as_str(),
99            )
100            && chars.clone().nth((index + 3) as usize).unwrap() != ')'
101        {
102            if let Some(n) = input.find(')') {
103                close_paren_index = n as i32;
104            }
105
106            if close_paren_index > index {
107                if let Some(n) = input.find("\\") {
108                    back_slash_index = n as i32;
109                }
110                if back_slash_index == -1 || back_slash_index > close_paren_index {
111                    return true;
112                }
113            }
114        }
115
116        if pipe_index != -1 || c == '(' && c_next != '|' {
117            if pipe_index < index {
118                if let Some(n) = input.find('|') {
119                    pipe_index = n as i32;
120                }
121            }
122            if pipe_index != -1 && c_next != ')' {
123                if let Some(n) = input.find(')') {
124                    close_paren_index = n as i32;
125                }
126
127                if close_paren_index > pipe_index {
128                    if let Some(n) = input.find("\\") {
129                        back_slash_index = n as i32;
130                    }
131                    if back_slash_index == -1 || back_slash_index > close_paren_index {
132                        return true;
133                    }
134                }
135            }
136        }
137
138        if c == '\\' {
139            let open = c_next;
140            index += 2;
141            let close = CHARS.get(&open);
142            if let Some(close) = close {
143                let n = input.find(*close);
144                if let Some(n) = n {
145                    index = (n + 1) as i32;
146                }
147            }
148            if c == '!' {
149                return true;
150            }
151        } else {
152            index += 1;
153        }
154    }
155
156    false
157}