muc/user: Simplify Status with a new macro.

This commit is contained in:
Emmanuel Gil Peyrot 2017-11-24 05:44:58 +00:00
parent 32f427a73c
commit 75625c497c
2 changed files with 59 additions and 91 deletions

View file

@ -139,6 +139,44 @@ macro_rules! generate_element_enum {
);
}
macro_rules! generate_attribute_enum {
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:expr, $attr:tt, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+,}) => (
generate_attribute_enum!($(#[$meta])* $elem, $name, $ns, $attr, {$($(#[$enum_meta])* $enum => $enum_name),+});
);
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:expr, $attr:tt, {$($(#[$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_unknown_attributes!(elem, $name, [$attr]);
Ok(match get_attr!(elem, $attr, required) {
$($enum_name => $elem::$enum,)+
_ => return Err(Error::ParseError(concat!("Invalid ", $name, " ", $attr, " value."))),
})
}
}
impl From<$elem> for Element {
fn from(elem: $elem) -> Element {
Element::builder($name)
.ns($ns)
.attr($attr, match elem {
$($elem::$enum => $enum_name,)+
})
.build()
}
}
);
}
macro_rules! check_self {
($elem:ident, $name:tt, $ns:expr) => (
check_self!($elem, $name, $ns, $name);

View file

@ -16,131 +16,61 @@ use error::Error;
use ns;
#[derive(Debug, Clone, PartialEq)]
pub enum Status {
generate_attribute_enum!(Status, "status", ns::MUC_USER, "code", {
/// Status: 100
NonAnonymousRoom,
NonAnonymousRoom => 100,
/// Status: 101
AffiliationChange,
AffiliationChange => 101,
/// Status: 102
ConfigShowsUnavailableMembers,
ConfigShowsUnavailableMembers => 102,
/// Status: 103
ConfigHidesUnavailableMembers,
ConfigHidesUnavailableMembers => 103,
/// Status: 104
ConfigNonPrivacyRelated,
ConfigNonPrivacyRelated => 104,
/// Status: 110
SelfPresence,
SelfPresence => 110,
/// Status: 170
ConfigRoomLoggingEnabled,
ConfigRoomLoggingEnabled => 170,
/// Status: 171
ConfigRoomLoggingDisabled,
ConfigRoomLoggingDisabled => 171,
/// Status: 172
ConfigRoomNonAnonymous,
ConfigRoomNonAnonymous => 172,
/// Status: 173
ConfigRoomSemiAnonymous,
ConfigRoomSemiAnonymous => 173,
/// Status: 201
RoomHasBeenCreated,
RoomHasBeenCreated => 201,
/// Status: 210
AssignedNick,
AssignedNick => 210,
/// Status: 301
Banned,
Banned => 301,
/// Status: 303
NewNick,
NewNick => 303,
/// Status: 307
Kicked,
Kicked => 307,
/// Status: 321
RemovalFromRoom,
RemovalFromRoom => 321,
/// Status: 322
ConfigMembersOnly,
ConfigMembersOnly => 322,
/// Status: 332
ServiceShutdown,
}
impl TryFrom<Element> for Status {
type Err = Error;
fn try_from(elem: Element) -> Result<Status, Error> {
if !elem.is("status", ns::MUC_USER) {
return Err(Error::ParseError("This is not a status element."));
}
for _ in elem.children() {
return Err(Error::ParseError("Unknown child in status element."));
}
for (attr, _) in elem.attrs() {
if attr != "code" {
return Err(Error::ParseError("Unknown attribute in status element."));
}
}
let code = get_attr!(elem, "code", required);
Ok(match code {
100 => Status::NonAnonymousRoom,
101 => Status::AffiliationChange,
102 => Status::ConfigShowsUnavailableMembers,
103 => Status::ConfigHidesUnavailableMembers,
104 => Status::ConfigNonPrivacyRelated,
110 => Status::SelfPresence,
170 => Status::ConfigRoomLoggingEnabled,
171 => Status::ConfigRoomLoggingDisabled,
172 => Status::ConfigRoomNonAnonymous,
173 => Status::ConfigRoomSemiAnonymous,
201 => Status::RoomHasBeenCreated,
210 => Status::AssignedNick,
301 => Status::Banned,
303 => Status::NewNick,
307 => Status::Kicked,
321 => Status::RemovalFromRoom,
322 => Status::ConfigMembersOnly,
332 => Status::ServiceShutdown,
_ => return Err(Error::ParseError("Invalid status code.")),
})
}
}
impl From<Status> for Element {
fn from(status: Status) -> Element {
Element::builder("status")
.ns(ns::MUC_USER)
.attr("code", match status {
Status::NonAnonymousRoom => 100,
Status::AffiliationChange => 101,
Status::ConfigShowsUnavailableMembers => 102,
Status::ConfigHidesUnavailableMembers => 103,
Status::ConfigNonPrivacyRelated => 104,
Status::SelfPresence => 110,
Status::ConfigRoomLoggingEnabled => 170,
Status::ConfigRoomLoggingDisabled => 171,
Status::ConfigRoomNonAnonymous => 172,
Status::ConfigRoomSemiAnonymous => 173,
Status::RoomHasBeenCreated => 201,
Status::AssignedNick => 210,
Status::Banned => 301,
Status::NewNick => 303,
Status::Kicked => 307,
Status::RemovalFromRoom => 321,
Status::ConfigMembersOnly => 322,
Status::ServiceShutdown => 332,
})
.build()
}
}
ServiceShutdown => 332,
});
/// Optional <actor/> element used in <item/> elements inside presence stanzas of type
/// "unavailable" that are sent to users who are kick or banned, as well as within IQs for tracking
@ -434,7 +364,7 @@ mod tests {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Invalid status code.");
assert_eq!(message, "Invalid status code value.");
}
#[test]