1use std::borrow::Cow;
2use std::net::IpAddr;
3use std::str::FromStr;
4
5use serde::{Deserialize, Serialize};
6
7use crate::common::{serialize_host_addrs_option, HostAddr, StringValue};
8use crate::Error;
9
10pub mod check;
11pub use check::DomainCheck;
12
13pub mod create;
14pub use create::DomainCreate;
15
16pub mod delete;
17pub use delete::DomainDelete;
18
19pub mod info;
20pub use info::DomainInfo;
21
22pub mod renew;
23pub use renew::DomainRenew;
24
25pub mod transfer;
26pub use transfer::DomainTransfer;
27
28pub mod update;
29pub use update::DomainUpdate;
30
31pub const XMLNS: &str = "urn:ietf:params:xml:ns:domain-1.0";
32
33#[derive(Serialize, Deserialize, Debug)]
35pub struct HostAttr<'a> {
36 #[serde(rename = "domain:hostName", alias = "hostName")]
38 pub name: StringValue<'a>,
39 #[serde(
41 rename = "domain:hostAddr",
42 alias = "hostAddr",
43 serialize_with = "serialize_host_addrs_option",
44 deserialize_with = "deserialize_host_addrs_option"
45 )]
46 pub addresses: Option<Vec<IpAddr>>,
47}
48
49fn deserialize_host_addrs_option<'de, D>(de: D) -> Result<Option<Vec<IpAddr>>, D::Error>
50where
51 D: serde::de::Deserializer<'de>,
52{
53 let addrs = Option::<Vec<HostAddr<'static>>>::deserialize(de)?;
54 let addrs = match addrs {
55 Some(addrs) => addrs,
56 None => return Ok(None),
57 };
58
59 let result = addrs
60 .into_iter()
61 .map(|addr| IpAddr::from_str(&addr.address))
62 .collect::<Result<_, _>>();
63
64 match result {
65 Ok(addrs) => Ok(Some(addrs)),
66 Err(e) => Err(serde::de::Error::custom(format!("{}", e))),
67 }
68}
69
70#[derive(Serialize, Debug)]
72pub struct HostAttrList<'a> {
73 #[serde(rename = "domain:hostAttr", alias = "hostAttr")]
75 pub hosts: &'a [HostAttr<'a>],
76}
77
78#[derive(Serialize, Debug)]
80pub struct HostObjList<'a> {
81 #[serde(rename = "domain:hostObj", alias = "hostObj")]
83 pub hosts: &'a [StringValue<'a>],
84}
85
86#[derive(Serialize, Debug)]
89#[serde(untagged)]
90pub enum HostList<'a> {
91 HostObjList(HostObjList<'a>),
92 HostAttrList(HostAttrList<'a>),
93}
94
95#[derive(Serialize, Deserialize, Debug)]
97pub struct DomainContact<'a> {
98 #[serde(rename = "$value")]
100 pub id: Cow<'a, str>,
101 #[serde(rename = "type")]
103 pub contact_type: Cow<'a, str>,
104}
105
106#[derive(Clone, Copy, Debug, Serialize)]
108pub struct Period {
109 unit: char,
111 #[serde(rename = "$value")]
113 length: u8,
114}
115
116impl Period {
117 pub fn years(length: u8) -> Result<Self, Error> {
118 Self::new(length, 'y')
119 }
120
121 pub fn months(length: u8) -> Result<Self, Error> {
122 Self::new(length, 'm')
123 }
124
125 fn new(length: u8, unit: char) -> Result<Self, Error> {
126 match length {
127 1..=99 => Ok(Period { length, unit }),
128 0 | 100.. => Err(Error::Other(
129 "Period length must be greater than 0 and less than 100".into(),
130 )),
131 }
132 }
133}
134
135pub const ONE_YEAR: Period = Period {
136 unit: 'y',
137 length: 1,
138};
139
140pub const TWO_YEARS: Period = Period {
141 unit: 'y',
142 length: 2,
143};
144
145pub const THREE_YEARS: Period = Period {
146 unit: 'y',
147 length: 3,
148};
149
150pub const ONE_MONTH: Period = Period {
151 unit: 'm',
152 length: 1,
153};
154
155pub const SIX_MONTHS: Period = Period {
156 unit: 'm',
157 length: 6,
158};
159
160#[derive(Serialize, Deserialize, Debug, Clone)]
162pub struct DomainAuthInfo<'a> {
163 #[serde(rename = "domain:pw", alias = "pw")]
165 pub password: StringValue<'a>,
166}
167
168impl<'a> DomainAuthInfo<'a> {
169 pub fn new(password: &'a str) -> Self {
171 Self {
172 password: password.into(),
173 }
174 }
175}