parsers: port some elements with children to derive macros

Jonas SchΓ€fer created

Change summary

parsers/src/carbons.rs         | 34 ++++++++++++++++------------------
parsers/src/cert_management.rs | 32 ++++++++++++++++----------------
parsers/src/data_forms.rs      |  3 ++-
parsers/src/http_upload.rs     | 22 ++++++++++++----------
parsers/src/mam.rs             | 31 ++++++++++++++++---------------
parsers/src/muc/user.rs        |  4 ++--
parsers/src/nick.rs            |  4 ++--
parsers/src/openpgp.rs         | 24 ++++++++++++------------
parsers/src/private.rs         | 20 +++++++++++---------
parsers/src/util/macros.rs     | 26 +++++---------------------
parsers/src/vcard.rs           | 23 ++++++++++++-----------
11 files changed, 106 insertions(+), 117 deletions(-)

Detailed changes

parsers/src/carbons.rs πŸ”—

@@ -33,27 +33,25 @@ pub struct Private;
 
 impl MessagePayload for Private {}
 
-generate_element!(
-    /// Wrapper for a message received on another resource.
-    Received, "received", CARBONS,
-
-    children: [
-        /// Wrapper for the enclosed message.
-        forwarded: Required<Forwarded> = ("forwarded", FORWARD) => Forwarded
-    ]
-);
+/// Wrapper for a message received on another resource.
+#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
+#[xml(namespace = ns::CARBONS, name = "received")]
+pub struct Received {
+    /// Wrapper for the enclosed message.
+    #[xml(child)]
+    pub forwarded: Forwarded,
+}
 
 impl MessagePayload for Received {}
 
-generate_element!(
-    /// Wrapper for a message sent from another resource.
-    Sent, "sent", CARBONS,
-
-    children: [
-        /// Wrapper for the enclosed message.
-        forwarded: Required<Forwarded> = ("forwarded", FORWARD) => Forwarded
-    ]
-);
+/// Wrapper for a message sent from another resource.
+#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
+#[xml(namespace = ns::CARBONS, name = "sent")]
+pub struct Sent {
+    /// Wrapper for the enclosed message.
+    #[xml(child)]
+    pub forwarded: Forwarded,
+}
 
 impl MessagePayload for Sent {}
 

parsers/src/cert_management.rs πŸ”—

