mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
jingle: Support more than one <text/> with different @xml:lang.
This commit is contained in:
parent
b56582c8b5
commit
2b9a6d57b6
1 changed files with 38 additions and 26 deletions
|
@ -9,6 +9,7 @@ use crate::iq::IqSetPayload;
|
||||||
use crate::ns;
|
use crate::ns;
|
||||||
use jid::Jid;
|
use jid::Jid;
|
||||||
use minidom::Element;
|
use minidom::Element;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use try_from::TryFrom;
|
use try_from::TryFrom;
|
||||||
|
|
||||||
|
@ -354,6 +355,8 @@ impl From<Reason> for Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Lang = String;
|
||||||
|
|
||||||
/// Informs the recipient of something.
|
/// Informs the recipient of something.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ReasonElement {
|
pub struct ReasonElement {
|
||||||
|
@ -361,7 +364,7 @@ pub struct ReasonElement {
|
||||||
pub reason: Reason,
|
pub reason: Reason,
|
||||||
|
|
||||||
/// A human-readable description of this reason.
|
/// A human-readable description of this reason.
|
||||||
pub text: Option<String>,
|
pub texts: BTreeMap<Lang, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Element> for ReasonElement {
|
impl TryFrom<Element> for ReasonElement {
|
||||||
|
@ -369,37 +372,38 @@ impl TryFrom<Element> for ReasonElement {
|
||||||
|
|
||||||
fn try_from(elem: Element) -> Result<ReasonElement, Error> {
|
fn try_from(elem: Element) -> Result<ReasonElement, Error> {
|
||||||
check_self!(elem, "reason", JINGLE);
|
check_self!(elem, "reason", JINGLE);
|
||||||
|
check_no_attributes!(elem, "reason");
|
||||||
let mut reason = None;
|
let mut reason = None;
|
||||||
let mut text = None;
|
let mut texts = BTreeMap::new();
|
||||||
for child in elem.children() {
|
for child in elem.children() {
|
||||||
if !child.has_ns(ns::JINGLE) {
|
if child.is("text", ns::JINGLE) {
|
||||||
|
check_no_children!(child, "text");
|
||||||
|
check_no_unknown_attributes!(child, "text", ["xml:lang"]);
|
||||||
|
let lang = get_attr!(elem, "xml:lang", Default);
|
||||||
|
if texts.insert(lang, child.text()).is_some() {
|
||||||
|
return Err(Error::ParseError(
|
||||||
|
"Text element present twice for the same xml:lang.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else if child.has_ns(ns::JINGLE) {
|
||||||
|
if reason.is_some() {
|
||||||
|
return Err(Error::ParseError(
|
||||||
|
"Reason must not have more than one reason.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
check_no_children!(child, "reason");
|
||||||
|
check_no_attributes!(child, "reason");
|
||||||
|
reason = Some(child.name().parse()?);
|
||||||
|
} else {
|
||||||
return Err(Error::ParseError("Reason contains a foreign element."));
|
return Err(Error::ParseError("Reason contains a foreign element."));
|
||||||
}
|
}
|
||||||
match child.name() {
|
|
||||||
"text" => {
|
|
||||||
if text.is_some() {
|
|
||||||
return Err(Error::ParseError(
|
|
||||||
"Reason must not have more than one text.",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
text = Some(child.text());
|
|
||||||
}
|
|
||||||
name => {
|
|
||||||
if reason.is_some() {
|
|
||||||
return Err(Error::ParseError(
|
|
||||||
"Reason must not have more than one reason.",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
reason = Some(name.parse()?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let reason = reason.ok_or(Error::ParseError(
|
let reason = reason.ok_or(Error::ParseError(
|
||||||
"Reason doesn’t contain a valid reason.",
|
"Reason doesn’t contain a valid reason.",
|
||||||
))?;
|
))?;
|
||||||
Ok(ReasonElement {
|
Ok(ReasonElement {
|
||||||
reason,
|
reason,
|
||||||
text,
|
texts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -407,8 +411,16 @@ impl TryFrom<Element> for ReasonElement {
|
||||||
impl From<ReasonElement> for Element {
|
impl From<ReasonElement> for Element {
|
||||||
fn from(reason: ReasonElement) -> Element {
|
fn from(reason: ReasonElement) -> Element {
|
||||||
Element::builder("reason")
|
Element::builder("reason")
|
||||||
|
.ns(ns::JINGLE)
|
||||||
.append(Element::from(reason.reason))
|
.append(Element::from(reason.reason))
|
||||||
.append(reason.text)
|
.append(
|
||||||
|
reason.texts.into_iter().map(|(lang, text)| {
|
||||||
|
Element::builder("text")
|
||||||
|
.ns(ns::JINGLE)
|
||||||
|
.attr("xml:lang", lang)
|
||||||
|
.append(text)
|
||||||
|
.build()
|
||||||
|
}).collect::<Vec<_>>())
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -679,13 +691,13 @@ mod tests {
|
||||||
let jingle = Jingle::try_from(elem).unwrap();
|
let jingle = Jingle::try_from(elem).unwrap();
|
||||||
let reason = jingle.reason.unwrap();
|
let reason = jingle.reason.unwrap();
|
||||||
assert_eq!(reason.reason, Reason::Success);
|
assert_eq!(reason.reason, Reason::Success);
|
||||||
assert_eq!(reason.text, None);
|
assert_eq!(reason.texts, BTreeMap::new());
|
||||||
|
|
||||||
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><reason><success/><text>coucou</text></reason></jingle>".parse().unwrap();
|
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><reason><success/><text>coucou</text></reason></jingle>".parse().unwrap();
|
||||||
let jingle = Jingle::try_from(elem).unwrap();
|
let jingle = Jingle::try_from(elem).unwrap();
|
||||||
let reason = jingle.reason.unwrap();
|
let reason = jingle.reason.unwrap();
|
||||||
assert_eq!(reason.reason, Reason::Success);
|
assert_eq!(reason.reason, Reason::Success);
|
||||||
assert_eq!(reason.text, Some(String::from("coucou")));
|
assert_eq!(reason.texts.get(""), Some(&String::from("coucou")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -728,6 +740,6 @@ mod tests {
|
||||||
Error::ParseError(string) => string,
|
Error::ParseError(string) => string,
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
};
|
};
|
||||||
assert_eq!(message, "Reason must not have more than one text.");
|
assert_eq!(message, "Text element present twice for the same xml:lang.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue