use std::collections::HashSet;
use serde_json::Value;
pub fn remove_duplicates(strings: &mut Vec<String>, stable: bool, lowercase: bool) {
if stable {
let mut seen = HashSet::new();
let mut i = 0;
while i < strings.len() {
if lowercase {
strings[i].make_ascii_lowercase();
}
if strings[i].trim().is_empty() || !seen.insert(strings[i].clone()) {
strings.remove(i);
} else {
i += 1;
}
}
} else {
if lowercase {
strings.iter_mut().for_each(|s| s.make_ascii_lowercase());
}
strings.retain(|s| !s.trim().is_empty());
strings.sort();
strings.dedup();
}
}
pub fn ensure_trailing_slash(s: &str) -> String {
let s = s.trim();
if s.is_empty() {
return String::new();
}
let mut result = s.to_string();
while !result.is_empty() && !result.ends_with('/') {
result.push('/');
}
result
}
pub fn ensure_no_trailing_slash(s: &str) -> String {
let s = s.trim();
if s.is_empty() {
return String::new();
}
let mut result = s.to_string();
while !result.is_empty() && result.ends_with('/') {
result.pop();
}
result
}
pub fn ensure_no_leading_slash(s: &str) -> String {
let s = s.trim();
if s.is_empty() {
return String::new();
}
let mut result = s.to_string();
while !result.is_empty() && result.starts_with('/') {
result.remove(0);
}
result
}
pub fn globbed_strings_match(item: &str, val: &str) -> bool {
if item.len() < 2 {
return item == val;
}
let has_prefix = item.starts_with('*');
let has_suffix = item.ends_with('*');
if has_prefix && has_suffix {
return val.contains(&item[1..item.len() - 1]);
} else if has_prefix {
return val.ends_with(&item[1..]);
} else if has_suffix {
return val.starts_with(&item[..item.len() - 1]);
}
item == val
}
pub trait GlobContains {
fn glob_contains(&self, val: &Value) -> bool;
}
impl GlobContains for &Vec<Value> {
fn glob_contains(&self, val: &Value) -> bool {
if self.is_empty() {
return true;
}
for item in self.iter() {
if item.is_string() {
if globbed_strings_match(item.as_str().unwrap(), val.as_str().unwrap_or_default()) {
return true;
}
} else {
return self.contains(val);
}
}
false
}
}
impl GlobContains for Vec<Value> {
fn glob_contains(&self, val: &Value) -> bool {
(&self).glob_contains(val)
}
}