Use enum type to represent domain::Status

This commit is contained in:
Dirkjan Ochtman 2023-03-02 13:49:54 +01:00
parent 01a9b6ceb8
commit cd92b45156
4 changed files with 126 additions and 18 deletions

View File

@ -82,7 +82,7 @@ pub struct InfoData {
pub roid: String, pub roid: String,
/// The list of domain statuses /// The list of domain statuses
#[xml(rename = "status")] #[xml(rename = "status")]
pub statuses: Option<Vec<Status<'static>>>, pub statuses: Option<Vec<Status>>,
/// The domain registrant /// The domain registrant
pub registrant: Option<String>, pub registrant: Option<String>,
/// The list of domain contacts /// The list of domain contacts
@ -122,7 +122,7 @@ pub struct InfoData {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::DomainInfo; use super::DomainInfo;
use crate::domain::{HostInfo, HostObj}; use crate::domain::{HostInfo, HostObj, Status};
use crate::response::ResultCode; use crate::response::ResultCode;
use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID}; use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID};
use chrono::{TimeZone, Utc}; use chrono::{TimeZone, Utc};
@ -150,8 +150,8 @@ mod tests {
assert_eq!(object.result.message, SUCCESS_MSG); assert_eq!(object.result.message, SUCCESS_MSG);
assert_eq!(result.name, "eppdev-1.com"); assert_eq!(result.name, "eppdev-1.com");
assert_eq!(result.roid, "125899511_DOMAIN_COM-VRSN"); assert_eq!(result.roid, "125899511_DOMAIN_COM-VRSN");
assert_eq!(statuses[0].status, "ok".to_string()); assert_eq!(statuses[0], Status::Ok);
assert_eq!(statuses[1].status, "clientTransferProhibited".to_string()); assert_eq!(statuses[1], Status::ClientTransferProhibited);
assert_eq!(*registrant, "eppdev-contact-2"); assert_eq!(*registrant, "eppdev-contact-2");
assert_eq!(contacts[0].id, "eppdev-contact-2".to_string()); assert_eq!(contacts[0].id, "eppdev-contact-2".to_string());
assert_eq!(contacts[0].contact_type, "admin".to_string()); assert_eq!(contacts[0].contact_type, "admin".to_string());

View File

@ -224,10 +224,122 @@ impl<'a> DomainAuthInfo<'a> {
} }
/// The `<status>` type on contact transactions /// The `<status>` type on contact transactions
#[derive(Debug, FromXml, ToXml)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[xml(rename = "status", ns(XMLNS))] pub enum Status {
pub struct Status<'a> { ClientDeleteProhibited,
/// The status name, represented by the 's' attr on `<status>` tags ServerDeleteProhibited,
#[xml(attribute, rename = "s")] ClientHold,
pub status: Cow<'a, str>, ServerHold,
ClientRenewProhibited,
ServerRenewProhibited,
ClientTransferProhibited,
ServerTransferProhibited,
ClientUpdateProhibited,
ServerUpdateProhibited,
Inactive,
Ok,
PendingCreate,
PendingDelete,
PendingRenew,
PendingTransfer,
PendingUpdate,
}
impl Status {
pub fn as_str(&self) -> &'static str {
use Status::*;
match self {
ClientDeleteProhibited => "clientDeleteProhibited",
ServerDeleteProhibited => "serverDeleteProhibited",
ClientHold => "clientHold",
ServerHold => "serverHold",
ClientRenewProhibited => "clientRenewProhibited",
ServerRenewProhibited => "serverRenewProhibited",
ClientTransferProhibited => "clientTransferProhibited",
ServerTransferProhibited => "serverTransferProhibited",
ClientUpdateProhibited => "clientUpdateProhibited",
ServerUpdateProhibited => "serverUpdateProhibited",
Inactive => "inactive",
Ok => "ok",
PendingCreate => "pendingCreate",
PendingDelete => "pendingDelete",
PendingRenew => "pendingRenew",
PendingTransfer => "pendingTransfer",
PendingUpdate => "pendingUpdate",
}
}
}
impl ToXml for Status {
fn serialize<W: fmt::Write + ?Sized>(
&self,
_: Option<instant_xml::Id<'_>>,
serializer: &mut Serializer<W>,
) -> Result<(), instant_xml::Error> {
serializer.write_start("status", XMLNS)?;
serializer.write_attr("s", XMLNS, &self.as_str())?;
serializer.end_empty()
}
}
impl<'xml> FromXml<'xml> for Status {
fn matches(id: instant_xml::Id<'_>, _: Option<instant_xml::Id<'_>>) -> bool {
id == instant_xml::Id {
ns: XMLNS,
name: "status",
}
}
fn deserialize<'cx>(
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), instant_xml::Error> {
use instant_xml::de::Node;
use instant_xml::{Error, Id};
let node = match deserializer.next() {
Some(result) => result?,
None => return Err(Error::MissingValue(field)),
};
let attr = match node {
Node::Attribute(attr) => attr,
Node::Open(_) | Node::Text(_) => return Err(Error::MissingValue(field)),
node => return Err(Error::UnexpectedNode(format!("{node:?} in Status"))),
};
let id = deserializer.attribute_id(&attr)?;
let expected = Id { ns: "", name: "s" };
if id != expected {
return Err(Error::MissingValue(field));
}
*into = Some(match attr.value {
"clientDeleteProhibited" => Status::ClientDeleteProhibited,
"serverDeleteProhibited" => Status::ServerDeleteProhibited,
"clientHold" => Status::ClientHold,
"serverHold" => Status::ServerHold,
"clientRenewProhibited" => Status::ClientRenewProhibited,
"serverRenewProhibited" => Status::ServerRenewProhibited,
"clientTransferProhibited" => Status::ClientTransferProhibited,
"serverTransferProhibited" => Status::ServerTransferProhibited,
"clientUpdateProhibited" => Status::ClientUpdateProhibited,
"serverUpdateProhibited" => Status::ServerUpdateProhibited,
"inactive" => Status::Inactive,
"ok" => Status::Ok,
"pendingCreate" => Status::PendingCreate,
"pendingDelete" => Status::PendingDelete,
"pendingRenew" => Status::PendingRenew,
"pendingTransfer" => Status::PendingTransfer,
"pendingUpdate" => Status::PendingUpdate,
val => return Err(Error::UnexpectedValue(format!("invalid status {val:?}"))),
});
deserializer.ignore()?;
Ok(())
}
type Accumulator = Option<Status>;
const KIND: instant_xml::Kind = instant_xml::Kind::Element;
} }

