allow_core/
lane_posture.rs1use 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 match value.trim() {
34 "advisory" => Ok(Self::Advisory),
35 "shadow" => Ok(Self::Shadow),
36 "blocking" => Ok(Self::Blocking),
37 other => Err(CargoAllowError::new(format!(
38 "unsupported lane enforcement mode `{other}`"
39 ))),
40 }
41 }
42}
43
44#[derive(Debug, Clone, PartialEq, Eq)]
45pub struct LaneConfig {
46 pub mode: LaneEnforcementMode,
47}
48
49pub fn lane_enforcement_mode_for_kind(
50 lanes: &BTreeMap<String, LaneConfig>,
51 kind: FindingKind,
52) -> LaneEnforcementMode {
53 lanes
54 .get(kind.as_str())
55 .map(|lane| lane.mode)
56 .unwrap_or(LaneEnforcementMode::Blocking)
57}
58
59pub fn effective_lane_posture_for_findings(
60 lanes: &BTreeMap<String, LaneConfig>,
61 kinds: impl IntoIterator<Item = FindingKind>,
62) -> BTreeMap<String, LaneEnforcementMode> {
63 let mut effective = lanes
64 .iter()
65 .map(|(name, lane)| (name.clone(), lane.mode))
66 .collect::<BTreeMap<_, _>>();
67 for kind in kinds {
68 effective
69 .entry(kind.as_str().to_string())
70 .or_insert(LaneEnforcementMode::Blocking);
71 }
72 effective
73}
74
75#[cfg(test)]
76#[path = "lane_posture_tests.rs"]
77mod tests;