This commit is contained in:
Emmanuel Gil Peyrot 2019-09-06 16:03:58 +02:00
commit ff77f6141f
18 changed files with 97 additions and 174 deletions

View file

@ -63,13 +63,10 @@ impl From<BindQuery> for Element {
fn from(bind: BindQuery) -> Element { fn from(bind: BindQuery) -> Element {
Element::builder("bind") Element::builder("bind")
.ns(ns::BIND) .ns(ns::BIND)
.append_all((match bind.resource { .append_all(bind.resource.map(|resource|
None => vec![], Element::builder("resource")
Some(resource) => vec![Element::builder("resource")
.ns(ns::BIND) .ns(ns::BIND)
.append(resource) .append(resource)))
.build()],
}).into_iter())
.build() .build()
} }
} }
@ -129,7 +126,7 @@ impl From<BindResponse> for Element {
fn from(bind: BindResponse) -> Element { fn from(bind: BindResponse) -> Element {
Element::builder("bind") Element::builder("bind")
.ns(ns::BIND) .ns(ns::BIND)
.append(Element::builder("jid").ns(ns::BIND).append(bind.jid).build()) .append(Element::builder("jid").ns(ns::BIND).append(bind.jid))
.build() .build()
} }
} }

View file

@ -55,7 +55,6 @@ macro_rules! generate_blocking_element {
Element::builder("item") Element::builder("item")
.ns(ns::BLOCKING) .ns(ns::BLOCKING)
.attr("jid", jid) .attr("jid", jid)
.build()
})) }))
.build() .build()
} }

View file

@ -7,7 +7,7 @@
use crate::util::error::Error; use crate::util::error::Error;
use crate::media_element::MediaElement; use crate::media_element::MediaElement;
use crate::ns; use crate::ns;
use minidom::{Element, Node}; use minidom::Element;
use std::convert::TryFrom; use std::convert::TryFrom;
generate_element!( generate_element!(
@ -152,12 +152,12 @@ impl From<Field> for Element {
.attr("var", field.var) .attr("var", field.var)
.attr("type", field.type_) .attr("type", field.type_)
.attr("label", field.label) .attr("label", field.label)
.append_all((if field.required { .append_all(if field.required {
Some(Element::builder("required").ns(ns::DATA_FORMS).build()) Some(Element::builder("required").ns(ns::DATA_FORMS))
} else { } else {
None None
}).into_iter()) })
.append_all(field.options.iter().cloned().map(Element::from).map(Node::Element).into_iter()) .append_all(field.options.iter().cloned().map(Element::from))
.append_all( .append_all(
field field
.values .values
@ -166,10 +166,9 @@ impl From<Field> for Element {
Element::builder("value") Element::builder("value")
.ns(ns::DATA_FORMS) .ns(ns::DATA_FORMS)
.append(value) .append(value)
.build()
}) })
) )
.append_all(field.media.iter().cloned().map(Element::from).map(Node::Element)) .append_all(field.media.iter().cloned().map(Element::from))
.build() .build()
} }
} }
@ -283,12 +282,16 @@ impl From<DataForm> for Element {
.ns(ns::DATA_FORMS) .ns(ns::DATA_FORMS)
.append(text) .append(text)
})) }))
.append_all((if let Some(form_type) = form.form_type { .append_all(form.form_type.map(|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()] Element::builder("field")
} else { .ns(ns::DATA_FORMS)
vec![] .attr("var", "FORM_TYPE")
}).into_iter()) .attr("type", "hidden")
.append_all(form.fields.iter().cloned().map(Element::from).map(Node::Element)) .append(Element::builder("value")
.ns(ns::DATA_FORMS)
.append(form_type))
}))
.append_all(form.fields.iter().cloned().map(Element::from))
.build() .build()
} }
} }

View file

@ -9,7 +9,7 @@ use crate::util::error::Error;
use crate::iq::{IqGetPayload, IqResultPayload}; use crate::iq::{IqGetPayload, IqResultPayload};
use crate::ns; use crate::ns;
use jid::Jid; use jid::Jid;
use minidom::{Element, Node}; use minidom::Element;
use std::convert::TryFrom; use std::convert::TryFrom;
generate_element!( generate_element!(
@ -180,7 +180,7 @@ impl From<DiscoInfoResult> for Element {
.attr("node", disco.node) .attr("node", disco.node)
.append_all(disco.identities.into_iter()) .append_all(disco.identities.into_iter())
.append_all(disco.features.into_iter()) .append_all(disco.features.into_iter())
.append_all(disco.extensions.iter().cloned().map(Element::from).map(Node::Element)) .append_all(disco.extensions.iter().cloned().map(Element::from))
.build() .build()
} }
} }

