use super::types::*;
lazy_static!{
pub static ref VALID_SEARCH_FIELDS: HashSet<char> = HashSet::from_iter(
['N', 'D', 'P', 'O', 'L', 'R', 'T', 'A'].iter().cloned());
}
impl SearchSettings {
pub fn new() -> SearchSettings {
SearchSettings {
use_regex: false,
name: false,
path: false,
parts: false,
partof: false,
loc: false,
text: false,
completed: PercentSearch{lt: false, perc: 0},
tested: PercentSearch{lt: false, perc: 0},
}
}
pub fn from_str(s: &str) -> Result<SearchSettings, String> {
let pattern = HashSet::from_iter(s.chars());
debug!("got search pattern: {:?}", pattern);
let invalid: HashSet<char> = pattern.difference(&VALID_SEARCH_FIELDS)
.cloned()
.collect();
if !invalid.is_empty() {
let mut msg = String::new();
write!(msg, "Unknown search fields in pattern: {:?}", invalid).unwrap();
return Err(msg);
}
let mut set = SearchSettings {
use_regex: true,
name: pattern.contains(&'N'),
path: pattern.contains(&'D'),
parts: pattern.contains(&'P'),
partof: pattern.contains(&'O'),
loc: pattern.contains(&'L'),
text: pattern.contains(&'T'),
completed: PercentSearch{lt: false, perc: 0},
tested: PercentSearch{lt: false, perc: 0},
};
if pattern.contains(&'A') {
set.name = !set.name;
set.path = !set.path;
set.parts = !set.parts;
set.partof = !set.partof;
set.loc = !set.loc;
set.text = !set.text;
}
Ok(set)
}
}
fn matches_name(pat: &Regex, names: &ArtNames) -> bool {
for n in names.iter() {
if pat.is_match(&n.raw) {
return true;
}
}
false
}
pub fn show_artifact(name: &ArtName,
art: &Artifact,
pat_case: &Regex,
search_settings: &SearchSettings)
-> bool {
let ss = search_settings;
let completed = (art.completed * 100.0).round() as u8;
let tested = (art.tested * 100.0).round() as u8;
if (ss.completed.lt && completed > ss.completed.perc)
|| (!ss.completed.lt && completed < ss.completed.perc)
|| (ss.tested.lt && tested > ss.tested.perc)
|| (!ss.tested.lt && tested < ss.tested.perc) {
false
} else {
!ss.use_regex
|| (ss.name && pat_case.is_match(&name.raw))
|| (ss.parts && matches_name(pat_case, &art.parts))
|| (ss.partof && matches_name(pat_case, &art.partof))
|| (ss.loc && match art.loc.as_ref() {
None => false,
Some(l) => pat_case.is_match(l.path.to_string_lossy().as_ref()),
})
|| (ss.text && pat_case.is_match(&art.text))
}
}
#[test]
fn test_show_artfact() {
let mut req_one = Artifact::from_str("[REQ-one]
partof = 'REQ-base'
text = 'hello bob'").unwrap();
let req_two = Artifact::from_str("[REQ-two]\ntext = 'goodbye joe'").unwrap();
req_one.1.tested = 0.2;
req_one.1.completed = 0.8;
let search_bob = &Regex::new("bob").unwrap();
let search_two = &Regex::new("two").unwrap();
let mut settings_little_tested = SearchSettings::new();
settings_little_tested.tested = PercentSearch{lt: false, perc: 10};
assert!(show_artifact(&req_one.0, &req_one.1, &search_bob, &settings_little_tested));
let mut settings_ct = SearchSettings::new();
settings_ct.completed = PercentSearch{lt: false, perc: 50};
settings_ct.tested = PercentSearch{lt: false, perc: 50};
assert!(!show_artifact(&req_one.0, &req_one.1, &search_bob, &settings_ct));
let settings_name = SearchSettings::from_str("N").unwrap();
let settings_text = SearchSettings::from_str("T").unwrap();
let settings_nt = SearchSettings::from_str("NT").unwrap();
assert!(show_artifact(&req_one.0, &req_one.1, &search_bob, &settings_text));
assert!(show_artifact(&req_one.0, &req_one.1, &search_bob, &settings_nt));
assert!(show_artifact(&req_two.0, &req_two.1, &search_two, &settings_nt));
assert!(!show_artifact(&req_one.0, &req_one.1, &search_bob, &settings_name));
assert!(!show_artifact(&req_one.0, &req_one.1, &search_two, &settings_nt));
}