summaryrefslogtreecommitdiffstats
path: root/cli/src/search.rs
blob: d388a8bf83f585fef9516f5b17e60b8adb1f5c81 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use chrono::{naive::NaiveDate, Duration};

use crate::transaction::{Category, Transaction};

pub struct Search<'t> {
    filtered: Vec<usize>,
    transactions: Vec<&'t Transaction>,
}

pub enum DateFilter {
    Absolute {
        start: Option<NaiveDate>,
        end: Option<NaiveDate>,
    },
    Relative {
        start: Option<Duration>,
        end: Option<Duration>,
    }
}

pub enum Constraint {
    Category(Category),
    Date(DateFilter),
}

impl Constraint {
    fn satisfies(&self, t: &Transaction) -> bool {
        match self {
            Constraint::Category(category) => category == &t.category,
            Constraint::Date(_) => todo!(),
        }
    }
}

impl<'t> Search<'t> {
    pub fn new(transactions: Vec<&'t Transaction>) -> Self {
        Self {
            filtered: std::iter::successors(Some(0_usize), |n| Some(n.checked_add(1).unwrap())).take(transactions.len()).collect(),
            transactions,
        }
    }

    pub fn get(&self) -> Vec<&'t Transaction> {
        self
            .filtered
            .iter()
            .map(|idx| self.transactions[*idx])
            .collect()
    }

    pub fn subtract(self, constraint: Constraint) -> Self {
        Self {
            filtered: self
                .filtered
                .iter()
                .copied()
                .filter(|idx| !constraint.satisfies(self.transactions[*idx]))
                .collect(),
            transactions: self.transactions,
        }
    }
}