Coverage Report

Created: 2024-02-20 21:15

/builds/xfbs/cindy/common/src/tag/predicate.rs
Line
Count
Source (jump to first uncovered line)
1
use super::*;
2
use std::{
3
    fmt::{Display, Formatter, Result as FmtResult},
4
    str::FromStr,
5
};
6
7
382
#[derive(Clone, 
D342
ebu
g342
,
P8
artialE
q8
, Eq,
P0
artialOr
d0
,
O0
r
d0
,
H0
as
h0
)]
8
pub enum TagPredicate<'a> {
9
    Exists(TagFilter<'a>),
10
    Missing(TagFilter<'a>),
11
}
12
13
impl<'a> TagPredicate<'a> {
14
2
    pub fn exists(&self) -> bool {
15
2
        
matches!1
(self, TagPredicate::Exists(_))
16
2
    }
17
18
0
    pub fn matches(&mut self, tags: &[Tag]) -> bool {
19
0
        match self {
20
0
            Self::Exists(filter) => tags.iter().any(|tag| filter.matches(tag)),
21
0
            Self::Missing(filter) => tags.iter().all(|tag| !filter.matches(tag)),
22
        }
23
0
    }
24
25
4.80k
    pub fn filter(&self) -> &TagFilter<'a> {
26
4.80k
        match self {
27
4.80k
            Self::Exists(filter) => filter,
28
5
            Self::Missing(filter) => filter,
29
        }
30
4.80k
    }
31
}
32
33
impl FromStr for TagPredicate<'static> {
34
    type Err = ParseError;
35
36
11
    fn from_str(input: &str) -> Result<Self, Self::Err> {
37
11
        match input.starts_with('!') {
38
7
            false => input.parse().map(TagPredicate::Exists),
39
4
            true => input
40
4
                .trim_start_matches('!')
41
4
                .parse()
42
4
                .map(TagPredicate::Missing),
43
        }
44
11
    }
45
}
46
47
1
#[test]
48
1
fn path_predicate_from_str() {
49
1
    assert_eq!(
50
1
        TagPredicate::from_str("tag:value").unwrap(),
51
1
        TagPredicate::Exists(TagFilter::new(Some("tag"), Some("value")))
52
1
    );
53
1
    assert_eq!(
54
1
        TagPredicate::from_str("*:value").unwrap(),
55
1
        TagPredicate::Exists(TagFilter::new(None, Some("value")))
56
1
    );
57
1
    assert_eq!(
58
1
        TagPredicate::from_str("name:*").unwrap(),
59
1
        TagPredicate::Exists(TagFilter::new(Some("name"), None))
60
1
    );
61
62
1
    assert_eq!(
63
1
        TagPredicate::from_str("!tag:value").unwrap(),
64
1
        TagPredicate::Missing(TagFilter::new(Some("tag"), Some("value")))
65
1
    );
66
1
    assert_eq!(
67
1
        TagPredicate::from_str("!*:value").unwrap(),
68
1
        TagPredicate::Missing(TagFilter::new(None, Some("value")))
69
1
    );
70
1
    assert_eq!(
71
1
        TagPredicate::from_str("!name:*").unwrap(),
72
1
        TagPredicate::Missing(TagFilter::new(Some("name"), None))
73
1
    );
74
1
}
75
76
impl<'a> Display for TagPredicate<'a> {
77
2
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
78
2
        let prefix = match self {
79
2
            Self::Exists(_) => "",
80
0
            Self::Missing(_) => "!",
81
        };
82
2
        let filter = self.filter();
83
2
        write!(f, "{prefix}{filter}")
84
2
    }
85
}
86
87
#[cfg(test)]
88
mod tests {
89
    use super::*;
90
91
1
    #[test]
92
1
    fn tag_predicate_filter() {
93
1
        let filter = TagFilter::new(Some("object"), None);
94
1
95
1
        let predicate = TagPredicate::Missing(filter.clone());
96
1
        assert_eq!(predicate.filter(), &filter);
97
1
        assert_eq!(predicate.exists(), false);
98
99
1
        let predicate = TagPredicate::Exists(filter.clone());
100
1
        assert_eq!(predicate.filter(), &filter);
101
1
        assert_eq!(predicate.exists(), true);
102
1
    }
103
}