diff options
Diffstat (limited to 'src/filters')
| -rw-r--r-- | src/filters/log.rs | 2 | ||||
| -rw-r--r-- | src/filters/mod.rs | 1 | ||||
| -rw-r--r-- | src/filters/values.rs | 144 | 
3 files changed, 146 insertions, 1 deletions
| diff --git a/src/filters/log.rs b/src/filters/log.rs index 8cfdcb4..9ca7d3c 100644 --- a/src/filters/log.rs +++ b/src/filters/log.rs @@ -137,7 +137,7 @@ fn time_is_between(  ///  /// This expects the filename to have the datetime in the pattern `YYYYmmdd-HHMMSS` somewhere in  /// it. -fn datetime_from_filename(name: &OsStr) -> Option<DateTime<Utc>> { +pub(crate) fn datetime_from_filename(name: &OsStr) -> Option<DateTime<Utc>> {      let date_match = DATE_REGEX.find(name.to_str()?)?;      let local_time = Local          .datetime_from_str(date_match.as_str(), "%Y%m%d-%H%M%S") diff --git a/src/filters/mod.rs b/src/filters/mod.rs index 162b6f8..e966851 100644 --- a/src/filters/mod.rs +++ b/src/filters/mod.rs @@ -5,6 +5,7 @@ use num_traits::FromPrimitive as _;  pub mod log;  pub mod player; +pub mod values;  /// Early filtering result.  /// diff --git a/src/filters/values.rs b/src/filters/values.rs new file mode 100644 index 0000000..543b59c --- /dev/null +++ b/src/filters/values.rs @@ -0,0 +1,144 @@ +use std::{ +    cmp::Ordering, +    fmt::{self, Debug}, +}; + +use chrono::{DateTime, Duration, Utc}; + +use super::{log::LogFilter, Filter}; +use crate::{EarlyLogResult, LogResult}; + +pub trait Producer: Send + Sync + Debug { +    type Output; + +    fn produce_early(&self, _early_log: &EarlyLogResult) -> Option<Self::Output> { +        None +    } + +    fn produce(&self, log: &LogResult) -> Self::Output; +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum CompOp { +    Less, +    LessEqual, +    Equal, +    GreaterEqual, +    Greater, +} + +impl fmt::Display for CompOp { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        let symbol = match self { +            CompOp::Less => "<", +            CompOp::LessEqual => "<=", +            CompOp::Equal => "=", +            CompOp::GreaterEqual => ">=", +            CompOp::Greater => ">", +        }; +        f.pad(symbol) +    } +} + +impl CompOp { +    pub fn matches(self, cmp: Ordering) -> bool { +        match cmp { +            Ordering::Less => self == CompOp::Less || self == CompOp::LessEqual, +            Ordering::Equal => { +                self == CompOp::LessEqual || self == CompOp::Equal || self == CompOp::GreaterEqual +            } +            Ordering::Greater => self == CompOp::Greater || self == CompOp::GreaterEqual, +        } +    } +} + +struct Comparator<V>( +    Box<dyn Producer<Output = V>>, +    CompOp, +    Box<dyn Producer<Output = V>>, +); + +impl<V> Debug for Comparator<V> { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        write!(f, "({:?} {} {:?})", self.0, self.1, self.2) +    } +} + +impl<V> Filter<EarlyLogResult, LogResult> for Comparator<V> +where +    V: Ord, +{ +    fn filter(&self, log: &LogResult) -> bool { +        let lhs = self.0.produce(log); +        let rhs = self.2.produce(log); +        self.1.matches(lhs.cmp(&rhs)) +    } +} + +pub fn comparison<V: 'static>( +    lhs: Box<dyn Producer<Output = V>>, +    op: CompOp, +    rhs: Box<dyn Producer<Output = V>>, +) -> Box<dyn LogFilter> +where +    V: Ord, +{ +    Box::new(Comparator(lhs, op, rhs)) +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +struct ConstantProducer<V>(V); + +impl<V: Send + Sync + Debug + Clone> Producer for ConstantProducer<V> { +    type Output = V; +    fn produce_early(&self, _: &EarlyLogResult) -> Option<Self::Output> { +        Some(self.0.clone()) +    } + +    fn produce(&self, _: &LogResult) -> Self::Output { +        self.0.clone() +    } +} + +pub fn constant<V: Send + Sync + Debug + Clone + 'static>( +    value: V, +) -> Box<dyn Producer<Output = V>> { +    Box::new(ConstantProducer(value)) +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +struct TimeProducer; + +impl Producer for TimeProducer { +    type Output = DateTime<Utc>; + +    fn produce_early(&self, early_log: &EarlyLogResult) -> Option<Self::Output> { +        early_log +            .log_file +            .file_name() +            .and_then(super::log::datetime_from_filename) +    } + +    fn produce(&self, log: &LogResult) -> Self::Output { +        log.time +    } +} + +pub fn time() -> Box<dyn Producer<Output = DateTime<Utc>>> { +    Box::new(TimeProducer) +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +struct DurationProducer; + +impl Producer for DurationProducer { +    type Output = Duration; + +    fn produce(&self, log: &LogResult) -> Self::Output { +        log.duration +    } +} + +pub fn duration() -> Box<dyn Producer<Output = Duration>> { +    Box::new(DurationProducer) +} | 
