use std::{error::Error, fmt};
use dnspls_domain::DomainName;
use serde::{Deserialize, Serialize};
use crate::{FreshWindow, ObservationId, SourceId};
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Observation {
id: ObservationId,
domain: DomainName,
source: SourceId,
window: FreshWindow,
latency_ms: u32,
fact: EvidenceFact,
}
impl Observation {
pub const fn new(
id: ObservationId,
domain: DomainName,
source: SourceId,
window: FreshWindow,
latency_ms: u32,
fact: EvidenceFact,
) -> Self {
Self {
id,
domain,
source,
window,
latency_ms,
fact,
}
}
pub const fn id(&self) -> &ObservationId {
&self.id
}
pub const fn domain(&self) -> &DomainName {
&self.domain
}
pub const fn source(&self) -> &SourceId {
&self.source
}
pub const fn window(&self) -> FreshWindow {
self.window
}
pub const fn latency_ms(&self) -> u32 {
self.latency_ms
}
pub const fn fact(&self) -> &EvidenceFact {
&self.fact
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum EvidenceFact {
ZoneSnapshot {
membership: ZoneMembership,
},
Dns {
outcome: DnsOutcome,
dnssec: DnssecStatus,
},
Rdap {
outcome: RdapOutcome,
},
ProviderCheck {
operation: ProviderOperation,
authority: ProviderAuthority,
status: ProviderStatus,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ZoneMembership {
Present,
Absent,
TldUncovered,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DnsOutcome {
Delegated,
NameError,
NoData,
ServerFailure,
Timeout,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DnssecStatus {
Secure,
Insecure,
Bogus,
Indeterminate,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RdapOutcome {
ObjectFound,
ObjectNotFound,
RateLimited,
Unsupported,
Failed,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProviderOperation {
Availability,
Quote,
Register,
Aftermarket,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProviderAuthority {
Reported,
RegistrationCapable,
RegistryEpp,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProviderStatus {
Registrable,
RegistryPremium,
AftermarketFixed,
AftermarketOffer,
Auction,
Reserved,
Registered,
Unsupported,
Pending,
Unknown,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ObservationError {
DomainMismatch,
}
impl fmt::Display for ObservationError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("observation domain does not match the reduction domain")
}
}
impl Error for ObservationError {}