From 5dbea93266c3a30dac5ec6f5a7915d73a440f573 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 25 Apr 2020 13:14:30 +0200 Subject: use free functions instead of Filter::new Having a ::new on each of the filter types was a bit weird, especially because we returned Box instead of Self (and clippy rightfully complained). With this patch, we now have a bunch of normal functions, and we don't show to the outside how a filter is actually implemented (or what struct is behind it). --- src/fexpr/grammar.lalrpop | 26 ++++++------- src/filters/log.rs | 99 +++++++++++++++++++++++++++++------------------ src/filters/mod.rs | 14 +++---- src/filters/player.rs | 23 +++++++---- src/main.rs | 3 +- 5 files changed, 97 insertions(+), 68 deletions(-) diff --git a/src/fexpr/grammar.lalrpop b/src/fexpr/grammar.lalrpop index caaaf7f..d8f64fa 100644 --- a/src/fexpr/grammar.lalrpop +++ b/src/fexpr/grammar.lalrpop @@ -44,19 +44,19 @@ Negation: T = { } LogPredicate: Box = { - "-success" => filters::log::OutcomeFilter::success(), - "-wipe" => filters::log::OutcomeFilter::wipe(), - "-outcome" > => filters::log::OutcomeFilter::new(<>), + "-success" => filters::log::success(), + "-wipe" => filters::log::wipe(), + "-outcome" > => filters::log::outcome(<>), - "-weekday" > => filters::log::WeekdayFilter::new(<>), - "-before" => filters::log::TimeFilter::new(None, Some(<>)), - "-after" => filters::log::TimeFilter::new(Some(<>), None), + "-weekday" > => filters::log::weekday(<>), + "-before" => filters::log::before(<>), + "-after" => filters::log::after(<>), - "-boss" > => filters::log::BossFilter::new(<>), + "-boss" > => filters::log::boss(<>), "-player" => filters::player::any( - filters::player::NameFilter::new(SearchField::Character, <>.clone()) - | filters::player::NameFilter::new(SearchField::Account, <>) + filters::player::character(<>.clone()) + | filters::player::account(<>) ), "all" "(" "player" ":" ")" => filters::player::all(<>), @@ -67,11 +67,11 @@ LogPredicate: Box = { } PlayerPredicate: Box = { - "-character" => filters::player::NameFilter::new(SearchField::Character, <>), - "-account" => filters::player::NameFilter::new(SearchField::Account, <>), + "-character" => filters::player::character(<>), + "-account" => filters::player::account(<>), "-name" => - filters::player::NameFilter::new(SearchField::Account, <>.clone()) - | filters::player::NameFilter::new(SearchField::Character, <>), + filters::player::account(<>.clone()) + | filters::player::character(<>), "(" ")", } diff --git a/src/filters/log.rs b/src/filters/log.rs index 8b84bf3..8d4e0b5 100644 --- a/src/filters/log.rs +++ b/src/filters/log.rs @@ -19,13 +19,7 @@ use num_traits::FromPrimitive as _; pub trait LogFilter = Filter; #[derive(Debug, Clone)] -pub struct BossFilter(HashSet); - -impl BossFilter { - pub fn new(bosses: HashSet) -> Box { - Box::new(BossFilter(bosses)) - } -} +struct BossFilter(HashSet); impl Filter for BossFilter { fn filter_early(&self, partial_evtc: &PartialEvtc) -> Inclusion { @@ -40,26 +34,14 @@ impl Filter for BossFilter { } } -#[derive(Debug, Clone)] -pub struct OutcomeFilter(HashSet); - -impl OutcomeFilter { - pub fn new(outcomes: HashSet) -> Box { - Box::new(OutcomeFilter(outcomes)) - } +/// A `LogFilter` that only accepts logs with one of the given bosses. +pub fn boss(bosses: HashSet) -> Box { + Box::new(BossFilter(bosses)) +} - pub fn success() -> Box { - let mut outcomes = HashSet::new(); - outcomes.insert(FightOutcome::Success); - Self::new(outcomes) - } - pub fn wipe() -> Box { - let mut outcomes = HashSet::new(); - outcomes.insert(FightOutcome::Wipe); - Self::new(outcomes) - } -} +#[derive(Debug, Clone)] +struct OutcomeFilter(HashSet); impl Filter for OutcomeFilter { fn filter(&self, log: &LogResult) -> bool { @@ -67,30 +49,49 @@ impl Filter for OutcomeFilter { } } -#[derive(Debug, Clone)] -pub struct WeekdayFilter(HashSet); +/// A `LogFilter` that only accepts logs with one of the given outcomes. +/// +/// See also [`success`][success] and [`wipe`][wipe]. +pub fn outcome(outcomes: HashSet) -> Box { + Box::new(OutcomeFilter(outcomes)) +} -impl WeekdayFilter { - pub fn new(weekdays: HashSet) -> Box { - Box::new(WeekdayFilter(weekdays)) - } +/// A `LogFilter` that only accepts successful logs. +/// +/// See also [`outcome`][outcome] and [`wipe`][wipe]. +pub fn success() -> Box { + let mut outcomes = HashSet::new(); + outcomes.insert(FightOutcome::Success); + outcome(outcomes) +} + +/// A `LogFilter` that only accepts failed logs. +/// +/// See also [`outcome`][outcome] and [`success`][wipe]. +pub fn wipe() -> Box { + let mut outcomes = HashSet::new(); + outcomes.insert(FightOutcome::Wipe); + outcome(outcomes) } +#[derive(Debug, Clone)] +struct WeekdayFilter(HashSet); + impl Filter for WeekdayFilter { fn filter(&self, log: &LogResult) -> bool { self.0.contains(&log.time.weekday()) } } -#[derive(Debug, Clone)] -pub struct TimeFilter(Option, Option); - -impl TimeFilter { - pub fn new(after: Option, before: Option) -> Box { - Box::new(TimeFilter(after, before)) - } +/// A `LogFilter` that only accepts logs if they were done on one of the given weekdays. +pub fn weekday(weekdays: HashSet) -> Box { + Box::new(WeekdayFilter(weekdays)) } + +#[derive(Debug, Clone)] +struct TimeFilter(Option, Option); + impl Filter for TimeFilter { fn filter(&self, log: &LogResult) -> bool { let after_ok = match self.0 { @@ -105,3 +106,25 @@ impl Filter for TimeFilter { after_ok && before_ok } } + +/// A `LogFilter` that only accepts logs in the given time frame. +/// +/// If a bound is not given, -Infinity is assumed for the lower bound, and Infinity for the upper +/// bound. +pub fn time(lower: Option, upper: Option) -> Box { + Box::new(TimeFilter(lower, upper)) +} + +/// A `LogFilter` that only accepts logs after the given date. +/// +/// Also see [`time`][time] and [`before`][before]. +pub fn after(when: NaiveDateTime) -> Box { + time(Some(when), None) +} + +/// A `LogFilter` that only accepts logs before the given date. +/// +/// Also see [`time`][time] and [`after`][after]. +pub fn before(when: NaiveDateTime) -> Box { + time(None, Some(when)) +} diff --git a/src/filters/mod.rs b/src/filters/mod.rs index 3d0868b..162b6f8 100644 --- a/src/filters/mod.rs +++ b/src/filters/mod.rs @@ -1,4 +1,3 @@ -#![allow(clippy::new_ret_no_self)] use std::{fmt, ops}; use num_derive::FromPrimitive; @@ -74,13 +73,7 @@ pub trait Filter: Send + Sync + fmt::Debug { } #[derive(Debug, Clone, Copy)] -pub struct Const(pub bool); - -impl Const { - pub fn new(output: bool) -> Box> { - Box::new(Const(output)) - } -} +struct Const(pub bool); impl Filter for Const { fn filter_early(&self, _: &E) -> Inclusion { @@ -92,6 +85,11 @@ impl Filter for Const { } } +/// Construct a `Filter` that always returns a fixed value. +pub fn constant(output: bool) -> Box> { + Box::new(Const(output)) +} + struct AndFilter(Box>, Box>); impl Filter for AndFilter { diff --git a/src/filters/player.rs b/src/filters/player.rs index 8f9196a..4daeb22 100644 --- a/src/filters/player.rs +++ b/src/filters/player.rs @@ -64,13 +64,7 @@ pub fn any(player_filter: Box) -> Box { /// /// The given SearchField determines in which field something should be searched. #[derive(Debug, Clone)] -pub struct NameFilter(SearchField, Regex); - -impl NameFilter { - pub fn new(field: SearchField, regex: Regex) -> Box { - Box::new(NameFilter(field, regex)) - } -} +struct NameFilter(SearchField, Regex); impl Filter for NameFilter { fn filter_early(&self, agent: &Agent) -> Inclusion { @@ -108,3 +102,18 @@ impl Filter for NameFilter { } } } + +/// Construct a `PlayerFilter` that searches the given `field` with the given `regex`. +pub fn name(field: SearchField, regex: Regex) -> Box { + Box::new(NameFilter(field, regex)) +} + +/// Construct a `PlayerFilter` that searches the character name with the given `regex`. +pub fn character(regex: Regex) -> Box { + name(SearchField::Character, regex) +} + +/// Construct a `PlayerFilter` that searches the account name with the given `regex`. +pub fn account(regex: Regex) -> Box { + name(SearchField::Account, regex) +} diff --git a/src/main.rs b/src/main.rs index 3164bd4..50dcf8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -266,8 +266,7 @@ fn single(opt: &Opt) -> Result<()> { let maybe_regex = Regex::new(line); if let Ok(rgx) = maybe_regex { let filter = filters::player::any( - filters::player::NameFilter::new(SearchField::Account, rgx.clone()) - | filters::player::NameFilter::new(SearchField::Character, rgx), + filters::player::account(rgx.clone()) | filters::player::character(rgx), ); return grep(opt, &*filter); } -- cgit v1.2.3