From 7881ba85ff40f3d22237ef903c7241b56aa9c185 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 15 Apr 2020 15:01:10 +0200 Subject: new filter pipeline This is the groundwork for introducing more complex filter queries like `find` has. Filters can be arbitrarily combined with and/or/not and support an "early filter" mode. So far, the filters have been translated pretty mechanically to match the current command line arguments, so now new syntax has been introduced. The NameFilter is not yet in its final version. The goal is to support something like PlayerAll/PlayerExists and have a PlayerFilter that works on single players instead of the complete log, but that might introduce some code duplication as we then need a PlayerFilterAnd, PlayerFilterOr, ... Some digging has to be done into whether we can reduce that duplication without devolving into madness or resorting to macros. Maybe some type-level generic hackery could be done? Maybe an enum instead of dynamic traits should be used, at least for the base functions? --- src/csl.rs | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'src/csl.rs') diff --git a/src/csl.rs b/src/csl.rs index e7d84f3..ac20ada 100644 --- a/src/csl.rs +++ b/src/csl.rs @@ -1,14 +1,14 @@ use std::collections::HashSet; +use std::fmt; use std::hash::Hash; use std::str::FromStr; -use std::fmt; -use super::{SearchField, FightOutcome}; +use super::{FightOutcome, SearchField}; use chrono::Weekday; use evtclib::statistics::gamedata::Boss; pub trait Variants: Copy { - type Output: Iterator; + type Output: Iterator; fn variants() -> Self::Output; } @@ -79,18 +79,21 @@ impl fmt::Display for ParseError { } impl FromStr for CommaSeparatedList - where T: FromStr + Variants + Hash + Eq + fmt::Debug +where + T: FromStr + Variants + Hash + Eq + fmt::Debug, { type Err = ParseError; fn from_str(input: &str) -> Result { if input == "*" { - Ok(CommaSeparatedList { values: T::variants().collect() }) + Ok(CommaSeparatedList { + values: T::variants().collect(), + }) } else if input.starts_with(NEGATOR) { let no_csl = CommaSeparatedList::from_str(&input[1..])?; let all_values = T::variants().collect::>(); Ok(CommaSeparatedList { - values: all_values.difference(&no_csl.values).cloned().collect() + values: all_values.difference(&no_csl.values).cloned().collect(), }) } else { let parts = input.split(DELIMITER); @@ -104,9 +107,26 @@ impl FromStr for CommaSeparatedList } impl CommaSeparatedList - where T: Hash + Eq + fmt::Debug +where + T: Hash + Eq + fmt::Debug, { pub fn contains(&self, value: &T) -> bool { self.values.contains(value) } + + pub fn values(&self) -> &HashSet { + &self.values + } +} + +// We allow implicit hasher because then it's a zero-cost conversion, as we're just unwrapping the +// values. +#[allow(clippy::implicit_hasher)] +impl From> for HashSet +where + T: Hash + Eq + fmt::Debug, +{ + fn from(csl: CommaSeparatedList) -> Self { + csl.values + } } -- cgit v1.2.3