From 96268d9528498ca7cb2b089259c334aaa6163ee8 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 2 Mar 2023 14:01:49 +0100 Subject: [PATCH] Use enum type to represent contact::Status --- src/contact/info.rs | 5 +- src/contact/mod.rs | 111 +++++++++++++++++++-- src/contact/update.rs | 16 +-- tests/resources/request/contact/update.xml | 4 +- 4 files changed, 114 insertions(+), 22 deletions(-) diff --git a/src/contact/info.rs b/src/contact/info.rs index 103495c..25e0d8a 100644 --- a/src/contact/info.rs +++ b/src/contact/info.rs @@ -56,7 +56,7 @@ pub struct InfoData { /// The contact ROID pub roid: String, /// The list of contact statuses - pub statuses: Vec>, + pub statuses: Vec, /// The postal info for the contact pub postal_info: PostalInfo<'static>, /// The voice data for the contact @@ -93,6 +93,7 @@ mod tests { use chrono::{TimeZone, Utc}; use super::ContactInfo; + use crate::contact::Status; use crate::response::ResultCode; use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID}; @@ -116,7 +117,7 @@ mod tests { assert_eq!(object.result.message, SUCCESS_MSG); assert_eq!(result.id, "eppdev-contact-3"); assert_eq!(result.roid, "UNDEF-ROID"); - assert_eq!(result.statuses[0].status, "ok"); + assert_eq!(result.statuses[0], Status::Ok); assert_eq!(result.postal_info.info_type, "loc"); assert_eq!(result.postal_info.name, "John Doe"); assert_eq!(result.postal_info.organization, "Acme Widgets"); diff --git a/src/contact/mod.rs b/src/contact/mod.rs index e4e3071..e717282 100644 --- a/src/contact/mod.rs +++ b/src/contact/mod.rs @@ -6,7 +6,7 @@ use std::borrow::Cow; use std::fmt; use std::str::FromStr; -use instant_xml::{display_to_xml, from_xml_str, FromXml, ToXml}; +use instant_xml::{display_to_xml, from_xml_str, Deserializer, FromXml, Serializer, ToXml}; pub mod check; pub use check::ContactCheck; @@ -220,10 +220,107 @@ impl<'a> PostalInfo<'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, + ClientTransferProhibited, + ServerTransferProhibited, + ClientUpdateProhibited, + ServerUpdateProhibited, + Linked, + Ok, + PendingCreate, + PendingDelete, + PendingTransfer, + PendingUpdate, +} + +impl Status { + pub fn as_str(&self) -> &'static str { + use Status::*; + match self { + ClientDeleteProhibited => "clientDeleteProhibited", + ServerDeleteProhibited => "serverDeleteProhibited", + ClientTransferProhibited => "clientTransferProhibited", + ServerTransferProhibited => "serverTransferProhibited", + ClientUpdateProhibited => "clientUpdateProhibited", + ServerUpdateProhibited => "serverUpdateProhibited", + Linked => "linked", + Ok => "ok", + PendingCreate => "pendingCreate", + PendingDelete => "pendingDelete", + 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, + "clientTransferProhibited" => Status::ClientTransferProhibited, + "serverTransferProhibited" => Status::ServerTransferProhibited, + "clientUpdateProhibited" => Status::ClientUpdateProhibited, + "serverUpdateProhibited" => Status::ServerUpdateProhibited, + "linked" => Status::Linked, + "ok" => Status::Ok, + "pendingCreate" => Status::PendingCreate, + "pendingDelete" => Status::PendingDelete, + "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/contact/update.rs b/src/contact/update.rs index 72f8e39..c0ab021 100644 --- a/src/contact/update.rs +++ b/src/contact/update.rs @@ -74,19 +74,19 @@ pub struct ContactChangeInfo<'a> { /// Type for list of elements of the `` tag for contact update request #[derive(Debug, ToXml)] pub struct StatusList<'a> { - status: &'a [Status<'a>], + status: &'a [Status], } #[derive(Debug, ToXml)] #[xml(rename = "add", ns(XMLNS))] struct AddStatuses<'a> { - statuses: &'a [Status<'a>], + statuses: &'a [Status], } #[derive(Debug, ToXml)] #[xml(rename = "rem", ns(XMLNS))] struct RemoveStatuses<'a> { - statuses: &'a [Status<'a>], + statuses: &'a [Status], } /// Type for elements under the contact `` tag @@ -125,14 +125,8 @@ mod tests { let voice = Voice::new("+33.47237942"); object.set_info("newemail@eppdev.net", postal_info, voice, "eppdev-387323"); - let add_statuses = &[Status { - status: "clientTransferProhibited".into(), - }]; - object.add(add_statuses); - let remove_statuses = &[Status { - status: "clientDeleteProhibited".into(), - }]; - object.remove(remove_statuses); + object.add(&[Status::ClientTransferProhibited]); + object.remove(&[Status::ClientDeleteProhibited]); assert_serialized("request/contact/update.xml", &object); } diff --git a/tests/resources/request/contact/update.xml b/tests/resources/request/contact/update.xml index ad4843e..1293846 100644 --- a/tests/resources/request/contact/update.xml +++ b/tests/resources/request/contact/update.xml @@ -5,10 +5,10 @@ eppdev-contact-3 - + - +