lib, ping, attention: Add a macro for singleton elements.

Emmanuel Gil Peyrot created

Change summary

src/attention.rs | 29 +----------------------------
src/lib.rs       | 30 ++++++++++++++++++++++++++++++
src/ping.rs      | 29 +----------------------------
3 files changed, 32 insertions(+), 56 deletions(-)

Detailed changes

src/attention.rs 🔗

@@ -12,34 +12,7 @@ use error::Error;
 
 use ns;
 
-/// Structure representing an `<attention xmlns='urn:xmpp:attention:0'/>` element.
-#[derive(Debug, Clone)]
-pub struct Attention;
-
-impl TryFrom<Element> for Attention {
-    type Err = Error;
-
-    fn try_from(elem: Element) -> Result<Attention, Error> {
-        if !elem.is("attention", ns::ATTENTION) {
-            return Err(Error::ParseError("This is not an attention element."));
-        }
-        for _ in elem.children() {
-            return Err(Error::ParseError("Unknown child in attention element."));
-        }
-        for _ in elem.attrs() {
-            return Err(Error::ParseError("Unknown attribute in attention element."));
-        }
-        Ok(Attention)
-    }
-}
-
-impl From<Attention> for Element {
-    fn from(_: Attention) -> Element {
-        Element::builder("attention")
-                .ns(ns::ATTENTION)
-                .build()
-    }
-}
+generate_empty_element!(Attention, "attention", ns::ATTENTION);
 
 #[cfg(test)]
 mod tests {

src/lib.rs 🔗

@@ -159,6 +159,36 @@ macro_rules! check_no_unknown_attributes {
     );
 }
 
+macro_rules! generate_empty_element {
+    ($elem:ident, $name:tt, $ns:expr) => (
+        // TODO: Find a better way to concatenate doc.
+        #[doc="Structure representing a "]
+        #[doc=$name]
+        #[doc=" element."]
+        #[derive(Debug, Clone)]
+        pub struct $elem;
+
+        impl TryFrom<Element> for $elem {
+            type Err = Error;
+
+            fn try_from(elem: Element) -> Result<$elem, Error> {
+                check_self!(elem, $name, $ns);
+                check_no_children!(elem, $name);
+                check_no_unknown_attributes!(elem, $name, []);
+                Ok($elem)
+            }
+        }
+
+        impl From<$elem> for Element {
+            fn from(_: $elem) -> Element {
+                Element::builder("attention")
+                        .ns($ns)
+                        .build()
+            }
+        }
+    );
+}
+
 macro_rules! generate_id {
     ($elem:ident) => (
         #[derive(Debug, Clone, PartialEq, Eq, Hash)]

src/ping.rs 🔗

@@ -13,34 +13,7 @@ use error::Error;
 
 use ns;
 
-/// Structure representing a `<ping xmlns='urn:xmpp:ping'/>` element.
-#[derive(Debug, Clone)]
-pub struct Ping;
-
-impl TryFrom<Element> for Ping {
-    type Err = Error;
-
-    fn try_from(elem: Element) -> Result<Ping, Error> {
-        if !elem.is("ping", ns::PING) {
-            return Err(Error::ParseError("This is not a ping element."));
-        }
-        for _ in elem.children() {
-            return Err(Error::ParseError("Unknown child in ping element."));
-        }
-        for _ in elem.attrs() {
-            return Err(Error::ParseError("Unknown attribute in ping element."));
-        }
-        Ok(Ping)
-    }
-}
-
-impl From<Ping> for Element {
-    fn from(_: Ping) -> Element {
-        Element::builder("ping")
-                .ns(ns::PING)
-                .build()
-    }
-}
+generate_empty_element!(Ping, "ping", ns::PING);
 
 #[cfg(test)]
 mod tests {