diff --git a/src/domain/info.rs b/src/domain/info.rs index 1bcb7a3..1bbf07e 100644 --- a/src/domain/info.rs +++ b/src/domain/info.rs @@ -82,7 +82,7 @@ pub struct InfoData { pub roid: String, /// The list of domain statuses #[xml(rename = "status")] - pub statuses: Option>>, + pub statuses: Option>, /// The domain registrant pub registrant: Option, /// The list of domain contacts @@ -122,7 +122,7 @@ pub struct InfoData { #[cfg(test)] mod tests { use super::DomainInfo; - use crate::domain::{HostInfo, HostObj}; + use crate::domain::{HostInfo, HostObj, Status}; use crate::response::ResultCode; use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID}; use chrono::{TimeZone, Utc}; @@ -150,8 +150,8 @@ mod tests { assert_eq!(object.result.message, SUCCESS_MSG); assert_eq!(result.name, "eppdev-1.com"); assert_eq!(result.roid, "125899511_DOMAIN_COM-VRSN"); - assert_eq!(statuses[0].status, "ok".to_string()); - assert_eq!(statuses[1].status, "clientTransferProhibited".to_string()); + assert_eq!(statuses[0], Status::Ok); + assert_eq!(statuses[1], Status::ClientTransferProhibited); assert_eq!(*registrant, "eppdev-contact-2"); assert_eq!(contacts[0].id, "eppdev-contact-2".to_string()); assert_eq!(contacts[0].contact_type, "admin".to_string()); diff --git a/src/domain/mod.rs b/src/domain/mod.rs index 6461fab..d553307 100644 --- a/src/domain/mod.rs +++ b/src/domain/mod.rs @@ -224,10 +224,122 @@ impl<'a> DomainAuthInfo<'a> { } /// The `` type on contact transactions -#[derive(Debug, FromXml, ToXml)] -#[xml(rename = "status", ns(XMLNS))] -pub struct Status<'a> { - /// The status name, represented by the 's' attr on `` tags - #[xml(attribute, rename = "s")] - pub status: Cow<'a, str>, +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum Status { + ClientDeleteProhibited, + ServerDeleteProhibited, + ClientHold, + 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( + &self, + _: Option>, + serializer: &mut Serializer, + ) -> 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>) -> 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; + const KIND: instant_xml::Kind = instant_xml::Kind::Element; } diff --git a/src/domain/update.rs b/src/domain/update.rs index b452125..03a32ff 100644 --- a/src/domain/update.rs +++ b/src/domain/update.rs @@ -63,7 +63,7 @@ pub struct DomainAdd<'a> { /// The list of contacts to add to or remove from the domain pub contacts: Option<&'a [DomainContact<'a>]>, /// 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 `` and `` tags for domain update @@ -76,7 +76,7 @@ pub struct DomainRemove<'a> { /// The list of contacts to add to or remove from the domain pub contacts: Option<&'a [DomainContact<'a>]>, /// 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 `` tag for domain update @@ -116,14 +116,10 @@ mod tests { fn command() { let mut object = DomainUpdate::new("eppdev.com"); - let statuses = &[Status { - status: "clientDeleteProhibited".into(), - }]; - let add = DomainAdd { ns: None, contacts: None, - statuses: Some(statuses), + statuses: Some(&[Status::ClientDeleteProhibited]), }; let contacts = &[DomainContact { diff --git a/tests/resources/request/domain/update.xml b/tests/resources/request/domain/update.xml index 8607feb..3585c62 100644 --- a/tests/resources/request/domain/update.xml +++ b/tests/resources/request/domain/update.xml @@ -5,7 +5,7 @@ eppdev.com - + eppdev-contact-2