mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
Implement macro for elements containing children
This commit is contained in:
parent
77e150c63d
commit
3e37beffe2
2 changed files with 68 additions and 46 deletions
58
src/disco.rs
58
src/disco.rs
|
@ -201,52 +201,22 @@ Item, "item", ns::DISCO_ITEMS, [
|
||||||
name: Option<String> = "name" => optional,
|
name: Option<String> = "name" => optional,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/// Structure representing a `<query
|
generate_element_with_children!(
|
||||||
/// xmlns='http://jabber.org/protocol/disco#items'/>` element.
|
/// Structure representing a `<query
|
||||||
///
|
/// xmlns='http://jabber.org/protocol/disco#items'/>` element.
|
||||||
/// It should only be used in an `<iq type='result'/>`, as it can only
|
///
|
||||||
/// represent the result, and not a request.
|
/// It should only be used in an `<iq type='result'/>`, as it can only
|
||||||
#[derive(Debug, Clone)]
|
/// represent the result, and not a request.
|
||||||
pub struct DiscoItemsResult {
|
DiscoItemsResult, "query", ns::DISCO_ITEMS,
|
||||||
|
attributes: [
|
||||||
/// Node on which we have done this discovery.
|
/// Node on which we have done this discovery.
|
||||||
pub node: Option<String>,
|
node: Option<String> = "node" => optional
|
||||||
|
],
|
||||||
|
children: [
|
||||||
/// List of items pointed by this entity.
|
/// List of items pointed by this entity.
|
||||||
pub items: Vec<Item>,
|
items: Vec<Item> = "item" => Item
|
||||||
}
|
]
|
||||||
|
);
|
||||||
impl TryFrom<Element> for DiscoItemsResult {
|
|
||||||
type Err = Error;
|
|
||||||
|
|
||||||
fn try_from(elem: Element) -> Result<DiscoItemsResult, Error> {
|
|
||||||
check_self!(elem, "query", ns::DISCO_ITEMS, "disco#items query");
|
|
||||||
check_no_unknown_attributes!(elem, "disco#items query", ["node"]);
|
|
||||||
|
|
||||||
let mut items: Vec<Item> = vec!();
|
|
||||||
for child in elem.children() {
|
|
||||||
if child.is("item", ns::DISCO_ITEMS) {
|
|
||||||
items.push(Item::try_from(child.clone())?);
|
|
||||||
} else {
|
|
||||||
return Err(Error::ParseError("Unknown element in disco#items."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(DiscoItemsResult {
|
|
||||||
node: get_attr!(elem, "node", optional),
|
|
||||||
items: items,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DiscoItemsResult> for Element {
|
|
||||||
fn from(disco: DiscoItemsResult) -> Element {
|
|
||||||
Element::builder("query")
|
|
||||||
.ns(ns::DISCO_ITEMS)
|
|
||||||
.attr("node", disco.node)
|
|
||||||
.append(disco.items)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -293,3 +293,55 @@ macro_rules! generate_element_with_text {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_element_with_children {
|
||||||
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:expr, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),+], children: [$($(#[$child_meta:meta])* $child_ident:ident: Vec<$child_type:ty> = $child_name:tt => $child_constructor:ident),+]) => (
|
||||||
|
$(#[$meta])*
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct $elem {
|
||||||
|
$(
|
||||||
|
$(#[$attr_meta])*
|
||||||
|
pub $attr: $attr_type
|
||||||
|
),*,
|
||||||
|
$(
|
||||||
|
$(#[$child_meta])*
|
||||||
|
pub $child_ident: Vec<$child_type>
|
||||||
|
),*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Element> for $elem {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn try_from(elem: Element) -> Result<$elem, Error> {
|
||||||
|
check_self!(elem, $name, $ns);
|
||||||
|
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
|
||||||
|
let mut parsed_children = vec!();
|
||||||
|
for child in elem.children() {
|
||||||
|
$(
|
||||||
|
let parsed_child = $child_constructor::try_from(child.clone())?;
|
||||||
|
parsed_children.push(parsed_child);
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
Ok($elem {
|
||||||
|
$(
|
||||||
|
$attr: get_attr!(elem, $attr_name, $attr_action)
|
||||||
|
),*,
|
||||||
|
$(
|
||||||
|
$child_ident: parsed_children
|
||||||
|
)*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<$elem> for Element {
|
||||||
|
fn from(elem: $elem) -> Element {
|
||||||
|
Element::builder($name)
|
||||||
|
.ns($ns)
|
||||||
|
$(
|
||||||
|
.attr($attr_name, elem.$attr)
|
||||||
|
)*
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue