status, presence: Merge status into presence.

This commit is contained in:
Emmanuel Gil Peyrot 2017-04-30 20:33:53 +01:00
parent 4b90c1dc1f
commit 0e20810a83
3 changed files with 93 additions and 103 deletions

View file

@ -35,8 +35,6 @@ pub mod iq;
/// RFC 6121: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence /// RFC 6121: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence
pub mod body; pub mod body;
/// RFC 6121: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence
pub mod status;
/// XEP-0004: Data Forms /// XEP-0004: Data Forms
pub mod data_forms; pub mod data_forms;

View file

@ -15,14 +15,15 @@ use error::Error;
use ns; use ns;
use status;
use delay; use delay;
use ecaps2; use ecaps2;
pub type Status = String;
/// Lists every known payload of a `<presence/>`. /// Lists every known payload of a `<presence/>`.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum PresencePayload { pub enum PresencePayload {
Status(status::Status), Status(Status),
Delay(delay::Delay), Delay(delay::Delay),
ECaps2(ecaps2::ECaps2), ECaps2(ecaps2::ECaps2),
} }
@ -112,19 +113,25 @@ pub fn parse_presence(root: &Element) -> Result<Presence, Error> {
}; };
let mut payloads = vec!(); let mut payloads = vec!();
for elem in root.children() { for elem in root.children() {
let payload = if let Ok(status) = status::parse_status(elem) { if elem.is("status", ns::JABBER_CLIENT) {
Some(PresencePayload::Status(status)) for _ in elem.children() {
} else if let Ok(delay) = delay::parse_delay(elem) { return Err(Error::ParseError("Unknown child in status element."));
Some(PresencePayload::Delay(delay)) }
} else if let Ok(ecaps2) = ecaps2::parse_ecaps2(elem) { let payload = PresencePayload::Status(elem.text());
Some(PresencePayload::ECaps2(ecaps2)) payloads.push(PresencePayloadType::Parsed(payload));
} else { } else {
None let payload = if let Ok(delay) = delay::parse_delay(elem) {
}; Some(PresencePayload::Delay(delay))
payloads.push(match payload { } else if let Ok(ecaps2) = ecaps2::parse_ecaps2(elem) {
Some(payload) => PresencePayloadType::Parsed(payload), Some(PresencePayload::ECaps2(ecaps2))
None => PresencePayloadType::XML(elem.clone()), } else {
}); None
};
payloads.push(match payload {
Some(payload) => PresencePayloadType::Parsed(payload),
None => PresencePayloadType::XML(elem.clone()),
});
}
} }
Ok(Presence { Ok(Presence {
from: from, from: from,
@ -137,7 +144,12 @@ pub fn parse_presence(root: &Element) -> Result<Presence, Error> {
pub fn serialise_payload(payload: &PresencePayload) -> Element { pub fn serialise_payload(payload: &PresencePayload) -> Element {
match *payload { match *payload {
PresencePayload::Status(ref status) => status::serialise(status), PresencePayload::Status(ref status) => {
Element::builder("status")
.ns(ns::JABBER_CLIENT)
.append(status.to_owned())
.build()
},
PresencePayload::Delay(ref delay) => delay::serialise(delay), PresencePayload::Delay(ref delay) => delay::serialise(delay),
PresencePayload::ECaps2(ref ecaps2) => ecaps2::serialise(ecaps2), PresencePayload::ECaps2(ref ecaps2) => ecaps2::serialise(ecaps2),
} }
@ -164,7 +176,9 @@ pub fn serialise(presence: &Presence) -> Element {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use minidom::Element; use minidom::Element;
use error::Error;
use presence; use presence;
use ns;
#[test] #[test]
fn test_simple() { fn test_simple() {
@ -190,4 +204,68 @@ mod tests {
let elem2 = presence::serialise(&presence); let elem2 = presence::serialise(&presence);
assert_eq!(elem, elem2); assert_eq!(elem, elem2);
} }
#[test]
fn test_status() {
let elem: Element = "<presence xmlns='jabber:client'><status xmlns='jabber:client'/></presence>".parse().unwrap();
let presence = presence::parse_presence(&elem).unwrap();
assert_eq!(presence.payloads.len(), 1);
match presence.payloads[0] {
presence::PresencePayloadType::Parsed(presence::PresencePayload::Status(ref status)) => {
assert_eq!(*status, presence::Status::from(""));
},
_ => panic!("Failed to parse status presence."),
}
}
#[test]
fn test_unknown_child() {
let elem: Element = "<presence xmlns='jabber:client'><test xmlns='invalid'/></presence>".parse().unwrap();
let presence = presence::parse_presence(&elem).unwrap();
if let presence::PresencePayloadType::XML(ref payload) = presence.payloads[0] {
assert!(payload.is("test", "invalid"));
} else {
panic!("Did successfully parse an invalid element.");
}
}
#[test]
#[ignore]
fn test_invalid_status_child() {
let elem: Element = "<presence xmlns='jabber:client'><status xmlns='jabber:client'><coucou/></status></presence>".parse().unwrap();
let error = presence::parse_presence(&elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown child in status element.");
}
#[test]
#[ignore]
fn test_invalid_attribute() {
let elem: Element = "<status xmlns='jabber:client' coucou=''/>".parse().unwrap();
let error = presence::parse_presence(&elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown attribute in status element.");
}
#[test]
fn test_serialise_status() {
let status = presence::Status::from("Hello world!");
let payloads = vec!(presence::PresencePayloadType::Parsed(presence::PresencePayload::Status(status)));
let presence = presence::Presence {
from: None,
to: None,
id: None,
type_: presence::PresenceType::Unavailable,
payloads: payloads,
};
let elem = presence::serialise(&presence);
assert!(elem.is("presence", ns::JABBER_CLIENT));
assert!(elem.children().collect::<Vec<_>>()[0].is("status", ns::JABBER_CLIENT));
}
} }

View file

@ -1,86 +0,0 @@
// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// 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 minidom::Element;
use error::Error;
use ns;
pub type Status = String;
pub fn parse_status(root: &Element) -> Result<Status, Error> {
// TODO: also support components and servers.
if !root.is("status", ns::JABBER_CLIENT) {
return Err(Error::ParseError("This is not a status element."));
}
for _ in root.children() {
return Err(Error::ParseError("Unknown child in status element."));
}
Ok(root.text())
}
pub fn serialise(status: &Status) -> Element {
Element::builder("status")
.ns(ns::JABBER_CLIENT)
.append(status.to_owned())
.build()
}
#[cfg(test)]
mod tests {
use minidom::Element;
use error::Error;
use status;
use ns;
#[test]
fn test_simple() {
let elem: Element = "<status xmlns='jabber:client'/>".parse().unwrap();
status::parse_status(&elem).unwrap();
}
#[test]
fn test_invalid() {
let elem: Element = "<status xmlns='jabber:server'/>".parse().unwrap();
let error = status::parse_status(&elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "This is not a status element.");
}
#[test]
fn test_invalid_child() {
let elem: Element = "<status xmlns='jabber:client'><coucou/></status>".parse().unwrap();
let error = status::parse_status(&elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown child in status element.");
}
#[test]
#[ignore]
fn test_invalid_attribute() {
let elem: Element = "<status xmlns='jabber:client' coucou=''/>".parse().unwrap();
let error = status::parse_status(&elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown attribute in status element.");
}
#[test]
fn test_serialise() {
let status = status::Status::from("Hello world!");
let elem = status::serialise(&status);
assert!(elem.is("status", ns::JABBER_CLIENT));
}
}