use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Certification {
pub standard: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub issuer: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub valid_until: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComplianceSection {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub jurisdictions: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub certifications: Vec<Certification>,
#[serde(skip_serializing_if = "Option::is_none")]
pub terms_of_service_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub privacy_policy_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data_handling_policy_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data_residency: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serde_round_trip() {
let comp = ComplianceSection {
jurisdictions: vec!["US".to_string()],
certifications: vec![Certification {
standard: "SOC2".to_string(),
issuer: Some("Vanta".to_string()),
valid_until: Some("2027-12-31".to_string()),
url: None,
}],
terms_of_service_url: Some("https://example.com/tos".to_string()),
privacy_policy_url: None,
data_handling_policy_url: None,
data_residency: Some("US".to_string()),
};
let json = serde_json::to_string(&comp).unwrap_or_default();
let parsed: ComplianceSection =
serde_json::from_str(&json).unwrap_or_else(|_| comp.clone());
assert_eq!(comp, parsed);
}
#[test]
fn empty_section_deserializes() {
let json = r#"{}"#;
let comp: Result<ComplianceSection, _> = serde_json::from_str(json);
assert!(comp.is_ok());
}
}