disco: Use a macro for <identity/>.

This commit is contained in:
Emmanuel Gil Peyrot 2019-02-28 02:26:10 +01:00
parent c4d867571e
commit b56582c8b5
2 changed files with 40 additions and 61 deletions

View file

@ -43,21 +43,25 @@ impl Feature {
} }
} }
/// Structure representing an `<identity xmlns='http://jabber.org/protocol/disco#info'/>` element. generate_element!(
#[derive(Debug, Clone)] /// Structure representing an `<identity xmlns='http://jabber.org/protocol/disco#info'/>` element.
pub struct Identity { Identity, "identity", DISCO_INFO,
/// Category of this identity. attributes: [
pub category: String, // TODO: use an enum here. /// Category of this identity.
// TODO: use an enum here.
category: RequiredNonEmpty<String> = "category",
/// Type of this identity. /// Type of this identity.
pub type_: String, // TODO: use an enum here. // TODO: use an enum here.
type_: RequiredNonEmpty<String> = "type",
/// Lang of the name of this identity. /// Lang of the name of this identity.
pub lang: Option<String>, lang: Option<String> = "xml:lang",
/// Name of this identity. /// Name of this identity.
pub name: Option<String>, name: Option<String> = "name",
} ]
);
impl Identity { impl Identity {
/// Create a new `<identity/>`. /// Create a new `<identity/>`.
@ -89,53 +93,6 @@ impl Identity {
} }
} }
impl TryFrom<Element> for Identity {
type Err = Error;
fn try_from(elem: Element) -> Result<Identity, Error> {
check_self!(elem, "identity", DISCO_INFO, "disco#info identity");
check_no_children!(elem, "disco#info identity");
check_no_unknown_attributes!(
elem,
"disco#info identity",
["category", "type", "xml:lang", "name"]
);
let category = get_attr!(elem, "category", Required);
if category == "" {
return Err(Error::ParseError(
"Identity must have a non-empty 'category' attribute.",
));
}
let type_ = get_attr!(elem, "type", Required);
if type_ == "" {
return Err(Error::ParseError(
"Identity must have a non-empty 'type' attribute.",
));
}
Ok(Identity {
category,
type_,
lang: get_attr!(elem, "xml:lang", Option),
name: get_attr!(elem, "name", Option),
})
}
}
impl From<Identity> for Element {
fn from(identity: Identity) -> Element {
Element::builder("identity")
.ns(ns::DISCO_INFO)
.attr("category", identity.category)
.attr("type", identity.type_)
.attr("xml:lang", identity.lang)
.attr("name", identity.name)
.build()
}
}
/// Structure representing a `<query xmlns='http://jabber.org/protocol/disco#info'/>` element. /// Structure representing a `<query xmlns='http://jabber.org/protocol/disco#info'/>` element.
/// ///
/// It should only be used in an `<iq type='result'/>`, as it can only /// It should only be used in an `<iq type='result'/>`, as it can only
@ -385,7 +342,7 @@ mod tests {
}; };
assert_eq!( assert_eq!(
message, message,
"Identity must have a non-empty 'category' attribute." "Required attribute 'category' must not be empty."
); );
let elem: Element = "<query xmlns='http://jabber.org/protocol/disco#info'><identity category='coucou'/></query>".parse().unwrap(); let elem: Element = "<query xmlns='http://jabber.org/protocol/disco#info'><identity category='coucou'/></query>".parse().unwrap();
@ -402,7 +359,7 @@ mod tests {
Error::ParseError(string) => string, Error::ParseError(string) => string,
_ => panic!(), _ => panic!(),
}; };
assert_eq!(message, "Identity must have a non-empty 'type' attribute."); assert_eq!(message, "Required attribute 'type' must not be empty.");
} }
#[test] #[test]

View file

@ -33,6 +33,25 @@ macro_rules! get_attr {
} }
} }
}; };
($elem:ident, $attr:tt, RequiredNonEmpty, $value:ident, $func:expr) => {
match $elem.attr($attr) {
Some("") => {
return Err(crate::util::error::Error::ParseError(concat!(
"Required attribute '",
$attr,
"' must not be empty."
)));
},
Some($value) => $func,
None => {
return Err(crate::util::error::Error::ParseError(concat!(
"Required attribute '",
$attr,
"' missing."
)));
}
}
};
($elem:ident, $attr:tt, Default, $value:ident, $func:expr) => { ($elem:ident, $attr:tt, Default, $value:ident, $func:expr) => {
match $elem.attr($attr) { match $elem.attr($attr) {
Some($value) => $func, Some($value) => $func,
@ -408,6 +427,9 @@ macro_rules! decl_attr {
(Required, $type:ty) => ( (Required, $type:ty) => (
$type $type
); );
(RequiredNonEmpty, $type:ty) => (
$type
);
(Default, $type:ty) => ( (Default, $type:ty) => (
$type $type
); );