//! Common data types included in EPP Requests and Responses use std::ops::Deref; use std::{borrow::Cow, fmt::Display, net::IpAddr}; use serde::ser::SerializeSeq; use serde::{Deserialize, Serialize}; use crate::request::Extension; pub(crate) const EPP_XMLNS: &str = "urn:ietf:params:xml:ns:epp-1.0"; /// Wraps String for easier serialization to and from values that are inner text /// for tags rather than attributes #[derive(Default, Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct StringValue<'a>(Cow<'a, str>); impl Deref for StringValue<'_> { type Target = str; fn deref(&self) -> &Self::Target { self.0.as_ref() } } impl<'a> AsRef for StringValue<'a> { fn as_ref(&self) -> &str { self.0.as_ref() } } impl Display for StringValue<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl<'a> From<&'a str> for StringValue<'a> { fn from(s: &'a str) -> Self { Self(s.into()) } } impl From for StringValue<'static> { fn from(s: String) -> Self { Self(s.into()) } } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] /// An empty placeholder tag. To be refactored to something more compliant later. pub struct NoExtension; impl Extension for NoExtension { type Response = NoExtension; } /// Type that represents the <name> tag for host check response #[derive(Deserialize, Debug)] struct Available { /// The resource name #[serde(rename = "$value")] pub id: StringValue<'static>, /// The resource (un)availability #[serde(rename = "avail")] pub available: bool, } /// Type that represents the <cd> tag for domain check response #[derive(Deserialize, Debug)] struct CheckResponseDataItem { /// Data under the <name> tag #[serde(rename = "name", alias = "id")] pub resource: Available, /// The reason for (un)availability pub reason: Option>, } /// Type that represents the <chkData> tag for host check response #[derive(Deserialize, Debug)] struct CheckData { /// Data under the <cd> tag #[serde(rename = "cd")] pub list: Vec, } /// Type that represents the <resData> tag for host check response #[derive(Deserialize, Debug)] struct DeserializedCheckResponse { /// Data under the <chkData> tag #[serde(rename = "chkData")] pub check_data: CheckData, } #[derive(Debug)] pub struct Checked { pub id: String, pub available: bool, pub reason: Option, } #[derive(Deserialize, Debug)] #[serde(from = "DeserializedCheckResponse")] pub struct CheckResponse { pub list: Vec, } impl From for CheckResponse { fn from(rsp: DeserializedCheckResponse) -> Self { Self { list: rsp .check_data .list .into_iter() .map(|item| Checked { id: item.resource.id.0.into_owned(), available: item.resource.available, reason: item.reason.map(|r| r.0.into_owned()), }) .collect(), } } } /// The