domain_check_lib/types.rs
1//! Core data types for domain availability checking.
2//!
3//! This module defines all the main data structures used throughout the library,
4//! including domain results, configuration options, and output formatting.
5
6use serde::{Deserialize, Serialize};
7use std::time::Duration;
8
9/// Result of a domain availability check.
10///
11/// Contains all information about a domain's availability status,
12/// registration details, and metadata about the check itself.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct DomainResult {
15 /// The domain name that was checked (e.g., "example.com")
16 pub domain: String,
17
18 /// Whether the domain is available for registration.
19 /// - `Some(true)`: Domain is available
20 /// - `Some(false)`: Domain is taken/registered
21 /// - `None`: Status could not be determined
22 pub available: Option<bool>,
23
24 /// Detailed registration information (only available for taken domains)
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub info: Option<DomainInfo>,
27
28 /// How long the domain check took to complete
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub check_duration: Option<Duration>,
31
32 /// Which method was used to check the domain
33 pub method_used: CheckMethod,
34
35 /// Any error message if the check failed
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub error_message: Option<String>,
38}
39
40/// Detailed information about a registered domain.
41///
42/// This information is typically extracted from RDAP responses
43/// and provides insights into the domain's registration details.
44#[derive(Debug, Clone, Serialize, Deserialize, Default)]
45pub struct DomainInfo {
46 /// The registrar that manages this domain
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub registrar: Option<String>,
49
50 /// When the domain was first registered
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub creation_date: Option<String>,
53
54 /// When the domain registration expires
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub expiration_date: Option<String>,
57
58 /// Domain status codes (e.g., "clientTransferProhibited")
59 pub status: Vec<String>,
60
61 /// Last update date of the domain record
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub updated_date: Option<String>,
64
65 /// Nameservers associated with the domain
66 pub nameservers: Vec<String>,
67}
68
69/// Configuration options for domain checking operations.
70///
71/// This struct allows fine-tuning of the domain checking behavior,
72/// including performance, timeout, and protocol preferences.
73#[derive(Debug, Clone)]
74pub struct CheckConfig {
75 /// Maximum number of concurrent domain checks
76 /// Default: 10, Range: 1-100
77 pub concurrency: usize,
78
79 /// Timeout for each individual domain check
80 /// Default: 5 seconds
81 pub timeout: Duration,
82
83 /// Whether to automatically fall back to WHOIS when RDAP fails
84 /// Default: true
85 pub enable_whois_fallback: bool,
86
87 /// Whether to use IANA bootstrap registry for unknown TLDs
88 /// Default: false (uses built-in registry only)
89 pub enable_bootstrap: bool,
90
91 /// Whether to extract detailed domain information for taken domains
92 /// Default: false (just availability status)
93 pub detailed_info: bool,
94
95 /// List of TLDs to check for base domain names
96 /// If None, defaults to ["com"]
97 pub tlds: Option<Vec<String>>,
98
99 /// Custom timeout for RDAP requests (separate from overall timeout)
100 /// Default: 3 seconds
101 pub rdap_timeout: Duration,
102
103 /// Custom timeout for WHOIS requests
104 /// Default: 5 seconds
105 pub whois_timeout: Duration,
106}
107
108/// Method used to check domain availability.
109///
110/// This helps users understand which protocol was used
111/// and can be useful for debugging or performance analysis.
112#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
113pub enum CheckMethod {
114 /// Domain checked via RDAP protocol
115 #[serde(rename = "rdap")]
116 Rdap,
117
118 /// Domain checked via WHOIS protocol
119 #[serde(rename = "whois")]
120 Whois,
121
122 /// RDAP endpoint discovered via IANA bootstrap registry
123 #[serde(rename = "bootstrap")]
124 Bootstrap,
125
126 /// Check failed or method unknown
127 #[serde(rename = "unknown")]
128 Unknown,
129}
130
131/// Output mode for displaying results.
132///
133/// This controls how and when results are presented to the user,
134/// affecting both performance perception and data formatting.
135#[derive(Debug, Clone, PartialEq)]
136pub enum OutputMode {
137 /// Stream results as they become available (good for interactive use)
138 Streaming,
139
140 /// Collect all results before displaying (good for formatting/sorting)
141 Collected,
142
143 /// Automatically choose based on context (terminal vs pipe, etc.)
144 Auto,
145}
146
147impl Default for CheckConfig {
148 /// Create a sensible default configuration.
149 ///
150 /// These defaults are chosen to work well for most use cases
151 /// while being conservative about resource usage.
152 fn default() -> Self {
153 Self {
154 concurrency: 10,
155 timeout: Duration::from_secs(5),
156 enable_whois_fallback: true,
157 enable_bootstrap: false,
158 detailed_info: false,
159 tlds: None, // Will default to ["com"] when needed
160 rdap_timeout: Duration::from_secs(3),
161 whois_timeout: Duration::from_secs(5),
162 }
163 }
164}
165
166impl CheckConfig {
167 /// Create a new configuration with custom concurrency.
168 ///
169 /// Automatically caps concurrency at 100 to prevent resource exhaustion.
170 pub fn with_concurrency(mut self, concurrency: usize) -> Self {
171 self.concurrency = concurrency.clamp(1, 100);
172 self
173 }
174
175 /// Set custom timeout for domain checks.
176 pub fn with_timeout(mut self, timeout: Duration) -> Self {
177 self.timeout = timeout;
178 self
179 }
180
181 /// Enable or disable WHOIS fallback.
182 pub fn with_whois_fallback(mut self, enabled: bool) -> Self {
183 self.enable_whois_fallback = enabled;
184 self
185 }
186
187 /// Enable or disable IANA bootstrap registry.
188 pub fn with_bootstrap(mut self, enabled: bool) -> Self {
189 self.enable_bootstrap = enabled;
190 self
191 }
192
193 /// Enable detailed domain information extraction.
194 pub fn with_detailed_info(mut self, enabled: bool) -> Self {
195 self.detailed_info = enabled;
196 self
197 }
198
199 /// Set TLDs to check for base domain names.
200 pub fn with_tlds(mut self, tlds: Vec<String>) -> Self {
201 self.tlds = Some(tlds);
202 self
203 }
204}
205
206impl std::fmt::Display for CheckMethod {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 match self {
209 CheckMethod::Rdap => write!(f, "RDAP"),
210 CheckMethod::Whois => write!(f, "WHOIS"),
211 CheckMethod::Bootstrap => write!(f, "Bootstrap"),
212 CheckMethod::Unknown => write!(f, "Unknown"),
213 }
214 }
215}
216
217impl std::fmt::Display for OutputMode {
218 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
219 match self {
220 OutputMode::Streaming => write!(f, "Streaming"),
221 OutputMode::Collected => write!(f, "Collected"),
222 OutputMode::Auto => write!(f, "Auto"),
223 }
224 }
225}