diff --git a/src/disco.rs b/src/disco.rs
index b958cce..8714520 100644
--- a/src/disco.rs
+++ b/src/disco.rs
@@ -43,21 +43,25 @@ impl Feature {
}
}
-/// Structure representing an `` element.
-#[derive(Debug, Clone)]
-pub struct Identity {
- /// Category of this identity.
- pub category: String, // TODO: use an enum here.
+generate_element!(
+ /// Structure representing an `` element.
+ Identity, "identity", DISCO_INFO,
+ attributes: [
+ /// Category of this identity.
+ // TODO: use an enum here.
+ category: RequiredNonEmpty = "category",
- /// Type of this identity.
- pub type_: String, // TODO: use an enum here.
+ /// Type of this identity.
+ // TODO: use an enum here.
+ type_: RequiredNonEmpty = "type",
- /// Lang of the name of this identity.
- pub lang: Option,
+ /// Lang of the name of this identity.
+ lang: Option = "xml:lang",
- /// Name of this identity.
- pub name: Option,
-}
+ /// Name of this identity.
+ name: Option = "name",
+ ]
+);
impl Identity {
/// Create a new ``.
@@ -89,53 +93,6 @@ impl Identity {
}
}
-impl TryFrom for Identity {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result {
- 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 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 `` element.
///
/// It should only be used in an ``, as it can only
@@ -385,7 +342,7 @@ mod tests {
};
assert_eq!(
message,
- "Identity must have a non-empty 'category' attribute."
+ "Required attribute 'category' must not be empty."
);
let elem: Element = "".parse().unwrap();
@@ -402,7 +359,7 @@ mod tests {
Error::ParseError(string) => string,
_ => panic!(),
};
- assert_eq!(message, "Identity must have a non-empty 'type' attribute.");
+ assert_eq!(message, "Required attribute 'type' must not be empty.");
}
#[test]
diff --git a/src/util/macros.rs b/src/util/macros.rs
index a67afe1..bc2b834 100644
--- a/src/util/macros.rs
+++ b/src/util/macros.rs
@@ -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) => {
match $elem.attr($attr) {
Some($value) => $func,
@@ -408,6 +427,9 @@ macro_rules! decl_attr {
(Required, $type:ty) => (
$type
);
+ (RequiredNonEmpty, $type:ty) => (
+ $type
+ );
(Default, $type:ty) => (
$type
);