pub fn glob_matches(pattern: &str, text: &str) -> bool {
glob_matches_impl(pattern, text)
}
fn glob_matches_impl(pattern: &str, text: &str) -> bool {
let mut pattern_chars = pattern.chars().peekable();
let mut text_chars = text.chars().peekable();
while let Some(pc) = pattern_chars.next() {
match pc {
'*' => {
let next_pattern: String = pattern_chars.collect();
if next_pattern.is_empty() {
return true;
}
while text_chars.peek().is_some() {
let remaining: String = text_chars.clone().collect();
if glob_matches_impl(&next_pattern, &remaining) {
return true;
}
text_chars.next();
}
return glob_matches_impl(&next_pattern, "");
}
'?' => {
if text_chars.next().is_none() {
return false;
}
}
'\\' => {
if let Some(literal) = pattern_chars.next() {
if text_chars.next() != Some(literal) {
return false;
}
} else {
return text_chars.next() == Some('\\');
}
}
c => {
if text_chars.next() != Some(c) {
return false;
}
}
}
}
text_chars.next().is_none()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_glob_matches_exact() {
assert!(glob_matches("agent-123", "agent-123"));
assert!(glob_matches("", ""));
}
#[test]
fn test_glob_matches_wildcard() {
assert!(glob_matches("agent-*", "agent-123"));
assert!(glob_matches("agent-*", "agent-"));
assert!(glob_matches("agent-*", "agent-abc"));
assert!(!glob_matches("agent-*", "user-123"));
assert!(!glob_matches("agent-*", "agent-123-extra"));
}
#[test]
fn test_glob_matches_single_char() {
assert!(glob_matches("agent-???", "agent-123"));
assert!(glob_matches("agent-???", "agent-abc"));
assert!(!glob_matches("agent-???", "agent-12"));
assert!(!glob_matches("agent-???", "agent-1234"));
}
#[test]
fn test_glob_matches_combined() {
assert!(glob_matches("*-test", "agent-test"));
assert!(glob_matches("*-test", "123-test"));
assert!(glob_matches("user:*:msg", "user:123:msg"));
assert!(!glob_matches("user:*:msg", "user:123:data"));
}
#[test]
fn test_glob_matches_escape() {
assert!(glob_matches(r"literal\*", "literal*"));
assert!(glob_matches(r"literal\?", "literal?"));
assert!(!glob_matches(r"literal\*", "literalX"));
}
#[test]
fn test_glob_matches_multiple_wildcards() {
assert!(glob_matches("user-*-msg-*", "user-123-msg-456"));
assert!(glob_matches("*", "anything"));
assert!(glob_matches("***", "anything"));
}
#[test]
fn test_glob_matches_empty_text() {
assert!(glob_matches("", ""));
assert!(glob_matches("*", ""));
assert!(!glob_matches("?", ""));
}
}