Skip to main content

allow_core/
lane_posture.rs

1use crate::{CargoAllowError, FindingKind};
2use std::collections::BTreeMap;
3use std::str::FromStr;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
6pub enum LaneEnforcementMode {
7    Advisory,
8    Shadow,
9    #[default]
10    Blocking,
11}
12
13impl LaneEnforcementMode {
14    pub const ALL: &[Self] = &[Self::Advisory, Self::Shadow, Self::Blocking];
15
16    pub fn as_str(self) -> &'static str {
17        match self {
18            Self::Advisory => "advisory",
19            Self::Shadow => "shadow",
20            Self::Blocking => "blocking",
21        }
22    }
23
24    pub fn blocks_check_failure(self) -> bool {
25        matches!(self, Self::Blocking)
26    }
27}
28
29impl FromStr for LaneEnforcementMode {
30    type Err = CargoAllowError;
31
32    fn from_str(value: &str) -> Result<Self, Self::Err> {
33        let trimmed = value.trim();
34        let normalized = trimmed.to_ascii_lowercase();
35        match normalized.as_str() {
36            "advisory" => Ok(Self::Advisory),
37            "shadow" => Ok(Self::Shadow),
38            "blocking" => Ok(Self::Blocking),
39            _ => Err(CargoAllowError::new(format!(
40                "unsupported lane enforcement mode `{trimmed}`; valid values: advisory, shadow, blocking"
41            ))),
42        }
43    }
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
47pub struct LaneConfig {
48    pub mode: LaneEnforcementMode,
49}
50
51pub fn lane_enforcement_mode_for_kind(
52    lanes: &BTreeMap<String, LaneConfig>,
53    kind: FindingKind,
54) -> LaneEnforcementMode {
55    lanes
56        .get(kind.as_str())
57        .map(|lane| lane.mode)
58        .unwrap_or(LaneEnforcementMode::Blocking)
59}
60
61pub fn effective_lane_posture_for_findings(
62    lanes: &BTreeMap<String, LaneConfig>,
63    kinds: impl IntoIterator<Item = FindingKind>,
64) -> BTreeMap<String, LaneEnforcementMode> {
65    let mut effective = lanes
66        .iter()
67        .map(|(name, lane)| (name.clone(), lane.mode))
68        .collect::<BTreeMap<_, _>>();
69    for kind in kinds {
70        effective
71            .entry(kind.as_str().to_string())
72            .or_insert(LaneEnforcementMode::Blocking);
73    }
74    effective
75}
76
77#[cfg(test)]
78#[path = "lane_posture_tests.rs"]
79mod tests;