#![allow(missing_docs)]
use super::{Citation, LocalizedText, PackageMetadata, ParameterValue, Selector, Source};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TargetGroup {
pub id: String,
pub name: LocalizedText,
pub description: Option<LocalizedText>,
pub selector: Selector,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct GroupApplicability {
pub groups: BTreeMap<String, TargetGroup>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RuleApplicability {
Selector(Selector),
Groups(GroupApplicability),
}
impl Default for RuleApplicability {
fn default() -> Self {
Self::Selector(Selector::All)
}
}
impl From<Selector> for RuleApplicability {
fn from(selector: Selector) -> Self {
Self::Selector(selector)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Requirement {
pub id: String,
pub statement: LocalizedText,
pub description: Option<LocalizedText>,
pub target_groups: Vec<String>,
#[serde(default)]
pub citations: Vec<Citation>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct ParameterCitation {
pub parameter_ids: Vec<String>,
pub citation: Citation,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct ExplanatoryImage {
pub id: String,
pub path: String,
pub media_type: String,
pub alternative_text: LocalizedText,
pub caption: Option<LocalizedText>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct RuleInstance {
pub id: String,
pub definition_id: String,
pub name: LocalizedText,
pub description: Option<LocalizedText>,
#[serde(default = "yes")]
pub enabled: bool,
#[serde(default = "severity")]
pub severity: Severity,
pub message: Option<LocalizedText>,
#[serde(default)]
pub parameters: BTreeMap<String, ParameterValue>,
#[serde(default)]
pub applicability: RuleApplicability,
#[serde(default)]
pub requirements: Vec<Requirement>,
#[serde(default)]
pub citations: Vec<Citation>,
#[serde(default)]
pub parameter_citations: Vec<ParameterCitation>,
#[serde(default)]
pub explanatory_images: Vec<ExplanatoryImage>,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub severity_bands: Vec<SeverityBand>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub severity_overrides: Vec<SeverityOverride>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub categories: Vec<CategoryLevel>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub gate: Option<RuleGate>,
#[serde(default, skip_serializing_if = "is_false")]
pub auxiliary: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct RuleGate {
pub rule: String,
pub condition: GateCondition,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum GateCondition {
AllIfPassed,
AllIfFailed,
PassedObjects,
FailedObjects,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CategoryLevel {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub property_set: Option<String>,
pub property: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub path: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SeverityOverride {
pub selector: Selector,
pub severity: Severity,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SeverityBand {
pub below: f64,
pub severity: Severity,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RuleFolder {
pub id: String,
pub name: LocalizedText,
pub description: Option<LocalizedText>,
#[serde(default)]
pub rules: Vec<RuleInstance>,
#[serde(default)]
pub folders: Vec<RuleFolder>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub gate: Option<RuleGate>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct RuleSetPackage {
pub schema_version: String,
pub package: PackageMetadata,
#[serde(default)]
pub sources: BTreeMap<String, Source>,
pub definition_packages: Vec<String>,
pub root: RuleFolder,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub classifications: BTreeMap<String, ClassificationDefinition>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct ClassificationDefinition {
pub id: String,
pub name: LocalizedText,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<LocalizedText>,
#[serde(default, skip_serializing_if = "ClassificationMode::is_first_match")]
pub mode: ClassificationMode,
pub rows: Vec<ClassificationRow>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct ClassificationRow {
pub selector: Selector,
pub class: String,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ClassificationMode {
#[default]
FirstMatch,
AllMatch,
}
impl ClassificationMode {
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_first_match(&self) -> bool {
matches!(self, Self::FirstMatch)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum Severity {
#[default]
Error,
Warning,
Info,
}
const fn yes() -> bool {
true
}
#[allow(clippy::trivially_copy_pass_by_ref)]
const fn is_false(value: &bool) -> bool {
!*value
}
fn severity() -> Severity {
Severity::Error
}