chatstates: Generate ChatState automatically.

Emmanuel Gil Peyrot created

Change summary

src/chatstates.rs | 60 ++++++++++++------------------------------------
src/macros.rs     | 36 +++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 45 deletions(-)

Detailed changes

src/chatstates.rs 🔗

@@ -14,56 +14,26 @@ use error::Error;
 
 use ns;
 
-/// Enum representing chatstate elements part of the
-/// `http://jabber.org/protocol/chatstates` namespace.
-#[derive(Debug, Clone)]
-pub enum ChatState {
-    /// `<active xmlns='http://jabber.org/protocol/chatstates'/>`
-    Active,
+generate_element_enum!(
+    /// Enum representing chatstate elements part of the
+    /// `http://jabber.org/protocol/chatstates` namespace.
+    ChatState, "chatstate", ns::CHATSTATES, {
+        /// `<active xmlns='http://jabber.org/protocol/chatstates'/>`
+        Active => "active",
 
-    /// `<composing xmlns='http://jabber.org/protocol/chatstates'/>`
-    Composing,
+        /// `<composing xmlns='http://jabber.org/protocol/chatstates'/>`
+        Composing => "composing",
 
-    /// `<gone xmlns='http://jabber.org/protocol/chatstates'/>`
-    Gone,
+        /// `<gone xmlns='http://jabber.org/protocol/chatstates'/>`
+        Gone => "gone",
 
-    /// `<inactive xmlns='http://jabber.org/protocol/chatstates'/>`
-    Inactive,
+        /// `<inactive xmlns='http://jabber.org/protocol/chatstates'/>`
+        Inactive => "inactive",
 
-    /// `<paused xmlns='http://jabber.org/protocol/chatstates'/>`
-    Paused,
-}
-
-impl TryFrom<Element> for ChatState {
-    type Err = Error;
-
-    fn try_from(elem: Element) -> Result<ChatState, Error> {
-        check_ns_only!(elem, "chatstate", ns::CHATSTATES);
-        check_no_children!(elem, "chatstate");
-        check_no_attributes!(elem, "chatstate");
-        Ok(match elem.name() {
-            "active" => ChatState::Active,
-            "composing" => ChatState::Composing,
-            "gone" => ChatState::Gone,
-            "inactive" => ChatState::Inactive,
-            "paused" => ChatState::Paused,
-            _ => return Err(Error::ParseError("This is not a chatstate element.")),
-        })
-    }
-}
-
-impl From<ChatState> for Element {
-    fn from(chatstate: ChatState) -> Element {
-        Element::builder(match chatstate {
-            ChatState::Active => "active",
-            ChatState::Composing => "composing",
-            ChatState::Gone => "gone",
-            ChatState::Inactive => "inactive",
-            ChatState::Paused => "paused",
-        }).ns(ns::CHATSTATES)
-          .build()
+        /// `<paused xmlns='http://jabber.org/protocol/chatstates'/>`
+        Paused => "paused",
     }
-}
+);
 
 #[cfg(test)]
 mod tests {

src/macros.rs 🔗

@@ -96,6 +96,42 @@ macro_rules! generate_attribute {
     );
 }
 
+macro_rules! generate_element_enum {
+    ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:expr, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+,}) => (
+        generate_element_enum!($(#[$meta])* $elem, $name, $ns, {$($(#[$enum_meta])* $enum => $enum_name),+});
+    );
+    ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:expr, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+}) => (
+        $(#[$meta])*
+        #[derive(Debug, Clone, PartialEq)]
+        pub enum $elem {
+            $(
+            $(#[$enum_meta])*
+            $enum
+            ),+
+        }
+        impl TryFrom<Element> for $elem {
+            type Err = Error;
+            fn try_from(elem: Element) -> Result<$elem, Error> {
+                check_ns_only!(elem, $name, $ns);
+                check_no_children!(elem, $name);
+                check_no_attributes!(elem, $name);
+                Ok(match elem.name() {
+                    $($enum_name => $elem::$enum,)+
+                    _ => return Err(Error::ParseError(concat!("This is not a ", $name, " element."))),
+                })
+            }
+        }
+        impl From<$elem> for Element {
+            fn from(elem: $elem) -> Element {
+                Element::builder(match elem {
+                    $($elem::$enum => $enum_name,)+
+                }).ns($ns)
+                  .build()
+            }
+        }
+    );
+}
+
 macro_rules! check_self {
     ($elem:ident, $name:tt, $ns:expr) => (
         check_self!($elem, $name, $ns, $name);