selene_core/library/collection/
rules.rs1use serde::{Deserialize, Serialize};
2
3mod track_rules;
4pub use track_rules::*;
5
6mod album_rules;
7pub use album_rules::*;
8
9#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
10pub enum GroupOp {
11 Any,
12 All,
13}
14
15#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
16pub enum EqOp {
17 EqAny,
18 EqAll,
19 NeqAny,
20 NeqAll,
21}
22
23#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
24pub enum OrdOp {
25 Eq,
26 Neq,
27 Greater,
28 GreaterEq,
29 Lesser,
30 LesserEq,
31}
32
33pub trait Rule {
34 type Item;
35 fn matches(&self, item: &Self::Item) -> bool;
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct RuleGroup<R: Rule> {
40 pub rules: Vec<R>,
41 pub op: GroupOp,
42}
43
44impl<R: Rule> Default for RuleGroup<R> {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl<R: Rule> RuleGroup<R> {
51 #[must_use]
52 pub const fn new() -> Self {
53 Self {
54 rules: Vec::new(),
55 op: GroupOp::Any,
56 }
57 }
58
59 pub fn filter<'a>(&self, candidates: &'a [R::Item]) -> impl Iterator<Item = &'a R::Item> {
60 candidates.iter().filter(|c| {
61 if self.rules.is_empty() {
62 return true;
63 }
64
65 match self.op {
66 GroupOp::Any => self.rules.iter().any(|rule| rule.matches(c)),
67 GroupOp::All => self.rules.iter().all(|rule| rule.matches(c)),
68 }
69 })
70 }
71}
72
73pub(crate) fn eq_single<T: PartialEq>(item: &T, cmp: &[T], op: EqOp) -> bool {
74 match op {
75 EqOp::EqAny | EqOp::EqAll => cmp.contains(item),
76 EqOp::NeqAny => !cmp.contains(item),
77 EqOp::NeqAll => cmp.iter().any(|c| c != item),
78 }
79}
80
81pub(crate) fn eq_many<T: PartialEq>(values: &[T], cmp: &[T], op: EqOp) -> bool {
82 match op {
83 EqOp::EqAny => cmp.iter().any(|c| values.contains(c)),
84 EqOp::EqAll => cmp.iter().all(|c| values.contains(c)),
85 EqOp::NeqAny => cmp.iter().any(|c| !values.contains(c)),
86 EqOp::NeqAll => cmp.iter().all(|c| !values.contains(c)),
87 }
88}
89
90pub(crate) fn ord_single<T: PartialOrd>(value: T, cmp: T, op: OrdOp) -> bool {
91 match op {
92 OrdOp::Eq => value == cmp,
93 OrdOp::Neq => value != cmp,
94 OrdOp::Greater => value > cmp,
95 OrdOp::GreaterEq => value >= cmp,
96 OrdOp::Lesser => value < cmp,
97 OrdOp::LesserEq => value <= cmp,
98 }
99}