zescrow_core/condition/
threshold.rs

1use bincode::{Decode, Encode};
2#[cfg(feature = "json")]
3use serde::{Deserialize, Serialize};
4
5use super::Condition;
6
7/// Threshold condition: at least `threshold` subconditions must hold.
8#[cfg_attr(feature = "json", derive(Serialize, Deserialize))]
9#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
10pub struct Threshold {
11    /// Minimum number of valid subconditions required.
12    pub threshold: usize,
13
14    /// Subconditions to evaluate.
15    pub subconditions: Vec<Condition>,
16}
17
18impl Threshold {
19    /// Verify subconditions
20    pub fn verify(&self) -> Result<(), Error> {
21        // zero threshold always satisfied
22        if self.threshold == 0 {
23            return Ok(());
24        }
25
26        let satisfied = self
27            .subconditions
28            .iter()
29            .filter(|c| c.verify().is_ok())
30            .count();
31
32        if satisfied >= self.threshold {
33            Ok(())
34        } else {
35            Err(Error::ThresholdNotMet {
36                required: self.threshold,
37                satisfied,
38            })
39        }
40    }
41}
42
43/// Threshold conditions verification errors.
44#[derive(Debug, thiserror::Error)]
45pub enum Error {
46    /// Fewer than the required number of subconditions were satisfied.
47    #[error("needed at least {required} passes, but only {satisfied} succeeded")]
48    ThresholdNotMet {
49        /// Minimum number of valid subconditions required.
50        required: usize,
51        /// Number of verified subconditions.
52        satisfied: usize,
53    },
54}