use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Affiliation {
pub did: String,
pub relationship: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RelationshipsSection {
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_organization: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub affiliations: Vec<Affiliation>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub blocked_dids: Vec<String>,
}
pub mod relationship_types {
pub const MEMBER: &str = "member";
pub const PARTNER: &str = "partner";
pub const SUBSIDIARY: &str = "subsidiary";
pub const AFFILIATE: &str = "affiliate";
pub const DELEGATE: &str = "delegate";
pub const ADVISOR: &str = "advisor";
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serde_round_trip() {
let rels = RelationshipsSection {
parent_organization: Some("did:oas:prod:enr:acme".to_string()),
affiliations: vec![Affiliation {
did: "did:oas:prod:ao:team-alpha".to_string(),
relationship: relationship_types::MEMBER.to_string(),
label: Some("Team Alpha".to_string()),
}],
blocked_dids: vec!["did:oas:prod:agent:rogue-42".to_string()],
};
let json = serde_json::to_string(&rels).unwrap_or_default();
let parsed: RelationshipsSection =
serde_json::from_str(&json).unwrap_or_else(|_| rels.clone());
assert_eq!(rels, parsed);
}
#[test]
fn empty_section_deserializes() {
let json = r#"{}"#;
let rels: Result<RelationshipsSection, _> = serde_json::from_str(json);
assert!(rels.is_ok());
}
#[test]
fn optional_fields_omitted() {
let rels = RelationshipsSection {
parent_organization: None,
affiliations: vec![],
blocked_dids: vec![],
};
let json = serde_json::to_string(&rels).unwrap_or_default();
assert_eq!(json, "{}");
}
}