@@ -94,25 +94,25 @@ generate_element!(
 
 impl IqResultPayload for ListCertsResponse {}
 
-generate_element!(
-    /// Client disables an X.509 certificate.
-    Disable, "disable", SASL_CERT,
-    children: [
-        /// Name of the certificate to disable.
-        name: Required<Name> = ("name", SASL_CERT) => Name
-    ]
-);
+/// Client disables an X.509 certificate.
+#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
+#[xml(namespace = ns::SASL_CERT, name = "disable")]
+pub struct Disable {
+    /// Name of the certificate to disable.
+    #[xml(child)]
+    pub name: Name,
+}
 
 impl IqSetPayload for Disable {}
 
-generate_element!(
-    /// Client revokes an X.509 certificate.
-    Revoke, "revoke", SASL_CERT,
-    children: [
-        /// Name of the certificate to revoke.
-        name: Required<Name> = ("name", SASL_CERT) => Name
-    ]
-);
+/// Client revokes an X.509 certificate.
+#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
+#[xml(namespace = ns::SASL_CERT, name = "revoke")]
+pub struct Revoke {
+    /// Name of the certificate to revoke.
+    #[xml(child)]
+    pub name: Name,
+}
 
 impl IqSetPayload for Revoke {}
 

parsers/src/data_forms.rs πŸ”—

@@ -4,11 +4,12 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+use xso::error::{Error, FromElementError};
+
 use crate::data_forms_validate::Validate;
 use crate::media_element::MediaElement;
 use crate::ns;
 use minidom::Element;
-use xso::error::{Error, FromElementError};
 
 generate_element!(
     /// Represents one of the possible values for a list- field.

parsers/src/http_upload.rs πŸ”—

@@ -105,16 +105,18 @@ pub struct Get {
     pub url: String,
 }
 
-generate_element!(
-    /// Requesting a slot
-    SlotResult, "slot", HTTP_UPLOAD,
-    children: [
-        /// Put URL and headers
-        put: Required<Put> = ("put", HTTP_UPLOAD) => Put,
-        /// Get URL
-        get: Required<Get> = ("get", HTTP_UPLOAD) => Get
-    ]
-);
+/// Requesting a slot
+#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
+#[xml(namespace = ns::HTTP_UPLOAD, name = "slot")]
+pub struct SlotResult {
+    /// Put URL and headers
+    #[xml(child)]
+    pub put: Put,
+
+    /// Get URL
+    #[xml(child)]
+    pub get: Get,
+}
 
 impl IqResultPayload for SlotResult {}
 

parsers/src/mam.rs πŸ”—

@@ -117,22 +117,23 @@ impl From<Query> for Element {
     }
 }
 
-generate_element!(
-    /// The wrapper around forwarded stanzas.
-    Result_, "result", MAM,
-    attributes: [
-        /// The stanza-id under which the archive stored this stanza.
-        id: Required<String> = "id",
+/// The wrapper around forwarded stanzas.
+#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
+#[xml(namespace = ns::MAM, name = "result")]
+pub struct Result_ {
+    /// The stanza-id under which the archive stored this stanza.
+    #[xml(attribute)]
+    pub id: String,
 
-        /// The same queryid as the one requested in the
-        /// [query](struct.Query.html).
-        queryid: Option<QueryId> = "queryid",
-    ],
-    children: [
-        /// The actual stanza being forwarded.
-        forwarded: Required<Forwarded> = ("forwarded", FORWARD) => Forwarded
-    ]
-);
+    /// The same queryid as the one requested in the
+    /// [query](struct.Query.html).
+    #[xml(attribute(default))]
+    pub queryid: Option<QueryId>,
+
+    /// The actual stanza being forwarded.
+    #[xml(child)]
+    pub forwarded: Forwarded,
+}
 
 impl MessagePayload for Result_ {}
 

parsers/src/muc/user.rs πŸ”—

@@ -567,7 +567,7 @@ mod tests {
             FromElementError::Invalid(Error::Other(string)) => string,
             _ => panic!(),
         };
-        assert_eq!(message, "Unknown attribute in reason element.".to_owned());
+        assert_eq!(message, "Unknown attribute in Reason element.".to_owned());
     }
 
     #[cfg(not(feature = "disable-validation"))]
@@ -583,7 +583,7 @@ mod tests {
             FromElementError::Invalid(Error::Other(string)) => string,
             _ => panic!(),
         };
-        assert_eq!(message, "Unknown child in reason element.".to_owned());
+        assert_eq!(message, "Unknown child in Reason element.".to_owned());
     }
 
     #[cfg(not(feature = "disable-validation"))]

parsers/src/nick.rs πŸ”—

@@ -59,7 +59,7 @@ mod tests {
             FromElementError::Invalid(Error::Other(string)) => string,
             _ => panic!(),
         };
-        assert_eq!(message, "Unknown child in nick element.");
+        assert_eq!(message, "Unknown child in Nick element.");
     }
 
     #[cfg(not(feature = "disable-validation"))]
@@ -73,6 +73,6 @@ mod tests {
             FromElementError::Invalid(Error::Other(string)) => string,
             _ => panic!(),
         };
-        assert_eq!(message, "Unknown attribute in nick element.");
+        assert_eq!(message, "Unknown attribute in Nick element.");
     }
 }

parsers/src/openpgp.rs πŸ”—

@@ -20,18 +20,18 @@ pub struct PubKeyData {
     pub data: Vec<u8>,
 }
 
-generate_element!(
-    /// Pubkey element to be used in PubSub publish payloads.
-    PubKey, "pubkey", OX,
-    attributes: [
-        /// Last updated date
-        date: Option<DateTime> = "date"
-    ],
-    children: [
-        /// Public key as base64 data
-        data: Required<PubKeyData> = ("data", OX) => PubKeyData
-    ]
-);
+/// Pubkey element to be used in PubSub publish payloads.
+#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
+#[xml(namespace = ns::OX, name = "pubkey")]
+pub struct PubKey {
+    /// Last updated date
+    #[xml(attribute(default))]
+    pub date: Option<DateTime>,
+
+    /// Public key as base64 data
+    #[xml(child)]
+    pub data: PubKeyData,
+}
 
 impl PubSubPayload for PubKey {}
 

