diff --git a/Cargo.toml b/Cargo.toml index fba43cb4..6690ccf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,8 @@ license = "MPL-2.0" edition = "2018" [dependencies] -minidom = "0.10.0" -jid = { version = "0.6.0", features = ["minidom"] } +minidom = "0.11.0" +jid = { version = "0.7.0", features = ["minidom"] } base64 = "0.10" digest = "0.8" sha-1 = "0.8" diff --git a/src/bind.rs b/src/bind.rs index 357a7326..17e1e124 100644 --- a/src/bind.rs +++ b/src/bind.rs @@ -63,13 +63,13 @@ impl From for Element { fn from(bind: BindQuery) -> Element { Element::builder("bind") .ns(ns::BIND) - .append(match bind.resource { + .append_all((match bind.resource { None => vec![], Some(resource) => vec![Element::builder("resource") .ns(ns::BIND) .append(resource) .build()], - }) + }).into_iter()) .build() } } diff --git a/src/blocking.rs b/src/blocking.rs index f218b21d..f9e6a821 100644 --- a/src/blocking.rs +++ b/src/blocking.rs @@ -51,12 +51,12 @@ macro_rules! generate_blocking_element { fn from(elem: $elem) -> Element { Element::builder($name) .ns(ns::BLOCKING) - .append(elem.items.into_iter().map(|jid| { + .append_all(elem.items.into_iter().map(|jid| { Element::builder("item") .ns(ns::BLOCKING) .attr("jid", jid) .build() - }).collect::>()) + })) .build() } } diff --git a/src/data_forms.rs b/src/data_forms.rs index 323e91ed..f252bb71 100644 --- a/src/data_forms.rs +++ b/src/data_forms.rs @@ -7,7 +7,7 @@ use crate::util::error::Error; use crate::media_element::MediaElement; use crate::ns; -use minidom::Element; +use minidom::{Element, Node}; use std::convert::TryFrom; generate_element!( @@ -152,13 +152,13 @@ impl From for Element { .attr("var", field.var) .attr("type", field.type_) .attr("label", field.label) - .append(if field.required { + .append_all((if field.required { Some(Element::builder("required").ns(ns::DATA_FORMS).build()) } else { None - }) - .append(field.options) - .append( + }).into_iter()) + .append_all(field.options.iter().cloned().map(Element::from).map(Node::Element).into_iter()) + .append_all( field .values .into_iter() @@ -168,9 +168,8 @@ impl From for Element { .append(value) .build() }) - .collect::>(), ) - .append(field.media) + .append_all(field.media.iter().cloned().map(Element::from).map(Node::Element)) .build() } } @@ -275,21 +274,21 @@ impl From for Element { Element::builder("x") .ns(ns::DATA_FORMS) .attr("type", form.type_) - .append( + .append_all( form.title .map(|title| Element::builder("title").ns(ns::DATA_FORMS).append(title)), ) - .append(form.instructions.map(|text| { + .append_all(form.instructions.map(|text| { Element::builder("instructions") .ns(ns::DATA_FORMS) .append(text) })) - .append(if let Some(form_type) = form.form_type { + .append_all((if let Some(form_type) = form.form_type { vec![Element::builder("field").ns(ns::DATA_FORMS).attr("var", "FORM_TYPE").attr("type", "hidden").append(Element::builder("value").ns(ns::DATA_FORMS).append(form_type).build()).build()] } else { vec![] - }) - .append(form.fields) + }).into_iter()) + .append_all(form.fields.iter().cloned().map(Element::from).map(Node::Element)) .build() } } diff --git a/src/date.rs b/src/date.rs index e5fd67e8..bfcf4e16 100644 --- a/src/date.rs +++ b/src/date.rs @@ -6,7 +6,7 @@ use crate::util::error::Error; use chrono::{DateTime as ChronoDateTime, FixedOffset}; -use minidom::{ElementEmitter, IntoAttributeValue, IntoElements}; +use minidom::{IntoAttributeValue, Node}; use std::str::FromStr; /// Implements the DateTime profile of XEP-0082, which represents a @@ -46,9 +46,9 @@ impl IntoAttributeValue for DateTime { } } -impl IntoElements for DateTime { - fn into_elements(self, emitter: &mut ElementEmitter) { - emitter.append_text_node(self.0.to_rfc3339()) +impl Into for DateTime { + fn into(self) -> Node { + Node::Text(self.0.to_rfc3339()) } } diff --git a/src/disco.rs b/src/disco.rs index abf0e238..3c2cde13 100644 --- a/src/disco.rs +++ b/src/disco.rs @@ -9,7 +9,7 @@ use crate::util::error::Error; use crate::iq::{IqGetPayload, IqResultPayload}; use crate::ns; use jid::Jid; -use minidom::Element; +use minidom::{Element, Node}; use std::convert::TryFrom; generate_element!( @@ -178,9 +178,9 @@ impl From for Element { Element::builder("query") .ns(ns::DISCO_INFO) .attr("node", disco.node) - .append(disco.identities) - .append(disco.features) - .append(disco.extensions) + .append_all(disco.identities.into_iter()) + .append_all(disco.features.into_iter()) + .append_all(disco.extensions.iter().cloned().map(Element::from).map(Node::Element)) .build() } } diff --git a/src/ibr.rs b/src/ibr.rs index 8ddca59d..d539f2ad 100644 --- a/src/ibr.rs +++ b/src/ibr.rs @@ -8,7 +8,7 @@ use crate::data_forms::DataForm; use crate::util::error::Error; use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload}; use crate::ns; -use minidom::Element; +use minidom::{Element, Node}; use std::collections::HashMap; use std::convert::TryFrom; @@ -93,24 +93,23 @@ impl From for Element { fn from(query: Query) -> Element { Element::builder("query") .ns(ns::REGISTER) - .append(if query.registered { + .append_all((if query.registered { Some(Element::builder("registered").ns(ns::REGISTER)) } else { None - }) - .append( + }).into_iter()) + .append_all( query .fields .into_iter() .map(|(name, value)| Element::builder(name).ns(ns::REGISTER).append(value)) - .collect::>(), ) - .append(if query.remove { + .append_all((if query.remove { Some(Element::builder("remove").ns(ns::REGISTER)) } else { None - }) - .append(query.form) + }).into_iter()) + .append_all(query.form.map(Element::from).map(Node::Element).into_iter()) .build() } } diff --git a/src/jingle.rs b/src/jingle.rs index 98e5fcbb..55a493ef 100644 --- a/src/jingle.rs +++ b/src/jingle.rs @@ -8,7 +8,7 @@ use crate::util::error::Error; use crate::iq::IqSetPayload; use crate::ns; use jid::Jid; -use minidom::Element; +use minidom::{Element, Node}; use std::collections::BTreeMap; use std::str::FromStr; use std::convert::TryFrom; @@ -413,14 +413,14 @@ impl From for Element { Element::builder("reason") .ns(ns::JINGLE) .append(Element::from(reason.reason)) - .append( + .append_all( reason.texts.into_iter().map(|(lang, text)| { Element::builder("text") .ns(ns::JINGLE) .attr("xml:lang", lang) .append(text) .build() - }).collect::>()) + })) .build() } } @@ -542,8 +542,8 @@ impl From for Element { .attr("initiator", jingle.initiator) .attr("responder", jingle.responder) .attr("sid", jingle.sid) - .append(jingle.contents) - .append(jingle.reason) + .append_all(jingle.contents.into_iter()) + .append_all(jingle.reason.map(Element::from).map(Node::Element).into_iter()) .build() } } diff --git a/src/jingle_ft.rs b/src/jingle_ft.rs index f0b7cf32..b3da6f8b 100644 --- a/src/jingle_ft.rs +++ b/src/jingle_ft.rs @@ -9,7 +9,7 @@ use crate::util::error::Error; use crate::hashes::Hash; use crate::jingle::{ContentId, Creator}; use crate::ns; -use minidom::Element; +use minidom::{Element, Node}; use std::collections::BTreeMap; use std::str::FromStr; use std::convert::TryFrom; @@ -196,43 +196,53 @@ impl From for Element { let mut root = Element::builder("file").ns(ns::JINGLE_FT); if let Some(date) = file.date { root = root.append( - Element::builder("date") - .ns(ns::JINGLE_FT) - .append(date) - .build(), + Node::Element( + Element::builder("date") + .ns(ns::JINGLE_FT) + .append(date) + .build() + ) ); } if let Some(media_type) = file.media_type { root = root.append( - Element::builder("media-type") - .ns(ns::JINGLE_FT) - .append(media_type) - .build(), + Node::Element( + Element::builder("media-type") + .ns(ns::JINGLE_FT) + .append(media_type) + .build() + ) ); } if let Some(name) = file.name { root = root.append( - Element::builder("name") - .ns(ns::JINGLE_FT) - .append(name) - .build(), + Node::Element( + Element::builder("name") + .ns(ns::JINGLE_FT) + .append(name) + .build() + ) ); } for (lang, desc) in file.descs.into_iter() { root = root.append( - Element::builder("desc") - .ns(ns::JINGLE_FT) - .attr("xml:lang", lang) - .append(desc.0) - .build(), + Node::Element( + Element::builder("desc") + .ns(ns::JINGLE_FT) + .attr("xml:lang", lang) + .append(desc.0) + .build() + ) ); } if let Some(size) = file.size { root = root.append( - Element::builder("size") - .ns(ns::JINGLE_FT) - .append(format!("{}", size)) - .build(), + Node::Element( + Element::builder("size") + .ns(ns::JINGLE_FT) + .append(format!("{}", size)) + .build() + ) ); } if let Some(range) = file.range { @@ -282,7 +292,7 @@ impl From for Element { fn from(description: Description) -> Element { Element::builder("description") .ns(ns::JINGLE_FT) - .append(description.file) + .append(Node::Element(description.file.into())) .build() } } @@ -334,7 +344,7 @@ impl From for Element { .ns(ns::JINGLE_FT) .attr("name", checksum.name) .attr("creator", checksum.creator) - .append(checksum.file) + .append(Node::Element(checksum.file.into())) .build() } } diff --git a/src/jingle_s5b.rs b/src/jingle_s5b.rs index 969b83f3..0f246691 100644 --- a/src/jingle_s5b.rs +++ b/src/jingle_s5b.rs @@ -247,26 +247,31 @@ impl From for Element { .attr("sid", transport.sid) .attr("dstaddr", transport.dstaddr) .attr("mode", transport.mode) - .append(match transport.payload { + .append_all(match transport.payload { TransportPayload::Candidates(candidates) => candidates .into_iter() .map(Element::from) - .collect::>(), + .collect::>() + .into_iter(), TransportPayload::Activated(cid) => vec![Element::builder("activated") .ns(ns::JINGLE_S5B) .attr("cid", cid) - .build()], + .build()] + .into_iter(), TransportPayload::CandidateError => vec![Element::builder("candidate-error") .ns(ns::JINGLE_S5B) - .build()], + .build()] + .into_iter(), TransportPayload::CandidateUsed(cid) => vec![Element::builder("candidate-used") .ns(ns::JINGLE_S5B) .attr("cid", cid) - .build()], - TransportPayload::ProxyError => { - vec![Element::builder("proxy-error").ns(ns::JINGLE_S5B).build()] - } - TransportPayload::None => vec![], + .build()] + .into_iter(), + TransportPayload::ProxyError => vec![Element::builder("proxy-error") + .ns(ns::JINGLE_S5B) + .build()] + .into_iter(), + TransportPayload::None => vec![].into_iter(), }) .build() } diff --git a/src/mam.rs b/src/mam.rs index 6889f2ed..edc0116c 100644 --- a/src/mam.rs +++ b/src/mam.rs @@ -13,7 +13,7 @@ use crate::ns; use crate::pubsub::NodeName; use crate::rsm::{SetQuery, SetResult}; use jid::Jid; -use minidom::Element; +use minidom::{Element, Node}; use std::convert::TryFrom; generate_id!( @@ -161,20 +161,29 @@ impl TryFrom for Prefs { } } -fn serialise_jid_list(name: &str, jids: Vec) -> Option { +fn serialise_jid_list(name: &str, jids: Vec) -> ::std::option::IntoIter { if jids.is_empty() { - None + None.into_iter() } else { Some( Element::builder(name) .ns(ns::MAM) - .append( + .append_all( jids.into_iter() - .map(|jid| Element::builder("jid").ns(ns::MAM).append(jid).build()) - .collect::>(), + .map(|jid| + Node::Element( + Element::builder("jid") + .ns(ns::MAM) + .append(Node::Text(String::from(jid))) + .build() + .into() + ) + ) + .into_iter(), ) - .build(), - ) + .build() + .into(), + ).into_iter() } } @@ -183,8 +192,8 @@ impl From for Element { Element::builder("prefs") .ns(ns::MAM) .attr("default", prefs.default_) - .append(serialise_jid_list("always", prefs.always)) - .append(serialise_jid_list("never", prefs.never)) + .append_all(serialise_jid_list("always", prefs.always)) + .append_all(serialise_jid_list("never", prefs.never)) .build() } } diff --git a/src/message.rs b/src/message.rs index f9bae2b1..4a78c6c0 100644 --- a/src/message.rs +++ b/src/message.rs @@ -212,7 +212,7 @@ impl From for Element { .attr("to", message.to) .attr("id", message.id) .attr("type", message.type_) - .append( + .append_all( message .subjects .into_iter() @@ -227,9 +227,8 @@ impl From for Element { ); subject }) - .collect::>(), ) - .append( + .append_all( message .bodies .into_iter() @@ -244,9 +243,8 @@ impl From for Element { ); body }) - .collect::>(), ) - .append(message.payloads) + .append_all(message.payloads.into_iter()) .build() } } diff --git a/src/presence.rs b/src/presence.rs index ffb734c5..4aad1622 100644 --- a/src/presence.rs +++ b/src/presence.rs @@ -8,7 +8,7 @@ use crate::util::error::Error; use crate::ns; use jid::Jid; -use minidom::{Element, ElementEmitter, IntoAttributeValue, IntoElements}; +use minidom::{Element, IntoAttributeValue, Node}; use std::collections::BTreeMap; use std::str::FromStr; use std::convert::TryFrom; @@ -48,18 +48,17 @@ impl FromStr for Show { } } -impl IntoElements for Show { - fn into_elements(self, emitter: &mut ElementEmitter) { - emitter.append_child( - Element::builder("show") - .append(match self { - Show::Away => Some("away"), - Show::Chat => Some("chat"), - Show::Dnd => Some("dnd"), - Show::Xa => Some("xa"), - }) - .build(), - ) +impl Into for Show { + fn into(self) -> Node { + Element::builder("show") + .append(match self { + Show::Away => "away", + Show::Chat => "chat", + Show::Dnd => "dnd", + Show::Xa => "xa", + }) + .build() + .into() } } @@ -310,8 +309,8 @@ impl From for Element { .attr("to", presence.to) .attr("id", presence.id) .attr("type", presence.type_) - .append(presence.show) - .append( + .append_all(presence.show.into_iter()) + .append_all( presence .statuses .into_iter() @@ -327,9 +326,8 @@ impl From for Element { .append(status) .build() }) - .collect::>(), ) - .append(if presence.priority == 0 { + .append_all((if presence.priority == 0 { None } else { Some( @@ -337,8 +335,8 @@ impl From for Element { .append(format!("{}", presence.priority)) .build() ) - }) - .append(presence.payloads) + }).into_iter()) + .append_all(presence.payloads.into_iter()) .build() } } diff --git a/src/pubsub/event.rs b/src/pubsub/event.rs index 5d65eb78..9327c50b 100644 --- a/src/pubsub/event.rs +++ b/src/pubsub/event.rs @@ -10,7 +10,7 @@ use crate::util::error::Error; use crate::ns; use crate::pubsub::{ItemId, NodeName, Subscription, SubscriptionId, Item as PubSubItem}; use jid::Jid; -use minidom::Element; +use minidom::{Element, Node}; use std::convert::TryFrom; /// Event wrapper for a PubSub ``. @@ -198,12 +198,12 @@ impl From for Element { PubSubEvent::Configuration { node, form } => Element::builder("configuration") .ns(ns::PUBSUB_EVENT) .attr("node", node) - .append(form) + .append_all(form.map(Element::from).map(Node::Element).into_iter()) .build(), PubSubEvent::Delete { node, redirect } => Element::builder("purge") .ns(ns::PUBSUB_EVENT) .attr("node", node) - .append(redirect.map(|redirect| { + .append_all(redirect.map(|redirect| { Element::builder("redirect") .ns(ns::PUBSUB_EVENT) .attr("uri", redirect) @@ -213,12 +213,12 @@ impl From for Element { PubSubEvent::PublishedItems { node, items } => Element::builder("items") .ns(ns::PUBSUB_EVENT) .attr("node", node) - .append(items) + .append_all(items.into_iter()) .build(), PubSubEvent::RetractedItems { node, items } => Element::builder("items") .ns(ns::PUBSUB_EVENT) .attr("node", node) - .append( + .append_all( items .into_iter() .map(|id| { @@ -227,7 +227,6 @@ impl From for Element { .attr("id", id) .build() }) - .collect::>(), ) .build(), PubSubEvent::Purge { node } => Element::builder("purge") diff --git a/src/pubsub/pubsub.rs b/src/pubsub/pubsub.rs index 0e166bd3..c49d5fbf 100644 --- a/src/pubsub/pubsub.rs +++ b/src/pubsub/pubsub.rs @@ -219,11 +219,11 @@ impl From for Element { fn from(subscribe_options: SubscribeOptions) -> Element { Element::builder("subscribe-options") .ns(ns::PUBSUB) - .append(if subscribe_options.required { + .append_all((if subscribe_options.required { vec![Element::builder("required").ns(ns::PUBSUB).build()] } else { vec![] - }) + }).into_iter()) .build() } } @@ -473,7 +473,7 @@ impl From for Element { fn from(pubsub: PubSub) -> Element { Element::builder("pubsub") .ns(ns::PUBSUB) - .append(match pubsub { + .append_all((match pubsub { PubSub::Create { create, configure } => { let mut elems = vec![Element::from(create)]; if let Some(configure) = configure { @@ -498,7 +498,7 @@ impl From for Element { PubSub::Subscription(subscription) => vec![Element::from(subscription)], PubSub::Subscriptions(subscriptions) => vec![Element::from(subscriptions)], PubSub::Unsubscribe(unsubscribe) => vec![Element::from(unsubscribe)], - }) + }).into_iter()) .build() } } diff --git a/src/rsm.rs b/src/rsm.rs index a4f97365..691e5e98 100644 --- a/src/rsm.rs +++ b/src/rsm.rs @@ -6,7 +6,7 @@ use crate::util::error::Error; use crate::ns; -use minidom::Element; +use minidom::{Element, Node}; use std::convert::TryFrom; /// Requests paging through a potentially big set of items (represented by an @@ -72,23 +72,23 @@ impl From for Element { fn from(set: SetQuery) -> Element { Element::builder("set") .ns(ns::RSM) - .append(set.max.map(|max| { + .append_all(set.max.map(|max| { Element::builder("max") .ns(ns::RSM) .append(format!("{}", max)) .build() })) - .append( + .append_all( set.after .map(|after| Element::builder("after").ns(ns::RSM).append(after).build()), ) - .append(set.before.map(|before| { + .append_all(set.before.map(|before| { Element::builder("before") .ns(ns::RSM) .append(before) .build() })) - .append(set.index.map(|index| { + .append_all(set.index.map(|index| { Element::builder("index") .ns(ns::RSM) .append(format!("{}", index)) @@ -162,12 +162,12 @@ impl From for Element { }); Element::builder("set") .ns(ns::RSM) - .append(first) - .append( + .append_all(first.map(Element::from).map(Node::Element).into_iter()) + .append_all( set.last .map(|last| Element::builder("last").ns(ns::RSM).append(last).build()), ) - .append(set.count.map(|count| { + .append_all(set.count.map(|count| { Element::builder("count") .ns(ns::RSM) .append(format!("{}", count)) diff --git a/src/sasl.rs b/src/sasl.rs index 3deed9e1..038e9e4f 100644 --- a/src/sasl.rs +++ b/src/sasl.rs @@ -203,7 +203,7 @@ impl From for Element { Element::builder("failure") .ns(ns::SASL) .append(failure.defined_condition) - .append( + .append_all( failure .texts .into_iter() @@ -214,7 +214,6 @@ impl From for Element { .append(text) .build() }) - .collect::>(), ) .build() } diff --git a/src/stanza_error.rs b/src/stanza_error.rs index db9230eb..e871a12b 100644 --- a/src/stanza_error.rs +++ b/src/stanza_error.rs @@ -9,7 +9,7 @@ use crate::message::MessagePayload; use crate::ns; use crate::presence::PresencePayload; use jid::Jid; -use minidom::Element; +use minidom::{Element, Node}; use std::collections::BTreeMap; use std::convert::TryFrom; @@ -294,15 +294,16 @@ impl From for Element { .attr("type", err.type_) .attr("by", err.by) .append(err.defined_condition) - .append( + .append_all( err.texts.into_iter().map(|(lang, text)| { Element::builder("text") .ns(ns::XMPP_STANZAS) .attr("xml:lang", lang) .append(text) .build() - }).collect::>()) - .append(err.other) + }) + ) + .append_all(err.other.map(Element::from).map(Node::Element).into_iter()) .build() } } diff --git a/src/tune.rs b/src/tune.rs index 1bbb436a..df9b6679 100644 --- a/src/tune.rs +++ b/src/tune.rs @@ -149,13 +149,13 @@ impl From for Element { fn from(tune: Tune) -> Element { Element::builder("tune") .ns(ns::TUNE) - .append(tune.artist) - .append(tune.length) - .append(tune.rating) - .append(tune.source) - .append(tune.title) - .append(tune.track) - .append(tune.uri) + .append_all(tune.artist) + .append_all(tune.length) + .append_all(tune.rating) + .append_all(tune.source) + .append_all(tune.title) + .append_all(tune.track) + .append_all(tune.uri) .build() } } diff --git a/src/util/helpers.rs b/src/util/helpers.rs index b7bdc844..b51b18a9 100644 --- a/src/util/helpers.rs +++ b/src/util/helpers.rs @@ -34,8 +34,8 @@ impl TrimmedPlainText { }) } - pub fn encode(string: &str) -> String { - string.to_owned() + pub fn encode(string: &str) -> Option { + Some(string.to_owned()) } } diff --git a/src/util/macros.rs b/src/util/macros.rs index c4b5c4e0..6843369d 100644 --- a/src/util/macros.rs +++ b/src/util/macros.rs @@ -253,6 +253,11 @@ macro_rules! generate_element_enum { .build() } } + impl From<$elem> for ::minidom::Node { + fn from(elem: $elem) -> ::minidom::Node { + ::minidom::Node::Element(elem.into()) + } + } ); } @@ -291,6 +296,11 @@ macro_rules! generate_attribute_enum { .build() } } + impl From<$elem> for ::minidom::Node { + fn from(elem: $elem) -> ::minidom::Node { + ::minidom::Node::Element(elem.into()) + } + } ); } @@ -385,6 +395,12 @@ macro_rules! generate_empty_element { .build() } } + + impl From<$elem> for ::minidom::Node { + fn from(elem: $elem) -> ::minidom::Node { + ::minidom::Node::Element(elem.into()) + } + } ); } @@ -441,6 +457,12 @@ macro_rules! generate_elem_id { .build() } } + + impl From<$elem> for ::minidom::Node { + fn from(elem: $elem) -> ::minidom::Node { + ::minidom::Node::Element(elem.into()) + } + } ); } @@ -547,22 +569,38 @@ macro_rules! finish_parse_elem { } macro_rules! generate_serialiser { - ($parent:ident, $elem:ident, Required, String, ($name:tt, $ns:ident)) => { - ::minidom::Element::builder($name) - .ns(crate::ns::$ns) - .append($parent.$elem) - .build() - }; - ($parent:ident, $elem:ident, Option, String, ($name:tt, $ns:ident)) => { - $parent.$elem.map(|elem| { + ($builder:ident, $parent:ident, $elem:ident, Required, String, ($name:tt, $ns:ident)) => { + $builder.append(::minidom::Node::Element( ::minidom::Element::builder($name) .ns(crate::ns::$ns) - .append(elem) + .append(::minidom::Node::Text($parent.$elem)) .build() - }) + ) + ) }; - ($parent:ident, $elem:ident, $_:ident, $constructor:ident, ($name:tt, $ns:ident)) => { - $parent.$elem + ($builder:ident, $parent:ident, $elem:ident, Option, String, ($name:tt, $ns:ident)) => { + $builder.append_all($parent.$elem.map(|elem| { + ::minidom::Element::builder($name) + .ns(crate::ns::$ns) + .append(::minidom::Node::Text(elem)) + .build() + }).into_iter() + ) + }; + ($builder:ident, $parent:ident, $elem:ident, Option, $constructor:ident, ($name:tt, $ns:ident)) => { + $builder.append_all($parent.$elem.map(|elem| { + ::minidom::Element::builder($name) + .ns(crate::ns::$ns) + .append(::minidom::Node::Element(::minidom::Element::from(elem))) + .build() + }).into_iter() + ) + }; + ($builder:ident, $parent:ident, $elem:ident, Vec, $constructor:ident, ($name:tt, $ns:ident)) => { + $builder.append_all($parent.$elem.into_iter()) + }; + ($builder:ident, $parent:ident, $elem:ident, $_:ident, $constructor:ident, ($name:tt, $ns:ident)) => { + $builder.append(::minidom::Node::Element(::minidom::Element::from($parent.$elem))) }; } @@ -637,18 +675,25 @@ macro_rules! generate_element { impl From<$elem> for ::minidom::Element { fn from(elem: $elem) -> ::minidom::Element { - ::minidom::Element::builder($name) - .ns(crate::ns::$ns) - $( - .attr($attr_name, elem.$attr) - )* - $( - .append(generate_serialiser!(elem, $child_ident, $coucou, $child_constructor, ($child_name, $child_ns))) - )* - $( - .append($codec::encode(&elem.$text_ident)) - )* - .build() + let mut builder = ::minidom::Element::builder($name) + .ns(crate::ns::$ns); + $( + builder = builder.attr($attr_name, elem.$attr); + )* + $( + builder = generate_serialiser!(builder, elem, $child_ident, $coucou, $child_constructor, ($child_name, $child_ns)); + )* + $( + builder = builder.append_all($codec::encode(&elem.$text_ident).map(::minidom::Node::Text).into_iter()); + )* + + builder.build() + } + } + + impl From<$elem> for ::minidom::Node { + fn from(elem: $elem) -> ::minidom::Node { + ::minidom::Node::Element(elem.into()) } } ); @@ -691,11 +736,17 @@ macro_rules! impl_pubsub_item { .ns(ns::$ns) .attr("id", item.0.id) .attr("publisher", item.0.publisher) - .append(item.0.payload) + .append_all(item.0.payload.map(::minidom::Node::Element).into_iter()) .build() } } + impl From<$item> for ::minidom::Node { + fn from(item: $item) -> ::minidom::Node { + ::minidom::Node::Element(item.into()) + } + } + impl ::std::ops::Deref for $item { type Target = crate::pubsub::Item; diff --git a/src/xhtml.rs b/src/xhtml.rs index 9c43181b..0216e7c9 100644 --- a/src/xhtml.rs +++ b/src/xhtml.rs @@ -98,14 +98,14 @@ impl From for Element { fn from(wrapper: XhtmlIm) -> Element { Element::builder("html") .ns(ns::XHTML_IM) - .append(wrapper.bodies.into_iter().map(|(ref lang, ref body)| { + .append_all(wrapper.bodies.into_iter().map(|(ref lang, ref body)| { if lang.is_empty() { assert!(body.xml_lang.is_none()); } else { assert_eq!(Some(lang), body.xml_lang.as_ref()); } Element::from(body.clone()) - }).collect::>()) + })) .build() } } @@ -174,7 +174,7 @@ impl From for Element { .ns(ns::XHTML) .attr("style", get_style_string(body.style)) .attr("xml:lang", body.xml_lang) - .append(children_to_nodes(body.children)) + .append_all(children_to_nodes(body.children)) .build() } } @@ -338,7 +338,7 @@ impl From for Element { }; let mut builder = Element::builder(name) .ns(ns::XHTML) - .append(children_to_nodes(children)); + .append_all(children_to_nodes(children)); for (key, value) in attrs { builder = builder.attr(key, value); }