View file

@ -8,7 +8,7 @@ use crate::data_forms::DataForm;
use crate::util::error::Error; use crate::util::error::Error;
use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload}; use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
use crate::ns; use crate::ns;
use minidom::{Element, Node}; use minidom::Element;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -93,23 +93,23 @@ impl From<Query> for Element {
fn from(query: Query) -> Element { fn from(query: Query) -> Element {
Element::builder("query") Element::builder("query")
.ns(ns::REGISTER) .ns(ns::REGISTER)
.append_all((if query.registered { .append_all(if query.registered {
Some(Element::builder("registered").ns(ns::REGISTER)) Some(Element::builder("registered").ns(ns::REGISTER))
} else { } else {
None None
}).into_iter()) })
.append_all( .append_all(
query query
.fields .fields
.into_iter() .into_iter()
.map(|(name, value)| Element::builder(name).ns(ns::REGISTER).append(value)) .map(|(name, value)| Element::builder(name).ns(ns::REGISTER).append(value))
) )
.append_all((if query.remove { .append_all(if query.remove {
Some(Element::builder("remove").ns(ns::REGISTER)) Some(Element::builder("remove").ns(ns::REGISTER))
} else { } else {
None None
}).into_iter()) })
.append_all(query.form.map(Element::from).map(Node::Element).into_iter()) .append_all(query.form.map(Element::from))
.build() .build()
} }
} }

View file

@ -8,7 +8,7 @@ use crate::util::error::Error;
use crate::iq::IqSetPayload; use crate::iq::IqSetPayload;
use crate::ns; use crate::ns;
use jid::Jid; use jid::Jid;
use minidom::{Element, Node}; use minidom::Element;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::str::FromStr; use std::str::FromStr;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -351,7 +351,8 @@ impl From<Reason> for Element {
Reason::UnsupportedApplications => "unsupported-applications", Reason::UnsupportedApplications => "unsupported-applications",
Reason::UnsupportedTransports => "unsupported-transports", Reason::UnsupportedTransports => "unsupported-transports",
}) })
.build() .ns(ns::JINGLE)
.build()
} }
} }
@ -419,7 +420,6 @@ impl From<ReasonElement> for Element {
.ns(ns::JINGLE) .ns(ns::JINGLE)
.attr("xml:lang", lang) .attr("xml:lang", lang)
.append(text) .append(text)
.build()
})) }))
.build() .build()
} }
@ -542,8 +542,8 @@ impl From<Jingle> for Element {
.attr("initiator", jingle.initiator) .attr("initiator", jingle.initiator)
.attr("responder", jingle.responder) .attr("responder", jingle.responder)
.attr("sid", jingle.sid) .attr("sid", jingle.sid)
.append_all(jingle.contents.into_iter()) .append_all(jingle.contents)
.append_all(jingle.reason.map(Element::from).map(Node::Element).into_iter()) .append_all(jingle.reason.map(Element::from))
.build() .build()
} }
} }

View file

