use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PolicyStatus {
Pass,
Warn,
Fail,
}
impl PolicyStatus {
#[must_use]
pub fn label(self) -> &'static str {
match self {
Self::Pass => "PASS",
Self::Warn => "WARN",
Self::Fail => "FAIL",
}
}
#[must_use]
pub fn max(self, other: Self) -> Self {
self.max_rank(other)
}
fn rank(self) -> u8 {
match self {
Self::Pass => 0,
Self::Warn => 1,
Self::Fail => 2,
}
}
fn max_rank(self, other: Self) -> Self {
if self.rank() >= other.rank() {
self
} else {
other
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
Info,
Warning,
Error,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PolicyResult {
pub policy_id: String,
pub status: PolicyStatus,
pub severity: Severity,
#[serde(skip_serializing_if = "Option::is_none")]
pub actual: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expected: Option<f64>,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub remediation: Option<String>,
}
impl PolicyResult {
#[must_use]
pub fn pass(policy_id: impl Into<String>, message: impl Into<String>) -> Self {
Self {
policy_id: policy_id.into(),
status: PolicyStatus::Pass,
severity: Severity::Info,
actual: None,
expected: None,
message: message.into(),
remediation: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn status_max_picks_worst() {
assert_eq!(
PolicyStatus::Pass.max(PolicyStatus::Fail),
PolicyStatus::Fail
);
assert_eq!(
PolicyStatus::Warn.max(PolicyStatus::Pass),
PolicyStatus::Warn
);
}
}