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 );