From ca19e545fdd6529df1351cb5c1551d1f331f79e5 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 12 Mar 2022 20:36:46 +0100 Subject: [PATCH] Flatten XML abstraction --- src/client.rs | 17 ++++++++--------- src/hello.rs | 11 +++-------- src/request.rs | 7 +------ src/response.rs | 11 +++-------- src/tests/mod.rs | 8 +++----- src/xml.rs | 31 ++++++++++--------------------- 6 files changed, 28 insertions(+), 57 deletions(-) diff --git a/src/client.rs b/src/client.rs index 5268579..b043b0f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -21,7 +21,7 @@ use crate::error::Error; use crate::hello::{Greeting, GreetingDocument, HelloDocument}; use crate::request::{Command, CommandDocument, Extension, Transaction}; use crate::response::{Response, ResponseDocument, ResponseStatus}; -use crate::xml::EppXml; +use crate::xml; /// An `EppClient` provides an interface to sending EPP requests to a registry /// @@ -107,13 +107,13 @@ impl EppClient { /// Executes an EPP Hello call and returns the response as a `Greeting` pub async fn hello(&mut self) -> Result { - let hello_xml = HelloDocument::default().serialize()?; + let xml = xml::serialize(&HelloDocument::default())?; - debug!("{}: hello: {}", self.connection.registry, &hello_xml); - let response = self.connection.transact(&hello_xml)?.await?; + debug!("{}: hello: {}", self.connection.registry, &xml); + let response = self.connection.transact(&xml)?.await?; debug!("{}: greeting: {}", self.connection.registry, &response); - Ok(GreetingDocument::deserialize(&response)?.data) + Ok(xml::deserialize::(&response)?.data) } pub async fn transact<'c, 'e, Cmd, Ext>( @@ -127,14 +127,13 @@ impl EppClient { { let data = data.into(); let document = CommandDocument::new(data.command, data.extension, id); - let xml = document.serialize()?; + let xml = xml::serialize(&document)?; debug!("{}: request: {}", self.connection.registry, &xml); let response = self.connection.transact(&xml)?.await?; debug!("{}: response: {}", self.connection.registry, &response); - let rsp = - as EppXml>::deserialize(&response)?; + let rsp = xml::deserialize::>(&response)?; if rsp.data.result.code.is_success() { return Ok(rsp.data); } @@ -161,7 +160,7 @@ impl EppClient { /// Returns the greeting received on establishment of the connection as an `Greeting` pub fn greeting(&self) -> Result { - GreetingDocument::deserialize(&self.connection.greeting).map(|obj| obj.data) + xml::deserialize::(&self.connection.greeting).map(|obj| obj.data) } pub async fn reconnect(&mut self) -> Result<(), Error> { diff --git a/src/hello.rs b/src/hello.rs index 697a60d..6a69429 100644 --- a/src/hello.rs +++ b/src/hello.rs @@ -4,7 +4,6 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Deserializer, Serialize}; use crate::common::{Options, ServiceExtension, Services, StringValue, EPP_XMLNS}; -use crate::xml::EppXml; // Request @@ -27,8 +26,6 @@ impl Default for HelloDocument { } } -impl EppXml for HelloDocument {} - // Response /// Type for data within the section of an EPP greeting @@ -302,20 +299,18 @@ pub struct GreetingDocument { pub data: Greeting, } -impl EppXml for GreetingDocument {} - #[cfg(test)] mod tests { use chrono::{TimeZone, Utc}; use super::{ExpiryType, GreetingDocument, HelloDocument, Relative}; use crate::tests::get_xml; - use crate::xml::EppXml; + use crate::xml; #[test] fn hello() { let xml = get_xml("request/hello.xml").unwrap(); - let serialized = HelloDocument::default().serialize().unwrap(); + let serialized = xml::serialize(&HelloDocument::default()).unwrap(); assert_eq!(xml, serialized); } @@ -323,7 +318,7 @@ mod tests { #[test] fn greeting() { let xml = get_xml("response/greeting.xml").unwrap(); - let object = GreetingDocument::deserialize(xml.as_str()).unwrap(); + let object = xml::deserialize::(xml.as_str()).unwrap(); assert_eq!(object.data.service_id, "ISPAPI EPP Server"); assert_eq!( diff --git a/src/request.rs b/src/request.rs index 464bcea..2f9b311 100644 --- a/src/request.rs +++ b/src/request.rs @@ -3,10 +3,7 @@ use serde::{de::DeserializeOwned, ser::SerializeStruct, ser::Serializer, Serialize}; use std::fmt::Debug; -use crate::{ - common::{StringValue, EPP_XMLNS}, - xml::EppXml, -}; +use crate::common::{StringValue, EPP_XMLNS}; pub const EPP_VERSION: &str = "1.0"; pub const EPP_LANG: &str = "en"; @@ -73,5 +70,3 @@ impl<'a, Cmd, Ext> CommandDocument<'a, Cmd, Ext> { } } } - -impl<'a, D: Serialize, E: Serialize> EppXml for CommandDocument<'a, D, E> {} diff --git a/src/response.rs b/src/response.rs index 81219bc..ba6bdca 100644 --- a/src/response.rs +++ b/src/response.rs @@ -3,10 +3,9 @@ use std::fmt::{self, Debug}; use chrono::{DateTime, Utc}; -use serde::{de::DeserializeOwned, Deserialize}; +use serde::Deserialize; use crate::common::StringValue; -use crate::xml::EppXml; /// Type corresponding to the tag an EPP response XML #[derive(Deserialize, Debug, PartialEq)] @@ -218,8 +217,6 @@ pub struct ResponseDocument { pub data: Response, } -impl EppXml for ResponseDocument {} - #[derive(Debug, Deserialize, PartialEq)] #[serde(rename = "epp")] pub struct ResultDocument { @@ -227,8 +224,6 @@ pub struct ResultDocument { pub data: ResponseStatus, } -impl EppXml for ResultDocument {} - #[derive(Deserialize, Debug, PartialEq)] /// Type corresponding to the <response> tag in an EPP response XML /// without or <resData> sections. Generally used for error handling @@ -261,12 +256,12 @@ impl Response { mod tests { use super::{ResultCode, ResultDocument}; use crate::tests::{get_xml, CLTRID, SVTRID}; - use crate::xml::EppXml; + use crate::xml; #[test] fn error() { let xml = get_xml("response/error.xml").unwrap(); - let object = ResultDocument::deserialize(xml.as_str()).unwrap(); + let object = xml::deserialize::(xml.as_str()).unwrap(); assert_eq!(object.data.result.code, ResultCode::ObjectDoesNotExist); assert_eq!(object.data.result.message, "Object does not exist".into()); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index c260c6f..01b3ab3 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -9,7 +9,7 @@ use crate::{ common::NoExtension, request::{Command, CommandDocument, Extension, Transaction}, response::{Response, ResponseDocument}, - xml::EppXml, + xml, }; pub(crate) const RESOURCES_DIR: &str = "./tests/resources"; @@ -47,8 +47,7 @@ pub(crate) fn assert_serialized<'c, 'e, Cmd, Ext>( let expected = get_xml(path).unwrap(); let req = req.into(); let document = CommandDocument::new(req.command, req.extension, CLTRID); - let actual = EppXml::serialize(&document).unwrap(); - assert_eq!(expected, actual); + assert_eq!(expected, xml::serialize(&document).unwrap()); } pub(crate) fn response_from_file<'c, Cmd>( @@ -68,8 +67,7 @@ where Ext: Extension, { let xml = get_xml(path).unwrap(); - let rsp = - as EppXml>::deserialize(&xml).unwrap(); + let rsp = xml::deserialize::>(&xml).unwrap(); assert!(rsp.data.result.code.is_success()); rsp.data } diff --git a/src/xml.rs b/src/xml.rs index ebdc500..960df83 100644 --- a/src/xml.rs +++ b/src/xml.rs @@ -6,25 +6,14 @@ use crate::error::Error; pub const EPP_XML_HEADER: &str = r#""#; -/// Trait to be implemented by serializers. Currently the only included serializer is `quick-xml` -pub trait EppXml: Sized { - /// Serializes the EppObject instance to an EPP XML document - fn serialize(&self) -> Result - where - Self: Serialize, - { - Ok(format!( - "{}\r\n{}", - EPP_XML_HEADER, - quick_xml::se::to_string(self).map_err(|e| Error::Xml(e.into()))? - )) - } - - /// Deserializes an EPP XML document to an EppObject instance - fn deserialize(epp_xml: &str) -> Result - where - Self: DeserializeOwned + Sized, - { - quick_xml::de::from_str::(epp_xml).map_err(|e| Error::Xml(e.into())) - } +pub(crate) fn serialize(doc: &impl Serialize) -> Result { + Ok(format!( + "{}\r\n{}", + EPP_XML_HEADER, + quick_xml::se::to_string(doc).map_err(|e| Error::Xml(e.into()))? + )) +} + +pub(crate) fn deserialize(xml: &str) -> Result { + quick_xml::de::from_str(xml).map_err(|e| Error::Xml(e.into())) }