use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::edges::{
CoAuthorityItem, ConstrainItem, ExtendItem, Origin, ReferenceItem, RefineItem, SupersedeItem,
};
use crate::frontmatter::{Implementation, Risk, Status};
use crate::unit::Unit;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Registry {
pub spec_version: String,
pub build: Build,
pub specs: Vec<SpecRecord>,
pub validation: ValidationReport,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Build {
pub compiler_id: String,
pub compiler_version: String,
pub input_root: String,
pub content_hash: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SpecRecord {
pub id: String,
pub title: String,
pub status: Status,
pub created: String,
pub summary: String,
pub spec_path: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub authors: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub owner: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub risk: Option<Risk>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub implementation: Option<Implementation>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub depends_on: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub code_aliases: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub feature_branch: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub section_headings: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub establishes: Vec<Unit>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extends: Vec<ExtendItem>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub refines: Vec<RefineItem>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub supersedes: Vec<SupersedeItem>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub amends: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub co_authority: Vec<CoAuthorityItem>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub constrains: Vec<ConstrainItem>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub references: Vec<ReferenceItem>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub superseded_by: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub retirement_rationale: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub amends_sections: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub unamendable: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub amendment_record: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub origin: Option<Origin>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub extra_frontmatter: BTreeMap<String, serde_json::Value>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RegistrySpecShard {
pub spec_version: String,
pub shard_hash: String,
pub record: SpecRecord,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub local_violations: Vec<Violation>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BuildMeta {
pub schema_version: String,
pub built_at: String,
pub compiler_id: String,
pub compiler_version: String,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
Error,
Warning,
Info,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Violation {
pub code: String,
pub severity: Severity,
pub message: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ValidationReport {
pub passed: bool,
#[serde(default)]
pub violations: Vec<Violation>,
}
impl ValidationReport {
pub fn from_violations(violations: Vec<Violation>) -> Self {
let passed = !violations.iter().any(|v| v.severity == Severity::Error);
ValidationReport { passed, violations }
}
}