Helper function to match string against pattern with wildcard (*)
(text: &str, pattern: &str)
| 257 | |
| 258 | // Helper function to match string against pattern with wildcard (*) |
| 259 | fn matches_wildcard(text: &str, pattern: &str) -> bool { |
| 260 | let text_lower = text.to_lowercase(); |
| 261 | let pattern_lower = pattern.to_lowercase(); |
| 262 | |
| 263 | // Split pattern by asterisks |
| 264 | let parts: Vec<&str> = pattern_lower.split('*').collect(); |
| 265 | |
| 266 | // If no wildcard, it's an exact match (case-insensitive) |
| 267 | if parts.len() == 1 { |
| 268 | return text_lower == pattern_lower; |
| 269 | } |
| 270 | |
| 271 | // If pattern is just asterisk(s), match everything |
| 272 | if parts.is_empty() { |
| 273 | return true; |
| 274 | } |
| 275 | |
| 276 | // Check if pattern starts with asterisk |
| 277 | let starts_with_wildcard = pattern_lower.starts_with('*'); |
| 278 | // Check if pattern ends with asterisk |
| 279 | let ends_with_wildcard = pattern_lower.ends_with('*'); |
| 280 | |
| 281 | let mut pos = 0; |
| 282 | |
| 283 | for (i, part) in parts.iter().enumerate() { |
| 284 | if part.is_empty() { |
| 285 | continue; |
| 286 | } |
| 287 | |
| 288 | // For the first part, check if it should be at the start |
| 289 | if i == 0 && !starts_with_wildcard { |
| 290 | if !text_lower.starts_with(part) { |
| 291 | return false; |
| 292 | } |
| 293 | pos = part.len(); |
| 294 | } else { |
| 295 | // Find the part in the remaining text |
| 296 | if let Some(found_pos) = text_lower[pos..].find(part) { |
| 297 | pos += found_pos + part.len(); |
| 298 | } else { |
| 299 | return false; |
| 300 | } |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | // For the last part, check if it should be at the end |
| 305 | if !ends_with_wildcard && !parts.is_empty() |
| 306 | && let Some(last_part) = parts.last() |
| 307 | && !last_part.is_empty() && !text_lower.ends_with(last_part) { |
| 308 | return false; |
| 309 | } |
| 310 | |
| 311 | true |
| 312 | } |
no test coverage detected