Detailed changes
@@ -66,16 +66,20 @@ generate_attribute!(Disposition, "disposition", {
generate_id!(ContentId);
-#[derive(Debug, Clone)]
-pub struct Content {
- pub creator: Creator,
- pub disposition: Disposition,
- pub name: ContentId,
- pub senders: Senders,
- pub description: Option<Element>,
- pub transport: Option<Element>,
- pub security: Option<Element>,
-}
+generate_element_with_children!(
+ Content, "content", JINGLE,
+ attributes: [
+ creator: Creator = "creator" => required,
+ disposition: Disposition = "disposition" => default,
+ name: ContentId = "name" => required,
+ senders: Senders = "senders" => default
+ ],
+ children: [
+ description: Option<Element> = ("description", JINGLE) => Element,
+ transport: Option<Element> = ("transport", JINGLE) => Element,
+ security: Option<Element> = ("security", JINGLE) => Element
+ ]
+);
impl Content {
pub fn new(creator: Creator, name: ContentId) -> Content {
@@ -116,61 +120,6 @@ impl Content {
}
}
-impl TryFrom<Element> for Content {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result<Content, Error> {
- check_self!(elem, "content", JINGLE);
- check_no_unknown_attributes!(elem, "content", ["creator", "disposition", "name", "senders"]);
-
- let mut content = Content {
- creator: get_attr!(elem, "creator", required),
- disposition: get_attr!(elem, "disposition", default),
- name: get_attr!(elem, "name", required),
- senders: get_attr!(elem, "senders", default),
- description: None,
- transport: None,
- security: None,
- };
- for child in elem.children() {
- if child.name() == "description" {
- if content.description.is_some() {
- return Err(Error::ParseError("Content must not have more than one description."));
- }
- content.description = Some(child.clone());
- } else if child.name() == "transport" {
- if content.transport.is_some() {
- return Err(Error::ParseError("Content must not have more than one transport."));
- }
- content.transport = Some(child.clone());
- } else if child.name() == "security" {
- if content.security.is_some() {
- return Err(Error::ParseError("Content must not have more than one security."));
- }
- content.security = Some(child.clone());
- } else {
- return Err(Error::ParseError("Unknown child in content element."));
- }
- }
- Ok(content)
- }
-}
-
-impl From<Content> for Element {
- fn from(content: Content) -> Element {
- Element::builder("content")
- .ns(ns::JINGLE)
- .attr("creator", content.creator)
- .attr("disposition", content.disposition)
- .attr("name", content.name)
- .attr("senders", content.senders)
- .append(content.description)
- .append(content.transport)
- .append(content.security)
- .build()
- }
-}
-
#[derive(Debug, Clone, PartialEq)]
pub enum Reason {
AlternativeSession, //(String),
@@ -424,129 +424,96 @@ macro_rules! generate_element_with_text {
);
}
-macro_rules! generate_element_with_children {
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, children: [$($(#[$child_meta:meta])* $child_ident:ident: Vec<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
- generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], children: [$($(#[$child_meta])* $child_ident: Vec<$child_type> = ($child_name, $child_ns) => $child_constructor),+]);
+macro_rules! start_decl {
+ (Vec, $type:ty) => (
+ Vec<$type>
);
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, 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_ns:ident) => $child_constructor:ident),+]) => (
- generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], children: [$($(#[$child_meta])* $child_ident: Vec<$child_type> = ($child_name, $child_ns) => $child_constructor),+]);
+ (Option, $type:ty) => (
+ Option<$type>
);
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, 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_ns:ident) => $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 ::try_from::TryFrom<::minidom::Element> for $elem {
- type Err = ::error::Error;
-
- fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
- check_self!(elem, $name, $ns);
- check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
- let mut parsed_children = vec!();
- for child in elem.children() {
- $(
- if child.is($child_name, ::ns::$child_ns) {
- let parsed_child = $child_constructor::try_from(child.clone())?;
- parsed_children.push(parsed_child);
- continue;
- }
- )*
- return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
- }
- Ok($elem {
- $(
- $attr: get_attr!(elem, $attr_name, $attr_action),
- )*
- $(
- $child_ident: parsed_children,
- )*
- })
- }
- }
+ (Required, $type:ty) => (
+ $type
+ );
+}
- impl From<$elem> for ::minidom::Element {
- fn from(elem: $elem) -> ::minidom::Element {
- ::minidom::Element::builder($name)
- .ns(::ns::$ns)
- $(
- .attr($attr_name, elem.$attr)
- )*
- $(
- .append(elem.$child_ident)
- )*
- .build()
- }
- }
+macro_rules! start_parse_elem {
+ ($temp:ident: Vec) => (
+ let mut $temp = Vec::new();
);
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
- generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], child: ($(#[$child_meta])* $child_ident: Option<$child_type> = ($child_name, $child_ns) => $child_constructor));
+ ($temp:ident: Option) => (
+ let mut $temp = None;
);
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*,], child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
- generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], child: ($(#[$child_meta])* $child_ident: Option<$child_type> = ($child_name, $child_ns) => $child_constructor));
+ ($temp:ident: Required) => (
+ let mut $temp = None;
);
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
- $(#[$meta])*
- #[derive(Debug, Clone)]
- pub struct $elem {
- $(
- $(#[$attr_meta])*
- pub $attr: $attr_type,
- )*
- $(#[$child_meta])*
- pub $child_ident: Option<$child_type>,
- }
+}
- impl ::try_from::TryFrom<::minidom::Element> for $elem {
- type Err = ::error::Error;
+macro_rules! do_parse {
+ ($elem:ident, Element) => (
+ $elem.clone()
+ );
+ ($elem:ident, String) => (
+ $elem.text()
+ );
+ ($elem:ident, $constructor:ident) => (
+ $constructor::try_from($elem.clone())?
+ );
+}
- fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
- check_self!(elem, $name, $ns);
- check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
- let mut parsed_child = None;
- for child in elem.children() {
- if child.is($child_name, ::ns::$child_ns) {
- parsed_child = Some($child_constructor::try_from(child.clone())?);
- continue;
- }
- return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
- }
- Ok($elem {
- $(
- $attr: get_attr!(elem, $attr_name, $attr_action),
- )*
- $child_ident: parsed_child,
- })
- }
+macro_rules! do_parse_elem {
+ ($temp:ident: Vec = $constructor:ident => $elem:ident) => (
+ $temp.push(do_parse!($elem, $constructor));
+ );
+ ($temp:ident: Option = $constructor:ident => $elem:ident) => (
+ if $temp.is_some() {
+ return Err(::error::Error::ParseError(concat!("coucou", " must not have more than one ", "coucou", ".")));
}
+ $temp = Some(do_parse!($elem, $constructor));
+ );
+ ($temp:ident: Required = $constructor:ident => $elem:ident) => (
+ $temp = Some(do_parse!($elem, $constructor));
+ );
+}
- impl From<$elem> for ::minidom::Element {
- fn from(elem: $elem) -> ::minidom::Element {
- ::minidom::Element::builder($name)
- .ns(::ns::$ns)
- $(
- .attr($attr_name, elem.$attr)
- )*
- .append(elem.$child_ident)
- .build()
- }
- }
+macro_rules! finish_parse_elem {
+ ($temp:ident: Vec = $name:tt) => (
+ $temp
+ );
+ ($temp:ident: Option = $name:tt) => (
+ $temp
+ );
+ ($temp:ident: Required = $name:tt) => (
+ $temp.ok_or(::error::Error::ParseError(concat!("Missing child coucou in ", $name, " element.")))?
+ );
+}
+
+macro_rules! generate_serialiser {
+ ($parent:ident, $elem:ident, Required, String, ($name:tt, $ns:ident)) => (
+ ::minidom::Element::builder($name)
+ .ns(::ns::$ns)
+ .append($parent.$elem)
+ .build()
);
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, child: ($(#[$child_meta:meta])* $child_ident:ident: $child_type:ty = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
- generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], child: ($(#[$child_meta])* $child_ident: $child_type = ($child_name, $child_ns) => $child_constructor));
+ ($parent:ident, $elem:ident, Option, String, ($name:tt, $ns:ident)) => (
+ $parent.$elem.map(|elem|
+ ::minidom::Element::builder($name)
+ .ns(::ns::$ns)
+ .append(elem)
+ .build())
);
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*,], child: ($(#[$child_meta:meta])* $child_ident:ident: $child_type:ty = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
- generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], child: ($(#[$child_meta])* $child_ident: $child_type = ($child_name, $child_ns) => $child_constructor));
+ ($parent:ident, $elem:ident, $_:ident, $constructor:ident, ($name:tt, $ns:ident)) => (
+ $parent.$elem
);
- ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], child: ($(#[$child_meta:meta])* $child_ident:ident: $child_type:ty = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
+}
+
+macro_rules! generate_element_with_children {
+ ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, children: [$($(#[$child_meta:meta])* $child_ident:ident: $coucou:tt<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
+ generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], children: [$($(#[$child_meta])* $child_ident: $coucou<$child_type> = ($child_name, $child_ns) => $child_constructor),+]);
+ );
+ ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*,], children: [$($(#[$child_meta:meta])* $child_ident:ident: $coucou:tt<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
+ generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], children: [$($(#[$child_meta])* $child_ident: $coucou<$child_type> = ($child_name, $child_ns) => $child_constructor),+]);
+ );
+ ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], children: [$($(#[$child_meta:meta])* $child_ident:ident: $coucou:tt<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
$(#[$meta])*
#[derive(Debug, Clone)]
pub struct $elem {
@@ -554,8 +521,10 @@ macro_rules! generate_element_with_children {
$(#[$attr_meta])*
pub $attr: $attr_type,
)*
+ $(
$(#[$child_meta])*
- pub $child_ident: $child_type,
+ pub $child_ident: start_decl!($coucou, $child_type),
+ )*
}
impl ::try_from::TryFrom<::minidom::Element> for $elem {
@@ -564,19 +533,25 @@ macro_rules! generate_element_with_children {
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
check_self!(elem, $name, $ns);
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
- let mut parsed_child = None;
+ $(
+ start_parse_elem!($child_ident: $coucou);
+ )*
for child in elem.children() {
+ $(
if child.is($child_name, ::ns::$child_ns) {
- parsed_child = Some($child_constructor::try_from(child.clone())?);
+ do_parse_elem!($child_ident: $coucou = $child_constructor => child);
continue;
}
+ )*
return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
}
Ok($elem {
$(
$attr: get_attr!(elem, $attr_name, $attr_action),
)*
- $child_ident: parsed_child.ok_or(::error::Error::ParseError(concat!("Missing child ", $child_name, " in ", $name, " element.")))?,
+ $(
+ $child_ident: finish_parse_elem!($child_ident: $coucou = $child_name),
+ )*
})
}
}
@@ -588,7 +563,9 @@ macro_rules! generate_element_with_children {
$(
.attr($attr_name, elem.$attr)
)*
- .append(elem.$child_ident)
+ $(
+ .append(generate_serialiser!(elem, $child_ident, $coucou, $child_constructor, ($child_name, $child_ns)))
+ )*
.build()
}
}
@@ -18,13 +18,17 @@ use forwarding::Forwarded;
use ns;
-#[derive(Debug, Clone)]
-pub struct Query {
- pub queryid: Option<String>,
- pub node: Option<String>,
- pub form: Option<DataForm>,
- pub set: Option<Set>,
-}
+generate_element_with_children!(
+ Query, "query", MAM,
+ attributes: [
+ queryid: Option<String> = "queryid" => optional,
+ node: Option<String> = "node" => optional
+ ],
+ children: [
+ form: Option<DataForm> = ("x", DATA_FORMS) => DataForm,
+ set: Option<Set> = ("set", RSM) => Set
+ ]
+);
impl IqGetPayload for Query {}
impl IqSetPayload for Query {}
@@ -36,16 +40,24 @@ generate_element_with_children!(
id: String = "id" => required,
queryid: String = "queryid" => required,
],
- child: (
- forwarded: Forwarded = ("forwarded", FORWARD) => Forwarded
- )
+ children: [
+ forwarded: Required<Forwarded> = ("forwarded", FORWARD) => Forwarded
+ ]
);
-#[derive(Debug, Clone)]
-pub struct Fin {
- pub complete: bool,
- pub set: Set,
-}
+generate_attribute!(
+ Complete, "complete", bool
+);
+
+generate_element_with_children!(
+ Fin, "fin", MAM,
+ attributes: [
+ complete: Complete = "complete" => default
+ ],
+ children: [
+ set: Required<Set> = ("set", RSM) => Set
+ ]
+);
impl IqResultPayload for Fin {}
@@ -66,54 +78,6 @@ impl IqGetPayload for Prefs {}
impl IqSetPayload for Prefs {}
impl IqResultPayload for Prefs {}
-impl TryFrom<Element> for Query {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result<Query, Error> {
- check_self!(elem, "query", MAM);
- check_no_unknown_attributes!(elem, "query", ["queryid", "node"]);
- let mut form = None;
- let mut set = None;
- for child in elem.children() {
- if child.is("x", ns::DATA_FORMS) {
- form = Some(DataForm::try_from(child.clone())?);
- } else if child.is("set", ns::RSM) {
- set = Some(Set::try_from(child.clone())?);
- } else {
- return Err(Error::ParseError("Unknown child in query element."));
- }
- }
- let queryid = get_attr!(elem, "queryid", optional);
- let node = get_attr!(elem, "node", optional);
- Ok(Query { queryid, node, form, set })
- }
-}
-
-impl TryFrom<Element> for Fin {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result<Fin, Error> {
- check_self!(elem, "fin", MAM);
- check_no_unknown_attributes!(elem, "fin", ["complete"]);
- let mut set = None;
- for child in elem.children() {
- if child.is("set", ns::RSM) {
- set = Some(Set::try_from(child.clone())?);
- } else {
- return Err(Error::ParseError("Unknown child in fin element."));
- }
- }
- let set = set.ok_or(Error::ParseError("Mandatory set element missing in fin."))?;
- let complete = match elem.attr("complete") {
- Some(complete) if complete == "true" => true,
- Some(complete) if complete == "false" => false,
- None => false,
- Some(_) => return Err(Error::ParseError("Invalid value for 'complete' attribute.")),
- };
- Ok(Fin { complete, set })
- }
-}
-
impl TryFrom<Element> for Prefs {
type Err = Error;
@@ -146,28 +110,6 @@ impl TryFrom<Element> for Prefs {
}
}
-impl From<Query> for Element {
- fn from(query: Query) -> Element {
- Element::builder("query")
- .ns(ns::MAM)
- .attr("queryid", query.queryid)
- .attr("node", query.node)
- //.append(query.form)
- .append(query.set)
- .build()
- }
-}
-
-impl From<Fin> for Element {
- fn from(fin: Fin) -> Element {
- Element::builder("fin")
- .ns(ns::MAM)
- .attr("complete", if fin.complete { Some("true") } else { None })
- .append(fin.set)
- .build()
- }
-}
-
fn serialise_jid_list(name: &str, jids: Vec<Jid>) -> Option<Element> {
if jids.is_empty() {
None
@@ -5,53 +5,18 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-use try_from::TryFrom;
-
-use minidom::Element;
-
-use error::Error;
-
-use ns;
-
-#[derive(Debug, Clone)]
-pub struct Muc {
- pub password: Option<String>,
-}
-
-impl TryFrom<Element> for Muc {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result<Muc, Error> {
- check_self!(elem, "x", MUC);
- check_no_attributes!(elem, "x");
-
- let mut password = None;
- for child in elem.children() {
- if child.is("password", ns::MUC) {
- password = Some(child.text());
- } else {
- return Err(Error::ParseError("Unknown child in x element."));
- }
- }
-
- Ok(Muc {
- password: password,
- })
- }
-}
-
-impl From<Muc> for Element {
- fn from(muc: Muc) -> Element {
- Element::builder("x")
- .ns(ns::MUC)
- .append(muc.password)
- .build()
- }
-}
+generate_element_with_children!(
+ Muc, "x", MUC, children: [
+ password: Option<String> = ("password", MUC) => String
+ ]
+);
#[cfg(test)]
mod tests {
use super::*;
+ use try_from::TryFrom;
+ use minidom::Element;
+ use error::Error;
use compare_elements::NamespaceAwareCompare;
#[test]
@@ -5,7 +5,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-use try_from::{TryFrom, TryInto};
+use try_from::TryFrom;
use minidom::Element;
@@ -80,6 +80,7 @@ Status, "status", MUC_USER, "code", {
/// 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
/// purposes. -- CHANGELOG 0.17 (2002-10-23)
+///
/// Possesses a 'jid' and a 'nick' attribute, so that an action can be attributed either to a real
/// JID or to a roomnick. -- CHANGELOG 1.25 (2012-02-08)
#[derive(Debug, Clone, PartialEq)]
@@ -140,108 +141,25 @@ generate_attribute!(Role, "role", {
None => "none",
}, Default = None);
-#[derive(Debug, Clone)]
-pub struct Item {
- pub affiliation: Affiliation,
- pub jid: Option<Jid>,
- pub nick: Option<String>,
- pub role: Role,
- pub actor: Option<Actor>,
- pub continue_: Option<Continue>,
- pub reason: Option<Reason>,
-}
-
-impl TryFrom<Element> for Item {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result<Item, Error> {
- check_self!(elem, "item", MUC_USER);
- check_no_unknown_attributes!(elem, "item", ["affiliation", "jid", "nick", "role"]);
- let mut actor: Option<Actor> = None;
- let mut continue_: Option<Continue> = None;
- let mut reason: Option<Reason> = None;
- for child in elem.children() {
- if child.is("actor", ns::MUC_USER) {
- actor = Some(child.clone().try_into()?);
- } else if child.is("continue", ns::MUC_USER) {
- continue_ = Some(child.clone().try_into()?);
- } else if child.is("reason", ns::MUC_USER) {
- reason = Some(child.clone().try_into()?);
- } else {
- return Err(Error::ParseError("Unknown child in item element."));
- }
- }
-
- let affiliation: Affiliation = get_attr!(elem, "affiliation", required);
- let jid: Option<Jid> = get_attr!(elem, "jid", optional);
- let nick: Option<String> = get_attr!(elem, "nick", optional);
- let role: Role = get_attr!(elem, "role", required);
-
- Ok(Item{
- affiliation: affiliation,
- jid: jid,
- nick: nick,
- role: role,
- actor: actor,
- continue_: continue_,
- reason: reason,
- })
- }
-}
-
-impl From<Item> for Element {
- fn from(item: Item) -> Element {
- Element::builder("item")
- .ns(ns::MUC_USER)
- .attr("affiliation", item.affiliation)
- .attr("jid", item.jid)
- .attr("nick", item.nick)
- .attr("role", item.role)
- .append(item.actor)
- .append(item.continue_)
- .append(item.reason)
- .build()
- }
-}
-
-#[derive(Debug, Clone)]
-pub struct MucUser {
- pub status: Vec<Status>,
- pub items: Vec<Item>,
-}
-
-impl TryFrom<Element> for MucUser {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result<MucUser, Error> {
- check_self!(elem, "x", MUC_USER);
- check_no_attributes!(elem, "x");
- let mut status = vec!();
- let mut items = vec!();
- for child in elem.children() {
- if child.is("status", ns::MUC_USER) {
- status.push(Status::try_from(child.clone())?);
- } else if child.is("item", ns::MUC_USER) {
- items.push(Item::try_from(child.clone())?);
- } else {
- return Err(Error::ParseError("Unknown child in x element."));
- }
- }
- Ok(MucUser {
- status,
- items,
- })
- }
-}
-
-impl From<MucUser> for Element {
- fn from(muc_user: MucUser) -> Element {
- Element::builder("x")
- .ns(ns::MUC_USER)
- .append(muc_user.status)
- .build()
- }
-}
+generate_element_with_children!(
+ Item, "item", MUC_USER, attributes: [
+ affiliation: Affiliation = "affiliation" => required,
+ jid: Option<Jid> = "jid" => optional,
+ nick: Option<String> = "nick" => optional,
+ role: Role = "role" => required
+ ], children: [
+ actor: Option<Actor> = ("actor", MUC_USER) => Actor,
+ continue_: Option<Continue> = ("continue", MUC_USER) => Continue,
+ reason: Option<Reason> = ("reason", MUC_USER) => Reason
+ ]
+);
+
+generate_element_with_children!(
+ MucUser, "x", MUC_USER, children: [
+ status: Vec<Status> = ("status", MUC_USER) => Status,
+ items: Vec<Item> = ("item", MUC_USER) => Item
+ ]
+);
#[cfg(test)]
mod tests {
@@ -257,6 +175,24 @@ mod tests {
MucUser::try_from(elem).unwrap();
}
+ #[test]
+ fn statuses_and_items() {
+ let elem: Element = "
+ <x xmlns='http://jabber.org/protocol/muc#user'>
+ <status code='101'/>
+ <status code='102'/>
+ <item affiliation='member' role='moderator'/>
+ </x>
+ ".parse().unwrap();
+ let muc_user = MucUser::try_from(elem).unwrap();
+ assert_eq!(muc_user.status.len(), 2);
+ assert_eq!(muc_user.status[0], Status::AffiliationChange);
+ assert_eq!(muc_user.status[1], Status::ConfigShowsUnavailableMembers);
+ assert_eq!(muc_user.items.len(), 1);
+ assert_eq!(muc_user.items[0].affiliation, Affiliation::Member);
+ assert_eq!(muc_user.items[0].role, Role::Moderator);
+ }
+
#[test]
fn test_invalid_child() {
let elem: Element = "
@@ -72,10 +72,10 @@ generate_element_with_only_attributes!(
generate_element_with_children!(
/// Request to configure a new node.
Configure, "configure", PUBSUB,
- child: (
+ children: [
/// The form to configure it.
form: Option<DataForm> = ("x", DATA_FORMS) => DataForm
- )
+ ]
);
generate_element_with_only_attributes!(
@@ -168,10 +168,10 @@ generate_element_with_children!(
/// The subscription identifier affected by this request.
subid: Option<SubscriptionId> = "subid" => optional,
],
- child: (
+ children: [
/// The form describing the subscription.
form: Option<DataForm> = ("x", DATA_FORMS) => DataForm
- )
+ ]
);
generate_element_with_children!(
@@ -190,10 +190,10 @@ generate_element_with_children!(
generate_element_with_children!(
/// The options associated to a publish request.
PublishOptions, "publish-options", PUBSUB,
- child: (
+ children: [
/// The form describing these options.
form: Option<DataForm> = ("x", DATA_FORMS) => DataForm
- )
+ ]
);
generate_attribute!(
@@ -300,10 +300,10 @@ generate_element_with_children!(
/// The state of the subscription.
subscription: Option<Subscription> = "subscription" => optional,
],
- child: (
+ children: [
/// The options related to this subscription.
subscribe_options: Option<SubscribeOptions> = ("subscribe-options", PUBSUB) => SubscribeOptions
- )
+ ]
);
generate_element_with_only_attributes!(
@@ -62,10 +62,10 @@ generate_element_with_children!(
attributes: [
h: Option<u32> = "h" => optional,
],
- child: (
+ children: [
// XXX: implement the * handling.
error: Option<DefinedCondition> = ("*", XMPP_STANZAS) => DefinedCondition
- )
+ ]
);
generate_empty_element!(
@@ -4,84 +4,25 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-use try_from::TryFrom;
-use minidom::Element;
-use error::Error;
-use ns;
use iq::{IqGetPayload, IqResultPayload};
-#[derive(Debug, Clone)]
-pub struct Version {
- pub name: String,
- pub version: String,
- pub os: Option<String>,
-}
+generate_element_with_children!(
+ Version, "query", VERSION,
+ children: [
+ name: Required<String> = ("name", VERSION) => String,
+ version: Required<String> = ("version", VERSION) => String,
+ os: Option<String> = ("os", VERSION) => String
+ ]
+);
impl IqGetPayload for Version {}
impl IqResultPayload for Version {}
-impl TryFrom<Element> for Version {
- type Err = Error;
-
- fn try_from(elem: Element) -> Result<Version, Error> {
- check_self!(elem, "query", VERSION, "version");
- check_no_attributes!(elem, "version");
- let mut name = None;
- let mut version = None;
- let mut os = None;
- for child in elem.children() {
- if child.is("name", ns::VERSION) {
- if name.is_some() {
- return Err(Error::ParseError("More than one name in version element."));
- }
- name = Some(child.text());
- } else if child.is("version", ns::VERSION) {
- if version.is_some() {
- return Err(Error::ParseError("More than one version in version element."));
- }
- version = Some(child.text());
- } else if child.is("os", ns::VERSION) {
- if os.is_some() {
- return Err(Error::ParseError("More than one os in version element."));
- }
- os = Some(child.text());
- } else {
- return Err(Error::ParseError("Unknown child in version element."));
- }
- }
- let name = name.unwrap();
- let version = version.unwrap();
- Ok(Version {
- name,
- version,
- os,
- })
- }
-}
-
-impl From<Version> for Element {
- fn from(version: Version) -> Element {
- Element::builder("query")
- .ns(ns::VERSION)
- .append(Element::builder("name")
- .ns(ns::VERSION)
- .append(version.name)
- .build())
- .append(Element::builder("version")
- .ns(ns::VERSION)
- .append(version.version)
- .build())
- .append(Element::builder("os")
- .ns(ns::VERSION)
- .append(version.os)
- .build())
- .build()
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
+ use try_from::TryFrom;
+ use minidom::Element;
use compare_elements::NamespaceAwareCompare;
#[test]