1use {
2 crate::{
3 col_expr::*,
4 },
5 bet::*,
6 lfs_core::*,
7 std::{
8 str::FromStr,
9 },
10};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13enum BoolOperator {
14 And,
15 Or,
16 Not,
17}
18
19#[derive(Debug, Default, Clone)]
20pub struct Filter {
21 expr: BeTree<BoolOperator, ColExpr>,
22}
23
24impl Filter {
25 #[allow(clippy::match_like_matches_macro)]
26 pub fn eval(&self, mount: &Mount) -> Result<bool, EvalExprError> {
27 self.expr.eval_faillible(
28 |col_expr| col_expr.eval(mount),
30 |op, a, b| match (op, b) {
32 (BoolOperator::And, Some(b)) => Ok(a & b),
33 (BoolOperator::Or, Some(b)) => Ok(a | b),
34 (BoolOperator::Not, None) => Ok(!a),
35 _ => { unreachable!() }
36 },
37 |op, a| match (op, a) {
39 (BoolOperator::And, false) => true,
40 (BoolOperator::Or, true) => true,
41 _ => false,
42 },
43 ).map(|b| b.unwrap_or(true))
44 }
45 pub fn filter<'m>(&self, mounts: &'m[Mount]) -> Result<Vec<&'m Mount>, EvalExprError> {
46 let mut filtered = Vec::new();
47 for mount in mounts {
48 if self.eval(mount)? {
49 filtered.push(mount);
50 }
51 }
52 Ok(filtered)
53 }
54}
55
56impl FromStr for Filter {
57 type Err = ParseExprError;
58 fn from_str(input: &str) -> Result<Self, ParseExprError> {
59
60 let mut expr: BeTree<BoolOperator, String> = BeTree::new();
62 for c in input.chars() {
63 match c {
64 '&' => expr.push_operator(BoolOperator::And),
65 '|' => expr.push_operator(BoolOperator::Or),
66 '!' => expr.push_operator(BoolOperator::Not),
67 ' ' => {},
68 '(' => expr.open_par(),
69 ')' => expr.close_par(),
70 _ => expr.mutate_or_create_atom(String::new).push(c),
71 }
72 }
73
74 let expr = expr.try_map_atoms(|raw| raw.parse())?;
76
77 Ok(Self { expr })
78 }
79}
80
81