View File

@ -63,7 +63,7 @@ pub struct DomainAdd<'a> {
/// The list of contacts to add to or remove from the domain /// The list of contacts to add to or remove from the domain
pub contacts: Option<&'a [DomainContact<'a>]>, pub contacts: Option<&'a [DomainContact<'a>]>,
/// The list of statuses to add to or remove from the domain /// The list of statuses to add to or remove from the domain
pub statuses: Option<&'a [Status<'a>]>, pub statuses: Option<&'a [Status]>,
} }
/// Type for elements under the `<add>` and `<rem>` tags for domain update /// Type for elements under the `<add>` and `<rem>` tags for domain update
@ -76,7 +76,7 @@ pub struct DomainRemove<'a> {
/// The list of contacts to add to or remove from the domain /// The list of contacts to add to or remove from the domain
pub contacts: Option<&'a [DomainContact<'a>]>, pub contacts: Option<&'a [DomainContact<'a>]>,
/// The list of statuses to add to or remove from the domain /// The list of statuses to add to or remove from the domain
pub statuses: Option<&'a [Status<'a>]>, pub statuses: Option<&'a [Status]>,
} }
/// Type for elements under the `<update>` tag for domain update /// Type for elements under the `<update>` tag for domain update
@ -116,14 +116,10 @@ mod tests {
fn command() { fn command() {
let mut object = DomainUpdate::new("eppdev.com"); let mut object = DomainUpdate::new("eppdev.com");
let statuses = &[Status {
status: "clientDeleteProhibited".into(),
}];
let add = DomainAdd { let add = DomainAdd {
ns: None, ns: None,
contacts: None, contacts: None,
statuses: Some(statuses), statuses: Some(&[Status::ClientDeleteProhibited]),
}; };
let contacts = &[DomainContact { let contacts = &[DomainContact {

View File

@ -5,7 +5,7 @@
<update xmlns="urn:ietf:params:xml:ns:domain-1.0"> <update xmlns="urn:ietf:params:xml:ns:domain-1.0">
<name>eppdev.com</name> <name>eppdev.com</name>
<add> <add>
<status s="clientDeleteProhibited"></status> <status s="clientDeleteProhibited" />
</add> </add>
<rem> <rem>
<contact type="billing">eppdev-contact-2</contact> <contact type="billing">eppdev-contact-2</contact>