Skip to main content

confium_attributes/
ast.rs

1//! Predicate AST.
2
3// Note: serde derive removed due to infinite recursion in derive macro
4// caused by the recursive Predicate type (And/Or/Not contain Predicate).
5// DSL parser + manual serializers handle persistence.
6
7/// A predicate over signer attributes.
8#[derive(Debug, Clone)]
9#[allow(clippy::large_enum_variant)]
10pub enum Predicate {
11    /// At least `count` signers must have `attribute`.
12    MinCount {
13        /// Attribute name (e.g., "role:director").
14        attribute: String,
15        /// Required count.
16        count: usize,
17    },
18    /// At least `count` distinct values of `attribute` must appear.
19    MinDistinct {
20        /// Attribute name.
21        attribute: String,
22        /// Required distinct-value count.
23        count: usize,
24    },
25    /// No signer has `attribute`.
26    None {
27        /// Attribute that no signer must have.
28        attribute: String,
29    },
30    /// At least one signer has `attribute`.
31    Any {
32        /// Attribute that at least one signer must have.
33        attribute: String,
34    },
35    /// All signers have `attribute`.
36    All {
37        /// Attribute that every signer must have.
38        attribute: String,
39    },
40    /// Conjunction of sub-predicates.
41    And(Vec<Predicate>),
42    /// Disjunction of sub-predicates.
43    Or(Vec<Predicate>),
44    /// Negation of a sub-predicate.
45    Not(Box<Predicate>),
46}
47
48/// A wrapper for type-safe construction.
49#[derive(Debug, Clone)]
50pub struct AttributePredicate(pub Predicate);
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn predicate_constructs() {
58        let p = Predicate::And(vec![
59            Predicate::MinCount {
60                attribute: "role:director".into(),
61                count: 5,
62            },
63            Predicate::MinDistinct {
64                attribute: "region".into(),
65                count: 3,
66            },
67        ]);
68        // Just verify the API compiles
69        let AttributePredicate(_) = AttributePredicate(p.clone());
70        match p {
71            Predicate::And(inner) => assert_eq!(inner.len(), 2),
72            _ => panic!("wrong variant"),
73        }
74    }
75}