use serde::{Deserialize, Serialize};
use crate::AeoError;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum EntityType {
Person,
Organization,
Product,
Place,
Concept,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum VerificationType {
Domain,
Dns,
Github,
Linkedin,
Gpg,
#[serde(rename = "well-known-uri")]
WellKnownUri,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Confidence {
#[default]
High,
Medium,
Low,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AuditMode {
None,
Signature,
Endpoint,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Entity {
pub id: String,
#[serde(rename = "type")]
pub entity_type: EntityType,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub aliases: Option<Vec<String>>,
pub canonical_url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Verification {
#[serde(rename = "type")]
pub verification_type: VerificationType,
pub value: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub proof_uri: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Authority {
pub primary_sources: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub evidence_links: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub verifications: Option<Vec<Verification>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Claim {
pub id: String,
pub predicate: String,
pub value: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub evidence: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub valid_from: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub valid_until: Option<Option<String>>,
#[serde(default)]
pub confidence: Confidence,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CitationPreferences {
#[serde(skip_serializing_if = "Option::is_none")]
pub preferred_attribution: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub canonical_links: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub do_not_cite: Option<Vec<String>>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AnswerConstraints {
#[serde(skip_serializing_if = "Option::is_none")]
pub must_include: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub must_not_include: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub freshness_window_days: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Audit {
pub mode: AuditMode,
#[serde(skip_serializing_if = "Option::is_none")]
pub signing_key_uri: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub endpoint_uri: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub endpoint_schema: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Document {
pub aeo_version: String,
pub entity: Entity,
pub authority: Authority,
pub claims: Vec<Claim>,
#[serde(skip_serializing_if = "Option::is_none")]
pub citation_preferences: Option<CitationPreferences>,
#[serde(skip_serializing_if = "Option::is_none")]
pub answer_constraints: Option<AnswerConstraints>,
#[serde(skip_serializing_if = "Option::is_none")]
pub audit: Option<Audit>,
}
impl Document {
pub fn from_json(raw: &str) -> Result<Self, AeoError> {
serde_json::from_str(raw).map_err(AeoError::Parse)
}
pub fn to_json(&self) -> Result<String, AeoError> {
serde_json::to_string_pretty(self).map_err(AeoError::Parse)
}
pub fn claim_ids(&self) -> Vec<&str> {
self.claims.iter().map(|c| c.id.as_str()).collect()
}
pub fn find_claim(&self, id: &str) -> Option<&Claim> {
self.claims.iter().find(|c| c.id == id)
}
}