Skip to main content

rdap_types/
common.rs

1//! Shared RDAP data types used across all response objects.
2//!
3//! Follows RFC 9083 §4 (Common Data Structures).
4
5use serde::{Deserialize, Serialize};
6
7// ── Status values (RFC 9083 §10.2.2) ─────────────────────────────────────────
8
9/// Registration status values defined in RFC 9083 §10.2.2.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub enum RdapStatus {
13    Validated,
14    #[serde(rename = "renew prohibited")]
15    RenewProhibited,
16    #[serde(rename = "update prohibited")]
17    UpdateProhibited,
18    #[serde(rename = "transfer prohibited")]
19    TransferProhibited,
20    #[serde(rename = "delete prohibited")]
21    DeleteProhibited,
22    Proxy,
23    Private,
24    Removed,
25    Obscured,
26    Associated,
27    Active,
28    Inactive,
29    Locked,
30    #[serde(rename = "pending create")]
31    PendingCreate,
32    #[serde(rename = "pending renew")]
33    PendingRenew,
34    #[serde(rename = "pending transfer")]
35    PendingTransfer,
36    #[serde(rename = "pending update")]
37    PendingUpdate,
38    #[serde(rename = "pending delete")]
39    PendingDelete,
40    /// Unknown/extension status value — preserved as-is.
41    #[serde(untagged)]
42    Other(String),
43}
44
45// ── Role types (RFC 9083 §10.2.4) ────────────────────────────────────────────
46
47/// Entity role values defined in RFC 9083 §10.2.4.
48#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase")]
50pub enum RdapRole {
51    Registrant,
52    Technical,
53    Administrative,
54    Abuse,
55    Billing,
56    Registrar,
57    Reseller,
58    Sponsor,
59    Proxy,
60    Notifications,
61    Noc,
62    /// Unknown/extension role — preserved as-is.
63    #[serde(untagged)]
64    Other(String),
65}
66
67// ── Event (RFC 9083 §4.5) ─────────────────────────────────────────────────────
68
69/// A lifecycle event associated with a registration object.
70#[derive(Debug, Clone, Serialize, Deserialize)]
71#[serde(rename_all = "camelCase")]
72pub struct RdapEvent {
73    /// Type of event (e.g. "registration", "expiration").
74    pub event_action: String,
75    /// RFC 3339 timestamp.
76    pub event_date: String,
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub event_actor: Option<String>,
79}
80
81// ── Link (RFC 9083 §4.2) ──────────────────────────────────────────────────────
82
83/// A hyperlink associated with a registration object.
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct RdapLink {
86    pub href: String,
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub rel: Option<String>,
89    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
90    pub media_type: Option<String>,
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub title: Option<String>,
93}
94
95// ── Remark (RFC 9083 §4.3) ────────────────────────────────────────────────────
96
97/// A remark (annotation) on a registration object.
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct RdapRemark {
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub title: Option<String>,
102    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
103    pub remark_type: Option<String>,
104    pub description: Vec<String>,
105    #[serde(default, skip_serializing_if = "Vec::is_empty")]
106    pub links: Vec<RdapLink>,
107}
108
109// ── Entity (RFC 9083 §5.1) ────────────────────────────────────────────────────
110
111/// A contact / registrant / registrar embedded in a response.
112#[derive(Debug, Clone, Serialize, Deserialize)]
113#[serde(rename_all = "camelCase")]
114pub struct RdapEntity {
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub handle: Option<String>,
117    /// vCard data (RFC 7095) — kept as raw JSON value to avoid strict parsing.
118    #[serde(skip_serializing_if = "Option::is_none")]
119    pub vcard_array: Option<serde_json::Value>,
120    #[serde(default, skip_serializing_if = "Vec::is_empty")]
121    pub roles: Vec<RdapRole>,
122    #[serde(default, skip_serializing_if = "Vec::is_empty")]
123    pub events: Vec<RdapEvent>,
124    #[serde(default, skip_serializing_if = "Vec::is_empty")]
125    pub links: Vec<RdapLink>,
126    #[serde(default, skip_serializing_if = "Vec::is_empty")]
127    pub remarks: Vec<RdapRemark>,
128    /// Nested entities (e.g., technical contacts of a registrar).
129    #[serde(default, skip_serializing_if = "Vec::is_empty")]
130    pub entities: Vec<RdapEntity>,
131}
132
133// ── Response metadata ─────────────────────────────────────────────────────────
134
135/// Metadata attached to every normalised response.
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct ResponseMeta {
138    /// The RDAP server base URL that served this response.
139    pub source: String,
140    /// RFC 3339 timestamp of when the query was made.
141    pub queried_at: String,
142    /// Whether the response was served from the local cache.
143    pub cached: bool,
144}