use crate::error::{Error, Result};
#[derive(Debug, Clone)]
struct Action {
item: String,
keep: bool,
wild: bool,
}
#[derive(Debug, Clone)]
pub struct Filter {
actions: Vec<Action>,
}
impl Filter {
pub fn discard_all() -> Self {
Filter {
actions: vec![Action {
item: String::new(),
keep: false,
wild: true,
}],
}
}
pub fn retain_all() -> Self {
Filter {
actions: vec![Action {
item: String::new(),
keep: true,
wild: true,
}],
}
}
pub fn new(filter: &str) -> Result<Self> {
let mut result = Filter {
actions: Vec::new(),
};
for item in filter.split(',') {
if let Some(it) = item.strip_prefix('+') {
if let Some(it) = it.strip_suffix('*') {
result.retain_prefix(it);
} else {
result.retain(it);
}
} else if let Some(it) = item.strip_prefix('-') {
if let Some(it) = it.strip_suffix('*') {
result.discard_prefix(it);
} else {
result.discard(it);
}
} else {
return Err(Error::Parse {
what: format!("Couldn't parse filter '{item}' must be [+-][a-zA-Z0-9_]+*?"),
});
}
}
Ok(result)
}
pub fn retain_prefix(&mut self, it: &str) {
self.actions.push(Action {
item: it.to_string(),
keep: true,
wild: true,
});
}
pub fn retain(&mut self, it: &str) {
self.actions.push(Action {
item: it.to_string(),
keep: true,
wild: false,
});
}
pub fn discard_prefix(&mut self, it: &str) {
self.actions.push(Action {
item: it.to_string(),
keep: false,
wild: true,
});
}
pub fn discard(&mut self, it: &str) {
self.actions.push(Action {
item: it.to_string(),
keep: false,
wild: false,
});
}
pub fn apply(&self, string: &str) -> bool {
let mut result = true;
for Action { item, keep, wild } in &self.actions {
if (*wild && string.starts_with(item)) || string == item {
result = *keep;
}
}
result
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn filter() {
let mut filter = Filter::retain_all();
assert_eq!(filter.apply("abcd"), true);
filter.discard_prefix("a");
assert_eq!(filter.apply("abcd"), false);
filter.retain_prefix("ab");
assert_eq!(filter.apply("abcd"), true);
filter.discard_prefix("abc");
assert_eq!(filter.apply("abcd"), false);
filter.retain("abcd");
assert_eq!(filter.apply("abcd"), true);
assert_eq!(filter.apply("abcq"), false);
}
}