dcbor_pattern/pattern/value/
bool_pattern.rs

1use dcbor::prelude::*;
2
3use crate::pattern::{Matcher, Path, Pattern, vm::Instr};
4
5/// Pattern for matching boolean values in dCBOR.
6#[derive(Debug, Clone, Hash, Eq, PartialEq)]
7pub enum BoolPattern {
8    /// Matches any boolean value.
9    Any,
10    /// Matches the specific boolean value.
11    Value(bool),
12}
13
14impl BoolPattern {
15    /// Creates a new `BoolPattern` that matches any boolean value.
16    pub fn any() -> Self { BoolPattern::Any }
17
18    /// Creates a new `BoolPattern` that matches the specific boolean value.
19    pub fn value(value: bool) -> Self { BoolPattern::Value(value) }
20}
21
22impl Matcher for BoolPattern {
23    fn paths(&self, haystack: &CBOR) -> Vec<Path> {
24        let is_hit = haystack.as_bool().is_some_and(|value| match self {
25            BoolPattern::Any => true,
26            BoolPattern::Value(want) => value == *want,
27        });
28
29        if is_hit {
30            vec![vec![haystack.clone()]]
31        } else {
32            vec![]
33        }
34    }
35
36    fn compile(
37        &self,
38        code: &mut Vec<Instr>,
39        literals: &mut Vec<Pattern>,
40        _captures: &mut Vec<String>,
41    ) {
42        let idx = literals.len();
43        literals.push(Pattern::Value(crate::pattern::ValuePattern::Bool(
44            self.clone(),
45        )));
46        code.push(Instr::MatchPredicate(idx));
47    }
48}
49
50impl std::fmt::Display for BoolPattern {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        match self {
53            BoolPattern::Any => write!(f, "bool"),
54            BoolPattern::Value(true) => write!(f, "true"),
55            BoolPattern::Value(false) => write!(f, "false"),
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn test_bool_pattern_display() {
66        assert_eq!(BoolPattern::any().to_string(), "bool");
67        assert_eq!(BoolPattern::value(true).to_string(), "true");
68        assert_eq!(BoolPattern::value(false).to_string(), "false");
69    }
70
71    #[test]
72    fn test_bool_pattern_matching() {
73        let true_cbor = true.to_cbor();
74        let false_cbor = false.to_cbor();
75        let number_cbor = 42.to_cbor();
76
77        // Test Any pattern
78        let any_pattern = BoolPattern::any();
79        assert!(any_pattern.matches(&true_cbor));
80        assert!(any_pattern.matches(&false_cbor));
81        assert!(!any_pattern.matches(&number_cbor));
82
83        // Test specific value patterns
84        let true_pattern = BoolPattern::value(true);
85        assert!(true_pattern.matches(&true_cbor));
86        assert!(!true_pattern.matches(&false_cbor));
87        assert!(!true_pattern.matches(&number_cbor));
88
89        let false_pattern = BoolPattern::value(false);
90        assert!(!false_pattern.matches(&true_cbor));
91        assert!(false_pattern.matches(&false_cbor));
92        assert!(!false_pattern.matches(&number_cbor));
93    }
94
95    #[test]
96    fn test_bool_pattern_paths() {
97        let true_cbor = true.to_cbor();
98        let false_cbor = false.to_cbor();
99
100        let any_pattern = BoolPattern::any();
101        let true_paths = any_pattern.paths(&true_cbor);
102        assert_eq!(true_paths.len(), 1);
103        assert_eq!(true_paths[0].len(), 1);
104        assert_eq!(true_paths[0][0], true_cbor);
105
106        let false_paths = any_pattern.paths(&false_cbor);
107        assert_eq!(false_paths.len(), 1);
108        assert_eq!(false_paths[0].len(), 1);
109        assert_eq!(false_paths[0][0], false_cbor);
110
111        let true_pattern = BoolPattern::value(true);
112        let paths = true_pattern.paths(&false_cbor);
113        assert_eq!(paths.len(), 0);
114    }
115}