#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct ToolRiskProfile {
pub untrusted_input: bool,
pub sensitive_access: bool,
pub state_changing: bool,
}
impl ToolRiskProfile {
pub const fn empty() -> Self {
Self {
untrusted_input: false,
sensitive_access: false,
state_changing: false,
}
}
pub fn count_armed(&self) -> usize {
usize::from(self.untrusted_input)
+ usize::from(self.sensitive_access)
+ usize::from(self.state_changing)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_profile_arms_nothing() {
let p = ToolRiskProfile::empty();
assert_eq!(p, ToolRiskProfile::default());
assert_eq!(p.count_armed(), 0);
}
#[test]
fn count_armed_covers_all_eight_combinations() {
for bits in 0..8u8 {
let p = ToolRiskProfile {
untrusted_input: bits & 0b001 != 0,
sensitive_access: bits & 0b010 != 0,
state_changing: bits & 0b100 != 0,
};
assert_eq!(p.count_armed(), bits.count_ones() as usize);
}
}
#[test]
fn all_true_is_rule_of_two_trip() {
let p = ToolRiskProfile {
untrusted_input: true,
sensitive_access: true,
state_changing: true,
};
assert_eq!(p.count_armed(), 3);
}
}