diff --git a/src/data_forms.rs b/src/data_forms.rs index 70c2d3aa..0899cc5c 100644 --- a/src/data_forms.rs +++ b/src/data_forms.rs @@ -14,19 +14,18 @@ use ns; use media_element::MediaElement; -#[derive(Debug, Clone, PartialEq)] -pub enum FieldType { - Boolean, - Fixed, - Hidden, - JidMulti, - JidSingle, - ListMulti, - ListSingle, - TextMulti, - TextPrivate, - TextSingle, -} +generate_attribute!(FieldType, "type", { + Boolean => "boolean", + Fixed => "fixed", + Hidden => "hidden", + JidMulti => "jid-multi", + JidSingle => "jid-single", + ListMulti => "list-multi", + ListSingle => "list-single", + TextMulti => "text-multi", + TextPrivate => "text-private", + TextSingle => "text-single", +}); impl Default for FieldType { fn default() -> FieldType { @@ -34,44 +33,6 @@ impl Default for FieldType { } } -impl FromStr for FieldType { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "boolean" => FieldType::Boolean, - "fixed" => FieldType::Fixed, - "hidden" => FieldType::Hidden, - "jid-multi" => FieldType::JidMulti, - "jid-single" => FieldType::JidSingle, - "list-multi" => FieldType::ListMulti, - "list-single" => FieldType::ListSingle, - "text-multi" => FieldType::TextMulti, - "text-private" => FieldType::TextPrivate, - "text-single" => FieldType::TextSingle, - - _ => return Err(Error::ParseError("Invalid 'type' attribute in field element.")), - }) - } -} - -impl IntoAttributeValue for FieldType { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - FieldType::Boolean => "boolean", - FieldType::Fixed => "fixed", - FieldType::Hidden => "hidden", - FieldType::JidMulti => "jid-multi", - FieldType::JidSingle => "jid-single", - FieldType::ListMulti => "list-multi", - FieldType::ListSingle => "list-single", - FieldType::TextMulti => "text-multi", - FieldType::TextPrivate => "text-private", - FieldType::TextSingle => "text-single", - })) - } -} - #[derive(Debug, Clone)] pub struct Option_ { pub label: Option, @@ -131,39 +92,12 @@ impl IntoElements for Field { } } -#[derive(Debug, Clone, PartialEq)] -pub enum DataFormType { - Cancel, - Form, - Result_, - Submit, -} - -impl FromStr for DataFormType { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "cancel" => DataFormType::Cancel, - "form" => DataFormType::Form, - "result" => DataFormType::Result_, - "submit" => DataFormType::Submit, - - _ => return Err(Error::ParseError("Unknown data form type.")), - }) - } -} - -impl IntoAttributeValue for DataFormType { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - DataFormType::Cancel => "cancel", - DataFormType::Form => "form", - DataFormType::Result_ => "result", - DataFormType::Submit => "submit", - })) - } -} +generate_attribute!(Subscription, "subscription", { + Cancel => "cancel", + Form => "form", + Result_ => "result", + Submit => "submit", +}); #[derive(Debug, Clone)] pub struct DataForm { diff --git a/src/ibb.rs b/src/ibb.rs index 18cb14e8..5463caae 100644 --- a/src/ibb.rs +++ b/src/ibb.rs @@ -14,39 +14,10 @@ use error::Error; use ns; -#[derive(Debug, Clone, PartialEq)] -pub enum Stanza { - Iq, - Message, -} - -impl Default for Stanza { - fn default() -> Stanza { - Stanza::Iq - } -} - -impl FromStr for Stanza { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "iq" => Stanza::Iq, - "message" => Stanza::Message, - - _ => return Err(Error::ParseError("Invalid 'stanza' attribute.")), - }) - } -} - -impl IntoAttributeValue for Stanza { - fn into_attribute_value(self) -> Option { - match self { - Stanza::Iq => None, - Stanza::Message => Some(String::from("message")), - } - } -} +generate_attribute!(Stanza, "stanza", { + Iq => "iq", + Message => "message", +}, Default = Iq); #[derive(Debug, Clone)] pub enum IBB { diff --git a/src/jingle.rs b/src/jingle.rs index c5041b09..e5fab352 100644 --- a/src/jingle.rs +++ b/src/jingle.rs @@ -13,108 +13,35 @@ use jid::Jid; use error::Error; use ns; -#[derive(Debug, Clone, PartialEq)] -pub enum Action { - ContentAccept, - ContentAdd, - ContentModify, - ContentReject, - ContentRemove, - DescriptionInfo, - SecurityInfo, - SessionAccept, - SessionInfo, - SessionInitiate, - SessionTerminate, - TransportAccept, - TransportInfo, - TransportReject, - TransportReplace, -} +generate_attribute!(Action, "action", { + ContentAccept => "content-accept", + ContentAdd => "content-add", + ContentModify => "content-modify", + ContentReject => "content-reject", + ContentRemove => "content-remove", + DescriptionInfo => "description-info", + SecurityInfo => "security-info", + SessionAccept => "session-accept", + SessionInfo => "session-info", + SessionInitiate => "session-initiate", + SessionTerminate => "session-terminate", + TransportAccept => "transport-accept", + TransportInfo => "transport-info", + TransportReject => "transport-reject", + TransportReplace => "transport-replace", +}); -impl FromStr for Action { - type Err = Error; +generate_attribute!(Creator, "creator", { + Initiator => "initiator", + Responder => "responder", +}); - fn from_str(s: &str) -> Result { - Ok(match s { - "content-accept" => Action::ContentAccept, - "content-add" => Action::ContentAdd, - "content-modify" => Action::ContentModify, - "content-reject" => Action::ContentReject, - "content-remove" => Action::ContentRemove, - "description-info" => Action::DescriptionInfo, - "security-info" => Action::SecurityInfo, - "session-accept" => Action::SessionAccept, - "session-info" => Action::SessionInfo, - "session-initiate" => Action::SessionInitiate, - "session-terminate" => Action::SessionTerminate, - "transport-accept" => Action::TransportAccept, - "transport-info" => Action::TransportInfo, - "transport-reject" => Action::TransportReject, - "transport-replace" => Action::TransportReplace, - - _ => return Err(Error::ParseError("Unknown action.")), - }) - } -} - -impl IntoAttributeValue for Action { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - Action::ContentAccept => "content-accept", - Action::ContentAdd => "content-add", - Action::ContentModify => "content-modify", - Action::ContentReject => "content-reject", - Action::ContentRemove => "content-remove", - Action::DescriptionInfo => "description-info", - Action::SecurityInfo => "security-info", - Action::SessionAccept => "session-accept", - Action::SessionInfo => "session-info", - Action::SessionInitiate => "session-initiate", - Action::SessionTerminate => "session-terminate", - Action::TransportAccept => "transport-accept", - Action::TransportInfo => "transport-info", - Action::TransportReject => "transport-reject", - Action::TransportReplace => "transport-replace", - })) - } -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Creator { - Initiator, - Responder, -} - -impl FromStr for Creator { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "initiator" => Creator::Initiator, - "responder" => Creator::Responder, - - _ => return Err(Error::ParseError("Unknown creator.")), - }) - } -} - -impl IntoAttributeValue for Creator { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - Creator::Initiator => "initiator", - Creator::Responder => "responder", - })) - } -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Senders { - Both, - Initiator, - None_, - Responder, -} +generate_attribute!(Senders, "senders", { + Both => "both", + Initiator => "initiator", + None => "none", + Responder => "responder", +}); impl Default for Senders { fn default() -> Senders { @@ -122,32 +49,6 @@ impl Default for Senders { } } -impl FromStr for Senders { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "both" => Senders::Both, - "initiator" => Senders::Initiator, - "none" => Senders::None_, - "responder" => Senders::Responder, - - _ => return Err(Error::ParseError("Unknown senders.")), - }) - } -} - -impl IntoAttributeValue for Senders { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - Senders::Both => "both", - Senders::Initiator => "initiator", - Senders::None_ => "none", - Senders::Responder => "responder", - })) - } -} - #[derive(Debug, Clone)] pub struct Content { pub creator: Creator, @@ -448,7 +349,7 @@ mod tests { Error::ParseError(string) => string, _ => panic!(), }; - assert_eq!(message, "Unknown action."); + assert_eq!(message, "Unknown value for 'action' attribute."); } #[test] @@ -493,7 +394,7 @@ mod tests { Error::ParseError(string) => string, _ => panic!(), }; - assert_eq!(message, "Unknown creator."); + assert_eq!(message, "Unknown value for 'creator' attribute."); let elem: Element = "".parse().unwrap(); let error = Jingle::try_from(elem).unwrap_err(); @@ -501,7 +402,7 @@ mod tests { Error::ParseError(string) => string, _ => panic!(), }; - assert_eq!(message, "Unknown senders."); + assert_eq!(message, "Unknown value for 'senders' attribute."); let elem: Element = "".parse().unwrap(); let error = Jingle::try_from(elem).unwrap_err(); @@ -509,7 +410,7 @@ mod tests { Error::ParseError(string) => string, _ => panic!(), }; - assert_eq!(message, "Unknown senders."); + assert_eq!(message, "Unknown value for 'senders' attribute."); } #[test] diff --git a/src/jingle_s5b.rs b/src/jingle_s5b.rs index e244a8c0..089d1605 100644 --- a/src/jingle_s5b.rs +++ b/src/jingle_s5b.rs @@ -13,45 +13,12 @@ use error::Error; use ns; -#[derive(Debug, Clone, PartialEq)] -pub enum Type { - Assisted, - Direct, - Proxy, - Tunnel, -} - -impl Default for Type { - fn default() -> Type { - Type::Direct - } -} - -impl FromStr for Type { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "assisted" => Type::Assisted, - "direct" => Type::Direct, - "proxy" => Type::Proxy, - "tunnel" => Type::Tunnel, - - _ => return Err(Error::ParseError("Invalid 'type' attribute in candidate element.")), - }) - } -} - -impl IntoAttributeValue for Type { - fn into_attribute_value(self) -> Option { - Some(match self { - Type::Assisted => String::from("assisted"), - Type::Direct => return None, - Type::Proxy => String::from("proxy"), - Type::Tunnel => String::from("tunnel"), - }) - } -} +generate_attribute!(Type, "type", { + Assisted => "assisted", + Direct => "direct", + Proxy => "proxy", + Tunnel => "tunnel", +}, Default = Direct); #[derive(Debug, Clone)] pub struct Candidate { @@ -77,39 +44,10 @@ impl Into for Candidate { } } -#[derive(Debug, Clone, PartialEq)] -pub enum Mode { - Tcp, - Udp, -} - -impl Default for Mode { - fn default() -> Mode { - Mode::Tcp - } -} - -impl FromStr for Mode { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "tcp" => Mode::Tcp, - "udp" => Mode::Udp, - - _ => return Err(Error::ParseError("Invalid 'mode' attribute.")), - }) - } -} - -impl IntoAttributeValue for Mode { - fn into_attribute_value(self) -> Option { - match self { - Mode::Tcp => None, - Mode::Udp => Some(String::from("udp")), - } - } -} +generate_attribute!(Mode, "mode", { + Tcp => "tcp", + Udp => "udp", +}, Default = Tcp); #[derive(Debug, Clone)] pub enum TransportPayload { diff --git a/src/lib.rs b/src/lib.rs index 46a2b8ef..4fc420b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,66 @@ macro_rules! get_attr { ); } +macro_rules! generate_attribute { + ($elem:ident, $name:tt, {$($a:ident => $b:tt),+,}) => ( + generate_attribute!($elem, $name, {$($a => $b),+}); + ); + ($elem:ident, $name:tt, {$($a:ident => $b:tt),+,}, Default = $default:ident) => ( + generate_attribute!($elem, $name, {$($a => $b),+}, Default = $default); + ); + ($elem:ident, $name:tt, {$($a:ident => $b:tt),+}) => ( + #[derive(Debug, Clone, PartialEq)] + pub enum $elem { + $($a),+ + } + impl FromStr for $elem { + type Err = Error; + fn from_str(s: &str) -> Result<$elem, Error> { + Ok(match s { + $($b => $elem::$a),+, + _ => return Err(Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))), + }) + } + } + impl IntoAttributeValue for $elem { + fn into_attribute_value(self) -> Option { + Some(String::from(match self { + $($elem::$a => $b),+ + })) + } + } + ); + ($elem:ident, $name:tt, {$($a:ident => $b:tt),+}, Default = $default:ident) => ( + #[derive(Debug, Clone, PartialEq)] + pub enum $elem { + $($a),+ + } + impl FromStr for $elem { + type Err = Error; + fn from_str(s: &str) -> Result<$elem, Error> { + Ok(match s { + $($b => $elem::$a),+, + _ => return Err(Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))), + }) + } + } + impl IntoAttributeValue for $elem { + #[allow(unreachable_patterns)] + fn into_attribute_value(self) -> Option { + Some(String::from(match self { + $elem::$default => return None, + $($elem::$a => $b),+ + })) + } + } + impl Default for $elem { + fn default() -> $elem { + $elem::$default + } + } + ); +} + /// Error type returned by every parser on failure. pub mod error; /// XML namespace definitions used through XMPP. diff --git a/src/mam.rs b/src/mam.rs index c8cd2ac8..920cf8d0 100644 --- a/src/mam.rs +++ b/src/mam.rs @@ -39,36 +39,11 @@ pub struct Fin { pub set: Set, } -#[derive(Debug, Clone)] -pub enum DefaultPrefs { - Always, - Never, - Roster, -} - -impl FromStr for DefaultPrefs { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "always" => DefaultPrefs::Always, - "never" => DefaultPrefs::Never, - "roster" => DefaultPrefs::Roster, - - _ => return Err(Error::ParseError("Invalid 'default' attribute.")), - }) - } -} - -impl IntoAttributeValue for DefaultPrefs { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - DefaultPrefs::Always => "always", - DefaultPrefs::Never => "never", - DefaultPrefs::Roster => "roster", - })) - } -} +generate_attribute!(DefaultPrefs, "default", { + Always => "always", + Never => "never", + Roster => "roster", +}); #[derive(Debug, Clone)] pub struct Prefs { diff --git a/src/message.rs b/src/message.rs index 13caed35..4efabbdb 100644 --- a/src/message.rs +++ b/src/message.rs @@ -102,14 +102,13 @@ impl Into for MessagePayload { } } -#[derive(Debug, Clone, PartialEq)] -pub enum MessageType { - Chat, - Error, - Groupchat, - Headline, - Normal, -} +generate_attribute!(MessageType, "type", { + Chat => "chat", + Error => "error", + Groupchat => "groupchat", + Headline => "headline", + Normal => "normal", +}); impl Default for MessageType { fn default() -> MessageType { @@ -117,34 +116,6 @@ impl Default for MessageType { } } -impl FromStr for MessageType { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "chat" => MessageType::Chat, - "error" => MessageType::Error, - "groupchat" => MessageType::Groupchat, - "headline" => MessageType::Headline, - "normal" => MessageType::Normal, - - _ => return Err(Error::ParseError("Invalid 'type' attribute on message element.")), - }) - } -} - -impl IntoAttributeValue for MessageType { - fn into_attribute_value(self) -> Option { - Some(match self { - MessageType::Chat => "chat", - MessageType::Error => "error", - MessageType::Groupchat => "groupchat", - MessageType::Headline => "headline", - MessageType::Normal => "normal", - }.to_owned()) - } -} - type Lang = String; type Body = String; type Subject = String; diff --git a/src/pubsub/event.rs b/src/pubsub/event.rs index 47d9a469..07e465c8 100644 --- a/src/pubsub/event.rs +++ b/src/pubsub/event.rs @@ -43,45 +43,12 @@ impl IntoElements for Item { } } -#[derive(Debug, Clone, PartialEq)] -pub enum Subscription { - None, - Pending, - Subscribed, - Unconfigured, -} - -impl Default for Subscription { - fn default() -> Subscription { - Subscription::None - } -} - -impl FromStr for Subscription { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "none" => Subscription::None, - "pending" => Subscription::Pending, - "subscribed" => Subscription::Subscribed, - "unconfigured" => Subscription::Unconfigured, - - _ => return Err(Error::ParseError("Invalid 'subscription' attribute.")), - }) - } -} - -impl IntoAttributeValue for Subscription { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - Subscription::None => return None, - Subscription::Pending => "pending", - Subscription::Subscribed => "subscribed", - Subscription::Unconfigured => "unconfigured", - })) - } -} +generate_attribute!(Subscription, "subscription", { + None => "none", + Pending => "pending", + Subscribed => "subscribed", + Unconfigured => "unconfigured", +}, Default = None); #[derive(Debug, Clone)] pub enum PubSubEvent { diff --git a/src/roster.rs b/src/roster.rs index e8dd8ad5..f38817d0 100644 --- a/src/roster.rs +++ b/src/roster.rs @@ -15,42 +15,13 @@ use ns; type Group = String; -#[derive(Debug, Clone, PartialEq)] -pub enum Subscription { - None, - From, - To, - Both, - Remove, -} - -impl FromStr for Subscription { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "none" => Subscription::None, - "from" => Subscription::From, - "to" => Subscription::To, - "both" => Subscription::Both, - "remove" => Subscription::Remove, - - _ => return Err(Error::ParseError("Unknown value for attribute 'subscription'.")), - }) - } -} - -impl IntoAttributeValue for Subscription { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - Subscription::None => "none", - Subscription::From => "from", - Subscription::To => "to", - Subscription::Both => "both", - Subscription::Remove => "remove", - })) - } -} +generate_attribute!(Subscription, "subscription", { + None => "none", + From => "from", + To => "to", + Both => "both", + Remove => "remove", +}); #[derive(Debug, Clone, PartialEq)] pub struct Item { diff --git a/src/stanza_error.rs b/src/stanza_error.rs index 3841ad5b..badd1efa 100644 --- a/src/stanza_error.rs +++ b/src/stanza_error.rs @@ -14,42 +14,13 @@ use error::Error; use jid::Jid; use ns; -#[derive(Debug, Clone, PartialEq)] -pub enum ErrorType { - Auth, - Cancel, - Continue, - Modify, - Wait, -} - -impl FromStr for ErrorType { - type Err = Error; - - fn from_str(s: &str) -> Result { - Ok(match s { - "auth" => ErrorType::Auth, - "cancel" => ErrorType::Cancel, - "continue" => ErrorType::Continue, - "modify" => ErrorType::Modify, - "wait" => ErrorType::Wait, - - _ => return Err(Error::ParseError("Unknown error type.")), - }) - } -} - -impl IntoAttributeValue for ErrorType { - fn into_attribute_value(self) -> Option { - Some(String::from(match self { - ErrorType::Auth => "auth", - ErrorType::Cancel => "cancel", - ErrorType::Continue => "continue", - ErrorType::Modify => "modify", - ErrorType::Wait => "wait", - })) - } -} +generate_attribute!(ErrorType, "type", { + Auth => "auth", + Cancel => "cancel", + Continue => "continue", + Modify => "modify", + Wait => "wait", +}); #[derive(Debug, Clone, PartialEq)] pub enum DefinedCondition { @@ -252,7 +223,7 @@ mod tests { Error::ParseError(string) => string, _ => panic!(), }; - assert_eq!(message, "Unknown error type."); + assert_eq!(message, "Unknown value for 'type' attribute."); } #[test]