use std::borrow::Cow;
use std::net::IpAddr;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use crate::common::{serialize_host_addrs_option, HostAddr, StringValue};
use crate::Error;
pub mod check;
pub use check::DomainCheck;
pub mod create;
pub use create::DomainCreate;
pub mod delete;
pub use delete::DomainDelete;
pub mod info;
pub use info::DomainInfo;
pub mod renew;
pub use renew::DomainRenew;
pub mod transfer;
pub use transfer::DomainTransfer;
pub mod update;
pub use update::DomainUpdate;
pub const XMLNS: &str = "urn:ietf:params:xml:ns:domain-1.0";
#[derive(Serialize, Deserialize, Debug)]
pub struct HostAttr<'a> {
#[serde(rename = "domain:hostName", alias = "hostName")]
pub name: StringValue<'a>,
#[serde(
rename = "domain:hostAddr",
alias = "hostAddr",
serialize_with = "serialize_host_addrs_option",
deserialize_with = "deserialize_host_addrs_option"
)]
pub addresses: Option<Vec<IpAddr>>,
}
fn deserialize_host_addrs_option<'de, D>(de: D) -> Result<Option<Vec<IpAddr>>, D::Error>
where
D: serde::de::Deserializer<'de>,
{
let addrs = Option::<Vec<HostAddr<'static>>>::deserialize(de)?;
let addrs = match addrs {
Some(addrs) => addrs,
None => return Ok(None),
};
let result = addrs
.into_iter()
.map(|addr| IpAddr::from_str(&addr.address))
.collect::<Result<_, _>>();
match result {
Ok(addrs) => Ok(Some(addrs)),
Err(e) => Err(serde::de::Error::custom(format!("{}", e))),
}
}
#[derive(Serialize, Debug)]
pub struct HostAttrList<'a> {
#[serde(rename = "domain:hostAttr", alias = "hostAttr")]
pub hosts: &'a [HostAttr<'a>],
}
#[derive(Serialize, Debug)]
pub struct HostObjList<'a> {
#[serde(rename = "domain:hostObj", alias = "hostObj")]
pub hosts: &'a [StringValue<'a>],
}
#[derive(Serialize, Debug)]
#[serde(untagged)]
pub enum HostList<'a> {
HostObjList(HostObjList<'a>),
HostAttrList(HostAttrList<'a>),
}
#[derive(Serialize, Deserialize, Debug)]
pub struct DomainContact<'a> {
#[serde(rename = "$value")]
pub id: Cow<'a, str>,
#[serde(rename = "type")]
pub contact_type: Cow<'a, str>,
}
#[derive(Clone, Copy, Debug, Serialize)]
pub struct Period {
unit: char,
#[serde(rename = "$value")]
length: u8,
}
impl Period {
pub fn years(length: u8) -> Result<Self, Error> {
Self::new(length, 'y')
}
pub fn months(length: u8) -> Result<Self, Error> {
Self::new(length, 'm')
}
fn new(length: u8, unit: char) -> Result<Self, Error> {
match length {
1..=99 => Ok(Period { length, unit }),
0 | 100.. => Err(Error::Other(
"Period length must be greater than 0 and less than 100".into(),
)),
}
}
}
pub const ONE_YEAR: Period = Period {
unit: 'y',
length: 1,
};
pub const TWO_YEARS: Period = Period {
unit: 'y',
length: 2,
};
pub const THREE_YEARS: Period = Period {
unit: 'y',
length: 3,
};
pub const ONE_MONTH: Period = Period {
unit: 'm',
length: 1,
};
pub const SIX_MONTHS: Period = Period {
unit: 'm',
length: 6,
};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DomainAuthInfo<'a> {
#[serde(rename = "domain:pw", alias = "pw")]
pub password: StringValue<'a>,
}
impl<'a> DomainAuthInfo<'a> {
pub fn new(password: &'a str) -> Self {
Self {
password: password.into(),
}
}
}