@ -193,65 +193,27 @@ impl TryFrom<Element> for File {
impl From<File> for Element { impl From<File> for Element {
fn from(file: File) -> Element { fn from(file: File) -> Element {
let mut root = Element::builder("file").ns(ns::JINGLE_FT); Element::builder("file")
if let Some(date) = file.date { .ns(ns::JINGLE_FT)
root = root.append( .append_all(file.date.map(|date|
Node::Element( Element::builder("date")
Element::builder("date") .append(date)))
.ns(ns::JINGLE_FT) .append_all(file.media_type.map(|media_type|
.append(date) Element::builder("media-type")
.build() .append(media_type)))
) .append_all(file.name.map(|name|
); Element::builder("name")
} .append(name)))
if let Some(media_type) = file.media_type { .append_all(file.descs.into_iter().map(|(lang, desc)|
root = root.append( Element::builder("desc")
Node::Element( .attr("xml:lang", lang)
Element::builder("media-type") .append(desc.0)))
.ns(ns::JINGLE_FT) .append_all(file.size.map(|size|
.append(media_type) Element::builder("size")
.build() .append(format!("{}", size))))
) .append_all(file.range)
); .append_all(file.hashes)
} .build()
if let Some(name) = file.name {
root = root.append(
Node::Element(
Element::builder("name")
.ns(ns::JINGLE_FT)
.append(name)
.build()
)
);
}
for (lang, desc) in file.descs.into_iter() {
root = root.append(
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(
Node::Element(
Element::builder("size")
.ns(ns::JINGLE_FT)
.append(format!("{}", size))
.build()
)
);
}
if let Some(range) = file.range {
root = root.append(range);
}
for hash in file.hashes {
root = root.append(hash);
}
root.build()
} }
} }

View file

@ -251,27 +251,22 @@ impl From<Transport> for Element {
TransportPayload::Candidates(candidates) => candidates TransportPayload::Candidates(candidates) => candidates
.into_iter() .into_iter()
.map(Element::from) .map(Element::from)
.collect::<Vec<_>>() .collect::<Vec<_>>(),
.into_iter(),
TransportPayload::Activated(cid) => vec![Element::builder("activated") TransportPayload::Activated(cid) => vec![Element::builder("activated")
.ns(ns::JINGLE_S5B) .ns(ns::JINGLE_S5B)
.attr("cid", cid) .attr("cid", cid)
.build()] .build()],
.into_iter(),
TransportPayload::CandidateError => vec![Element::builder("candidate-error") TransportPayload::CandidateError => vec![Element::builder("candidate-error")
.ns(ns::JINGLE_S5B) .ns(ns::JINGLE_S5B)
.build()] .build()],
.into_iter(),
TransportPayload::CandidateUsed(cid) => vec![Element::builder("candidate-used") TransportPayload::CandidateUsed(cid) => vec![Element::builder("candidate-used")
.ns(ns::JINGLE_S5B) .ns(ns::JINGLE_S5B)
.attr("cid", cid) .attr("cid", cid)
.build()] .build()],
.into_iter(),
TransportPayload::ProxyError => vec![Element::builder("proxy-error") TransportPayload::ProxyError => vec![Element::builder("proxy-error")
.ns(ns::JINGLE_S5B) .ns(ns::JINGLE_S5B)
.build()] .build()],
.into_iter(), TransportPayload::None => vec![],
TransportPayload::None => vec![].into_iter(),
}) })
.build() .build()
} }

View file

@ -171,17 +171,9 @@ fn serialise_jid_list(name: &str, jids: Vec<Jid>) -> ::std::option::IntoIter<Nod
.append_all( .append_all(
jids.into_iter() jids.into_iter()
.map(|jid| .map(|jid|
Node::Element( Element::builder("jid")
Element::builder("jid") .ns(ns::MAM)
.ns(ns::MAM) .append(String::from(jid))))
.append(Node::Text(String::from(jid)))
.build()
.into()
)
)
.into_iter(),
)
.build()
.into(), .into(),
).into_iter() ).into_iter()
} }

View file

@ -324,18 +324,14 @@ impl From<Presence> for Element {
}, },
) )
.append(status) .append(status)
.build()
}) })
) )
.append_all((if presence.priority == 0 { .append_all(if presence.priority == 0 {
None None
} else { } else {
Some( Some(Element::builder("priority")
Element::builder("priority") .append(format!("{}", presence.priority)))
.append(format!("{}", presence.priority)) })
.build()
)
}).into_iter())
.append_all(presence.payloads.into_iter()) .append_all(presence.payloads.into_iter())
.build() .build()
} }

View file