parsers/src/private.rs πŸ”—

@@ -19,20 +19,22 @@
 //! This module uses the legacy bookmarks [`bookmarks::Conference`][crate::bookmarks::Conference]
 //! struct as stored in a legacy [`bookmarks::Storage`][crate::bookmarks::Storage] struct.
 
+use xso::{AsXml, FromXml};
+
 use crate::{
     bookmarks::Storage,
     iq::{IqGetPayload, IqResultPayload, IqSetPayload},
+    ns,
 };
 
-generate_element!(
-    /// A Private XML Storage query. Only supports XEP-0048 bookmarks.
-    Query, "query", PRIVATE,
-    attributes: [],
-    children: [
-        /// XEP-0048 bookmarks in a [`Storage`] element
-        storage: Required<Storage> = ("storage", BOOKMARKS) => Storage,
-    ]
-);
+/// A Private XML Storage query. Only supports XEP-0048 bookmarks.
+#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
+#[xml(namespace = ns::PRIVATE, name = "query")]
+pub struct Query {
+    /// XEP-0048 bookmarks in a [`Storage`] element
+    #[xml(child)]
+    pub storage: Storage,
+}
 
 impl IqSetPayload for Query {}
 impl IqGetPayload for Query {}

parsers/src/util/macros.rs πŸ”—

@@ -453,7 +453,7 @@ macro_rules! generate_id {
 }
 
 macro_rules! generate_elem_id {
-    ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident) => (
+    ($(#[$meta:meta])* $elem:ident, $name:literal, $ns:ident) => (
         generate_elem_id!($(#[$meta])* $elem, $name, $ns, String);
         impl ::std::str::FromStr for $elem {
             type Err = xso::error::Error;
@@ -463,27 +463,11 @@ macro_rules! generate_elem_id {
             }
         }
     );
-    ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $type:ty) => (
+    ($(#[$meta:meta])* $elem:ident, $name:literal, $ns:ident, $type:ty) => (
         $(#[$meta])*
-        #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-        pub struct $elem(pub $type);
-        impl ::std::convert::TryFrom<minidom::Element> for $elem {
-            type Error = xso::error::FromElementError;
-            fn try_from(elem: minidom::Element) -> Result<$elem, xso::error::FromElementError> {
-                check_self!(elem, $name, $ns);
-                check_no_children!(elem, $name);
-                check_no_attributes!(elem, $name);
-                // TODO: add a way to parse that differently when needed.
-                Ok($elem(elem.text().parse().map_err(xso::error::Error::text_parse_error)?))
-            }
-        }
-        impl From<$elem> for minidom::Element {
-            fn from(elem: $elem) -> minidom::Element {
-                minidom::Element::builder($name, crate::ns::$ns)
-                    .append(elem.0.to_string())
-                    .build()
-            }
-        }
+        #[derive(xso::FromXml, xso::AsXml, Debug, Clone, PartialEq, Eq, Hash)]
+        #[xml(namespace = crate::ns::$ns, name = $name)]
+        pub struct $elem(#[xml(text)] pub $type);
     );
 }
 

parsers/src/vcard.rs πŸ”—

@@ -23,17 +23,18 @@ use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
 use crate::ns;
 use minidom::Element;
 
-generate_element!(
-    /// A photo element.
-    Photo, "PHOTO", VCARD,
-    attributes: [],
-    children: [
-        /// The type of the photo.
-        type_: Required<Type> = ("TYPE", VCARD) => Type,
-        /// The binary data of the photo.
-        binval: Required<Binval> = ("BINVAL", VCARD) => Binval,
-    ]
-);
+/// A photo element.
+#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
+#[xml(namespace = ns::VCARD, name = "PHOTO")]
+pub struct Photo {
+    /// The type of the photo.
+    #[xml(child)]
+    pub type_: Type,
+
+    /// The binary data of the photo.
+    #[xml(child)]
+    pub binval: Binval,
+}
 
 /// The type of the photo.
 #[derive(FromXml, AsXml, PartialEq, Debug, Clone)]