use bincode::{Decode, Encode};
#[cfg(feature = "json")]
use serde::{Deserialize, Serialize};
use super::Condition;
#[cfg_attr(feature = "json", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
pub struct Threshold {
pub threshold: usize,
pub subconditions: Vec<Condition>,
}
impl Threshold {
pub fn verify(&self) -> Result<(), Error> {
match self.threshold {
0 => Err(Error::ZeroThreshold),
required if required > self.subconditions.len() => Err(Error::ThresholdUnsatisfiable {
required,
available: self.subconditions.len(),
}),
required => {
let satisfied = self.count_satisfied();
(satisfied >= required)
.then_some(())
.ok_or(Error::ThresholdNotMet {
required,
satisfied,
})
}
}
}
fn count_satisfied(&self) -> usize {
self.subconditions
.iter()
.filter_map(|c| c.verify().ok())
.count()
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("threshold must be greater than zero")]
ZeroThreshold,
#[error("threshold {required} exceeds the {available} subconditions available")]
ThresholdUnsatisfiable {
required: usize,
available: usize,
},
#[error("needed at least {required} passes, but only {satisfied} succeeded")]
ThresholdNotMet {
required: usize,
satisfied: usize,
},
}