use seer_core::output::{get_formatter, OutputFormat};
#[derive(Debug, Clone)]
pub enum Payload {
Overview(Box<seer_core::LookupResult>),
Whois(Box<seer_core::WhoisResponse>),
Rdap(Box<seer_core::RdapResponse>),
Dns(Vec<seer_core::DnsRecord>),
Ssl(Box<seer_core::SslReport>),
Status(Box<seer_core::StatusResponse>),
Prop(Box<seer_core::PropagationResult>),
Reverse(Vec<seer_core::DnsRecord>),
Avail(Box<seer_core::AvailabilityResult>),
Tld(Box<seer_core::TldInfo>),
Dnssec(Box<seer_core::DnssecReport>),
Compare(Box<seer_core::DnsComparison>),
Diff(Box<seer_core::DomainDiff>),
Watch(Box<seer_core::WatchReport>),
History(Vec<seer_core::HistoryEntry>),
Subdomains(Box<seer_core::SubdomainResult>),
Info(Box<seer_core::DomainInfo>),
Drift(Box<seer_core::DriftReport>),
Posture(Box<seer_core::EmailPosture>),
Caa(Box<seer_core::CaaPolicy>),
Confusables(Box<seer_core::ConfusableReport>),
}
impl Payload {
pub fn kind(&self) -> &'static str {
match self {
Payload::Overview(_) => "lookup",
Payload::Whois(_) => "whois",
Payload::Rdap(_) => "rdap",
Payload::Dns(_) => "dns",
Payload::Ssl(_) => "ssl",
Payload::Status(_) => "status",
Payload::Prop(_) => "propagation",
Payload::Reverse(_) => "reverse",
Payload::Avail(_) => "availability",
Payload::Tld(_) => "tld",
Payload::Dnssec(_) => "dnssec",
Payload::Compare(_) => "compare",
Payload::Diff(_) => "diff",
Payload::Watch(_) => "watch",
Payload::History(_) => "history",
Payload::Subdomains(_) => "subdomains",
Payload::Info(_) => "info",
Payload::Drift(_) => "drift",
Payload::Posture(_) => "posture",
Payload::Caa(_) => "caa",
Payload::Confusables(_) => "confusables",
}
}
}
pub fn serialize(data: &Payload, format: OutputFormat) -> String {
let fmt = get_formatter(format);
match data {
Payload::Overview(r) => fmt.format_lookup(r),
Payload::Whois(w) => fmt.format_whois(w),
Payload::Rdap(r) => fmt.format_rdap(r),
Payload::Dns(records) => fmt.format_dns(records),
Payload::Ssl(s) => fmt.format_ssl(s),
Payload::Status(s) => fmt.format_status(s),
Payload::Prop(p) => fmt.format_propagation(p),
Payload::Reverse(records) => fmt.format_dns(records),
Payload::Avail(a) => fmt.format_availability(a),
Payload::Tld(t) => fmt.format_tld(t),
Payload::Dnssec(r) => fmt.format_dnssec(r),
Payload::Compare(c) => fmt.format_dns_comparison(c),
Payload::Diff(d) => fmt.format_diff(d),
Payload::Watch(w) => fmt.format_watch(w),
Payload::History(_) => "history (raw view not applicable)".to_string(),
Payload::Subdomains(s) => fmt.format_subdomains(s),
Payload::Info(i) => fmt.format_domain_info(i),
Payload::Drift(d) => fmt.format_drift(d),
Payload::Posture(p) => fmt.format_posture(p),
Payload::Caa(c) => fmt.format_caa(c),
Payload::Confusables(c) => fmt.format_confusables(c),
}
}
#[cfg(test)]
mod tests {
use super::*;
use seer_core::dns::{RecordData, RecordType};
use seer_core::DnsRecord;
#[test]
fn serializes_dns_as_json() {
let data = Payload::Dns(vec![DnsRecord {
name: "example.com".into(),
record_type: RecordType::A,
ttl: 300,
data: RecordData::A {
address: "1.2.3.4".into(),
},
}]);
let out = serialize(&data, OutputFormat::Json);
assert!(out.contains("1.2.3.4"));
assert!(out.trim_start().starts_with('['));
}
#[test]
fn serializes_dns_as_markdown() {
let data = Payload::Dns(vec![DnsRecord {
name: "example.com".into(),
record_type: RecordType::A,
ttl: 300,
data: RecordData::A {
address: "1.2.3.4".into(),
},
}]);
let out = serialize(&data, OutputFormat::Markdown);
assert!(out.contains("1.2.3.4"));
assert!(
out.contains('#') || out.contains('|'),
"expected markdown structure"
);
}
#[test]
fn serializes_new_caa_variant() {
let policy = seer_core::CaaPolicy {
records: vec![],
effective_domain: None,
has_policy: false,
issuer_match: None,
iodef: vec![],
wildcard_note: None,
note: "no CAA policy found".into(),
};
let data = Payload::Caa(Box::new(policy));
let out = serialize(&data, OutputFormat::Markdown);
assert!(!out.is_empty());
}
#[test]
fn kind_labels_are_lowercase() {
let data = Payload::Dns(vec![]);
assert_eq!(data.kind(), "dns");
}
}