@ -10,7 +10,7 @@ use crate::util::error::Error;
use crate::ns; use crate::ns;
use crate::pubsub::{ItemId, NodeName, Subscription, SubscriptionId, Item as PubSubItem}; use crate::pubsub::{ItemId, NodeName, Subscription, SubscriptionId, Item as PubSubItem};
use jid::Jid; use jid::Jid;
use minidom::{Element, Node}; use minidom::Element;
use std::convert::TryFrom; use std::convert::TryFrom;
/// Event wrapper for a PubSub `<item/>`. /// Event wrapper for a PubSub `<item/>`.
@ -198,8 +198,7 @@ impl From<PubSubEvent> for Element {
PubSubEvent::Configuration { node, form } => Element::builder("configuration") PubSubEvent::Configuration { node, form } => Element::builder("configuration")
.ns(ns::PUBSUB_EVENT) .ns(ns::PUBSUB_EVENT)
.attr("node", node) .attr("node", node)
.append_all(form.map(Element::from).map(Node::Element).into_iter()) .append_all(form.map(Element::from)),
.build(),
PubSubEvent::Delete { node, redirect } => Element::builder("purge") PubSubEvent::Delete { node, redirect } => Element::builder("purge")
.ns(ns::PUBSUB_EVENT) .ns(ns::PUBSUB_EVENT)
.attr("node", node) .attr("node", node)
@ -207,14 +206,11 @@ impl From<PubSubEvent> for Element {
Element::builder("redirect") Element::builder("redirect")
.ns(ns::PUBSUB_EVENT) .ns(ns::PUBSUB_EVENT)
.attr("uri", redirect) .attr("uri", redirect)
.build() })),
}))
.build(),
PubSubEvent::PublishedItems { node, items } => Element::builder("items") PubSubEvent::PublishedItems { node, items } => Element::builder("items")
.ns(ns::PUBSUB_EVENT) .ns(ns::PUBSUB_EVENT)
.attr("node", node) .attr("node", node)
.append_all(items.into_iter()) .append_all(items.into_iter()),
.build(),
PubSubEvent::RetractedItems { node, items } => Element::builder("items") PubSubEvent::RetractedItems { node, items } => Element::builder("items")
.ns(ns::PUBSUB_EVENT) .ns(ns::PUBSUB_EVENT)
.attr("node", node) .attr("node", node)
@ -225,14 +221,11 @@ impl From<PubSubEvent> for Element {
Element::builder("retract") Element::builder("retract")
.ns(ns::PUBSUB_EVENT) .ns(ns::PUBSUB_EVENT)
.attr("id", id) .attr("id", id)
.build()
}) })
) ),
.build(),
PubSubEvent::Purge { node } => Element::builder("purge") PubSubEvent::Purge { node } => Element::builder("purge")
.ns(ns::PUBSUB_EVENT) .ns(ns::PUBSUB_EVENT)
.attr("node", node) .attr("node", node),
.build(),
PubSubEvent::Subscription { PubSubEvent::Subscription {
node, node,
expiry, expiry,
@ -245,8 +238,7 @@ impl From<PubSubEvent> for Element {
.attr("expiry", expiry) .attr("expiry", expiry)
.attr("jid", jid) .attr("jid", jid)
.attr("subid", subid) .attr("subid", subid)
.attr("subscription", subscription) .attr("subscription", subscription),
.build(),
}; };
Element::builder("event") Element::builder("event")
.ns(ns::PUBSUB_EVENT) .ns(ns::PUBSUB_EVENT)

View file

@ -219,11 +219,11 @@ impl From<SubscribeOptions> for Element {
fn from(subscribe_options: SubscribeOptions) -> Element { fn from(subscribe_options: SubscribeOptions) -> Element {
Element::builder("subscribe-options") Element::builder("subscribe-options")
.ns(ns::PUBSUB) .ns(ns::PUBSUB)
.append_all((if subscribe_options.required { .append_all(if subscribe_options.required {
vec![Element::builder("required").ns(ns::PUBSUB).build()] Some(Element::builder("required").ns(ns::PUBSUB))
} else { } else {
vec![] None
}).into_iter()) })
.build() .build()
} }
} }
@ -473,7 +473,7 @@ impl From<PubSub> for Element {
fn from(pubsub: PubSub) -> Element { fn from(pubsub: PubSub) -> Element {
Element::builder("pubsub") Element::builder("pubsub")
.ns(ns::PUBSUB) .ns(ns::PUBSUB)
.append_all((match pubsub { .append_all(match pubsub {
PubSub::Create { create, configure } => { PubSub::Create { create, configure } => {
let mut elems = vec![Element::from(create)]; let mut elems = vec![Element::from(create)];
if let Some(configure) = configure { if let Some(configure) = configure {
@ -498,7 +498,7 @@ impl From<PubSub> for Element {
PubSub::Subscription(subscription) => vec![Element::from(subscription)], PubSub::Subscription(subscription) => vec![Element::from(subscription)],
PubSub::Subscriptions(subscriptions) => vec![Element::from(subscriptions)], PubSub::Subscriptions(subscriptions) => vec![Element::from(subscriptions)],
PubSub::Unsubscribe(unsubscribe) => vec![Element::from(unsubscribe)], PubSub::Unsubscribe(unsubscribe) => vec![Element::from(unsubscribe)],
}).into_iter()) })
.build() .build()
} }
} }

View file

@ -6,7 +6,7 @@
use crate::util::error::Error; use crate::util::error::Error;
use crate::ns; use crate::ns;
use minidom::{Element, Node}; use minidom::Element;
use std::convert::TryFrom; use std::convert::TryFrom;
/// Requests paging through a potentially big set of items (represented by an /// Requests paging through a potentially big set of items (represented by an
@ -76,23 +76,20 @@ impl From<SetQuery> for Element {
Element::builder("max") Element::builder("max")
.ns(ns::RSM) .ns(ns::RSM)
.append(format!("{}", max)) .append(format!("{}", max))
.build()
})) }))
.append_all( .append_all(
set.after set.after
.map(|after| Element::builder("after").ns(ns::RSM).append(after).build()), .map(|after| Element::builder("after").ns(ns::RSM).append(after))
) )
.append_all(set.before.map(|before| { .append_all(set.before.map(|before| {
Element::builder("before") Element::builder("before")
.ns(ns::RSM) .ns(ns::RSM)
.append(before) .append(before)
.build()
})) }))
.append_all(set.index.map(|index| { .append_all(set.index.map(|index| {
Element::builder("index") Element::builder("index")
.ns(ns::RSM) .ns(ns::RSM)
.append(format!("{}", index)) .append(format!("{}", index))
.build()
})) }))
.build() .build()
} }
@ -158,20 +155,18 @@ impl From<SetResult> for Element {
.ns(ns::RSM) .ns(ns::RSM)
.attr("index", set.first_index) .attr("index", set.first_index)
.append(first) .append(first)
.build()
}); });
Element::builder("set") Element::builder("set")
.ns(ns::RSM) .ns(ns::RSM)
.append_all(first.map(Element::from).map(Node::Element).into_iter()) .append_all(first)
.append_all( .append_all(
set.last set.last
.map(|last| Element::builder("last").ns(ns::RSM).append(last).build()), .map(|last| Element::builder("last").ns(ns::RSM).append(last)),
) )
.append_all(set.count.map(|count| { .append_all(set.count.map(|count| {
Element::builder("count") Element::builder("count")
.ns(ns::RSM) .ns(ns::RSM)
.append(format!("{}", count)) .append(format!("{}", count))
.build()
})) }))
.build() .build()
} }

