mirror of https://gitlab.com/xmpp-rs/xmpp-rs.git
Merge branch 'feature/fix-standard-deviance-in-jingle' into 'main'
Fix two places where we deviate from XEP-0166 See merge request xmpp-rs/xmpp-rs!305
This commit is contained in:
commit
5020f6f174
|
@ -14,7 +14,6 @@ use crate::ns;
|
|||
use crate::util::error::Error;
|
||||
use crate::Element;
|
||||
use jid::Jid;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -461,8 +460,6 @@ impl From<Reason> for Element {
|
|||
}
|
||||
}
|
||||
|
||||
type Lang = String;
|
||||
|
||||
/// Informs the recipient of something.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ReasonElement {
|
||||
|
@ -470,15 +467,18 @@ pub struct ReasonElement {
|
|||
pub reason: Reason,
|
||||
|
||||
/// A human-readable description of this reason.
|
||||
pub texts: BTreeMap<Lang, String>,
|
||||
pub text: Option<String>,
|
||||
|
||||
/// A machine-readable extension of the reason.
|
||||
// using a box here to save a significant amount of bytes in the common
|
||||
// (absent) case.
|
||||
pub other: Option<Box<Element>>,
|
||||
}
|
||||
|
||||
impl fmt::Display for ReasonElement {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", Element::from(self.reason.clone()).name())?;
|
||||
if let Some(text) = self.texts.get("en") {
|
||||
write!(fmt, ": {}", text)?;
|
||||
} else if let Some(text) = self.texts.get("") {
|
||||
if let Some(text) = self.text.as_ref() {
|
||||
write!(fmt, ": {}", text)?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -492,17 +492,16 @@ impl TryFrom<Element> for ReasonElement {
|
|||
check_self!(elem, "reason", JINGLE);
|
||||
check_no_attributes!(elem, "reason");
|
||||
let mut reason = None;
|
||||
let mut texts = BTreeMap::new();
|
||||
let mut text = None;
|
||||
let mut other = None;
|
||||
for child in elem.children() {
|
||||
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.",
|
||||
));
|
||||
if text.is_some() {
|
||||
return Err(Error::ParseError("Multiple reason texts."));
|
||||
}
|
||||
text = Some(child.text());
|
||||
} else if child.has_ns(ns::JINGLE) {
|
||||
if reason.is_some() {
|
||||
return Err(Error::ParseError(
|
||||
|
@ -512,12 +511,18 @@ impl TryFrom<Element> for ReasonElement {
|
|||
check_no_children!(child, "reason");
|
||||
check_no_attributes!(child, "reason");
|
||||
reason = Some(child.name().parse()?);
|
||||
} else if other.is_none() {
|
||||
other = Some(Box::new(child.clone()));
|
||||
} else {
|
||||
return Err(Error::ParseError("Reason contains a foreign element."));
|
||||
}
|
||||
}
|
||||
let reason = reason.ok_or(Error::ParseError("Reason doesn’t contain a valid reason."))?;
|
||||
Ok(ReasonElement { reason, texts })
|
||||
Ok(ReasonElement {
|
||||
reason,
|
||||
text,
|
||||
other,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,11 +530,13 @@ impl From<ReasonElement> for Element {
|
|||
fn from(reason: ReasonElement) -> Element {
|
||||
Element::builder("reason", ns::JINGLE)
|
||||
.append(Element::from(reason.reason))
|
||||
.append_all(reason.texts.into_iter().map(|(lang, text)| {
|
||||
Element::builder("text", ns::JINGLE)
|
||||
.attr("xml:lang", lang)
|
||||
.append(text)
|
||||
}))
|
||||
.append_all(
|
||||
reason
|
||||
.text
|
||||
.into_iter()
|
||||
.map(|text| Element::builder("text", ns::JINGLE).append(text)),
|
||||
)
|
||||
.append_all(reason.other.into_iter().map(|other| *other))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
@ -690,9 +697,9 @@ mod tests {
|
|||
assert_size!(ContentId, 12);
|
||||
assert_size!(Content, 216);
|
||||
assert_size!(Reason, 1);
|
||||
assert_size!(ReasonElement, 16);
|
||||
assert_size!(ReasonElement, 20);
|
||||
assert_size!(SessionId, 12);
|
||||
assert_size!(Jingle, 104);
|
||||
assert_size!(Jingle, 108);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
|
@ -709,9 +716,9 @@ mod tests {
|
|||
#[cfg(feature = "stable")]
|
||||
assert_size!(Content, 440);
|
||||
assert_size!(Reason, 1);
|
||||
assert_size!(ReasonElement, 32);
|
||||
assert_size!(ReasonElement, 40);
|
||||
assert_size!(SessionId, 24);
|
||||
assert_size!(Jingle, 208);
|
||||
assert_size!(Jingle, 216);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -823,13 +830,13 @@ mod tests {
|
|||
let jingle = Jingle::try_from(elem).unwrap();
|
||||
let reason = jingle.reason.unwrap();
|
||||
assert_eq!(reason.reason, Reason::Success);
|
||||
assert_eq!(reason.texts, BTreeMap::new());
|
||||
assert_eq!(reason.text, None);
|
||||
|
||||
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 reason = jingle.reason.unwrap();
|
||||
assert_eq!(reason.reason, Reason::Success);
|
||||
assert_eq!(reason.texts.get(""), Some(&String::from("coucou")));
|
||||
assert_eq!(reason.text, Some(String::from("coucou")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -856,7 +863,7 @@ mod tests {
|
|||
Error::ParseError(string) => string,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(message, "Reason contains a foreign element.");
|
||||
assert_eq!(message, "Reason doesn’t contain a valid reason.");
|
||||
|
||||
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><reason><decline/></reason><reason/></jingle>".parse().unwrap();
|
||||
let error = Jingle::try_from(elem).unwrap_err();
|
||||
|
@ -872,7 +879,7 @@ mod tests {
|
|||
Error::ParseError(string) => string,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(message, "Text element present twice for the same xml:lang.");
|
||||
assert_eq!(message, "Multiple reason texts.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in New Issue