View file

@ -212,7 +212,6 @@ impl From<Failure> for Element {
.ns(ns::SASL) .ns(ns::SASL)
.attr("xml:lang", lang) .attr("xml:lang", lang)
.append(text) .append(text)
.build()
}) })
) )
.build() .build()

View file

@ -9,7 +9,7 @@ use crate::message::MessagePayload;
use crate::ns; use crate::ns;
use crate::presence::PresencePayload; use crate::presence::PresencePayload;
use jid::Jid; use jid::Jid;
use minidom::{Element, Node}; use minidom::Element;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -300,10 +300,9 @@ impl From<StanzaError> for Element {
.ns(ns::XMPP_STANZAS) .ns(ns::XMPP_STANZAS)
.attr("xml:lang", lang) .attr("xml:lang", lang)
.append(text) .append(text)
.build()
}) })
) )
.append_all(err.other.map(Element::from).map(Node::Element).into_iter()) .append_all(err.other)
.build() .build()
} }
} }

View file

@ -78,11 +78,9 @@ impl From<TimeResult> for Element {
Element::builder("time") Element::builder("time")
.ns(ns::TIME) .ns(ns::TIME)
.append(Element::builder("tzo") .append(Element::builder("tzo")
.append(format!("{}", time.0.timezone())) .append(format!("{}", time.0.timezone())))
.build())
.append(Element::builder("utc") .append(Element::builder("utc")
.append(time.0.with_timezone(FixedOffset::east(0)).format("%FT%TZ")) .append(time.0.with_timezone(FixedOffset::east(0)).format("%FT%TZ")))
.build())
.build() .build()
} }
} }

View file

@ -570,12 +570,10 @@ macro_rules! finish_parse_elem {
macro_rules! generate_serialiser { macro_rules! generate_serialiser {
($builder:ident, $parent:ident, $elem:ident, Required, String, ($name:tt, $ns:ident)) => { ($builder:ident, $parent:ident, $elem:ident, Required, String, ($name:tt, $ns:ident)) => {
$builder.append(::minidom::Node::Element( $builder.append(
::minidom::Element::builder($name) ::minidom::Element::builder($name)
.ns(crate::ns::$ns) .ns(crate::ns::$ns)
.append(::minidom::Node::Text($parent.$elem)) .append(::minidom::Node::Text($parent.$elem))
.build()
)
) )
}; };
($builder:ident, $parent:ident, $elem:ident, Option, String, ($name:tt, $ns:ident)) => { ($builder:ident, $parent:ident, $elem:ident, Option, String, ($name:tt, $ns:ident)) => {
@ -583,8 +581,7 @@ macro_rules! generate_serialiser {
::minidom::Element::builder($name) ::minidom::Element::builder($name)
.ns(crate::ns::$ns) .ns(crate::ns::$ns)
.append(::minidom::Node::Text(elem)) .append(::minidom::Node::Text(elem))
.build() })
}).into_iter()
) )
}; };
($builder:ident, $parent:ident, $elem:ident, Option, $constructor:ident, ($name:tt, $ns:ident)) => { ($builder:ident, $parent:ident, $elem:ident, Option, $constructor:ident, ($name:tt, $ns:ident)) => {
@ -592,8 +589,7 @@ macro_rules! generate_serialiser {
::minidom::Element::builder($name) ::minidom::Element::builder($name)
.ns(crate::ns::$ns) .ns(crate::ns::$ns)
.append(::minidom::Node::Element(::minidom::Element::from(elem))) .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:ident, $parent:ident, $elem:ident, Vec, $constructor:ident, ($name:tt, $ns:ident)) => {
@ -736,7 +732,7 @@ macro_rules! impl_pubsub_item {
.ns(ns::$ns) .ns(ns::$ns)
.attr("id", item.0.id) .attr("id", item.0.id)
.attr("publisher", item.0.publisher) .attr("publisher", item.0.publisher)
.append_all(item.0.payload.map(::minidom::Node::Element).into_iter()) .append_all(item.0.payload)
.build() .build()
} }
} }

View file

@ -98,13 +98,13 @@ impl From<XhtmlIm> for Element {
fn from(wrapper: XhtmlIm) -> Element { fn from(wrapper: XhtmlIm) -> Element {
Element::builder("html") Element::builder("html")
.ns(ns::XHTML_IM) .ns(ns::XHTML_IM)
.append_all(wrapper.bodies.into_iter().map(|(ref lang, ref body)| { .append_all(wrapper.bodies.into_iter().map(|(lang, body)| {
if lang.is_empty() { if lang.is_empty() {
assert!(body.xml_lang.is_none()); assert!(body.xml_lang.is_none());
} else { } else {
assert_eq!(Some(lang), body.xml_lang.as_ref()); assert_eq!(Some(lang), body.xml_lang);
} }
Element::from(body.clone()) Element::from(body)
})) }))
.build() .build()
} }
@ -346,11 +346,11 @@ impl From<Tag> for Element {
} }
} }
fn children_to_nodes(children: Vec<Child>) -> Vec<Node> { fn children_to_nodes(children: Vec<Child>) -> impl IntoIterator<Item = Node> {
children.into_iter().map(|child| match child { children.into_iter().map(|child| match child {
Child::Tag(tag) => Node::Element(Element::from(tag)), Child::Tag(tag) => Node::Element(Element::from(tag)),
Child::Text(text) => Node::Text(text), Child::Text(text) => Node::Text(text),
}).collect::<Vec<_>>() })
} }
fn children_to_html(children: Vec<Child>) -> String { fn children_to_html(children: Vec<Child>) -> String {