use xso::{AsXml, FromXml};
use crate::message::MessagePayload;
use crate::ns;
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::CALL_INVITES, name = "invite")]
pub struct Invite {
#[xml(attribute(default))]
pub audio: bool,
#[xml(attribute(default))]
pub video: bool,
#[xml(child)]
pub jingle: Jingle,
#[xml(extract(n = .., name = "external", fields(attribute(name = "uri", type_ = String))))]
pub external_uris: Vec<String>,
}
impl MessagePayload for Invite {}
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::CALL_INVITES, name = "jingle")]
pub struct Jingle {
#[xml(attribute)]
pub sid: String,
#[xml(attribute(default))]
pub jid: Option<String>,
}
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::CALL_INVITES, name = "retract")]
pub struct Retract {
#[xml(attribute)]
pub id: String,
}
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::CALL_INVITES, name = "accept")]
pub struct Accept {
#[xml(attribute)]
pub id: String,
#[xml(child)]
pub payload: AcceptPayload,
}
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml()]
pub enum AcceptPayload {
#[xml(transparent)]
Jingle(Jingle),
#[xml(namespace = ns::CALL_INVITES, name = "external")]
ExternalUri(
#[xml(extract(name = "external", fields(attribute(name = "uri", type_ = String))))] String,
),
}
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::CALL_INVITES, name = "reject")]
pub struct Reject {
#[xml(attribute)]
pub id: String,
}
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::CALL_INVITES, name = "left")]
pub struct Left {
#[xml(attribute)]
pub id: String,
}
#[cfg(test)]
mod tests {
use super::*;
use minidom::Element;
#[cfg(target_pointer_width = "32")]
#[test]
fn test_size() {
assert_size!(Invite, 40);
assert_size!(Jingle, 24);
assert_size!(Retract, 12);
assert_size!(Accept, 36);
assert_size!(AcceptPayload, 24);
assert_size!(Reject, 12);
assert_size!(Left, 12);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn test_size() {
assert_size!(Invite, 80);
assert_size!(Jingle, 48);
assert_size!(Retract, 24);
assert_size!(Accept, 72);
assert_size!(AcceptPayload, 48);
assert_size!(Reject, 24);
assert_size!(Left, 24);
}
#[test]
fn invite_example_1() {
let elem: Element =
"<invite video='true' xmlns='urn:xmpp:call-invites:0'><jingle sid='sid1'/></invite>"
.parse()
.unwrap();
let invite = Invite::try_from(elem).unwrap();
assert_eq!(invite.video, true);
assert_eq!(invite.jingle.sid, "sid1");
assert_eq!(invite.jingle.jid, None);
assert_eq!(invite.external_uris.len(), 0);
}
#[test]
fn invite_example_2() {
let elem: Element = "<invite xmlns='urn:xmpp:call-invites:0'><jingle sid='sid2' jid='mixer@example.com/uuid'/><external uri='https://example.com/uuid'/><external uri='tel:+12345678'/></invite>".parse().unwrap();
let invite = Invite::try_from(elem).unwrap();
assert_eq!(invite.video, false);
assert_eq!(invite.jingle.sid, "sid2");
assert_eq!(invite.jingle.jid.unwrap(), "mixer@example.com/uuid");
assert_eq!(invite.external_uris.len(), 2);
assert_eq!(invite.external_uris[0], "https://example.com/uuid");
assert_eq!(invite.external_uris[1], "tel:+12345678");
}
#[test]
fn retract_example_3() {
let elem: Element = "<retract id='id1' xmlns='urn:xmpp:call-invites:0'/>"
.parse()
.unwrap();
let retract = Retract::try_from(elem).unwrap();
assert_eq!(retract.id, "id1");
}
#[test]
fn accept_example_4() {
let elem: Element = "<accept id='id1' xmlns='urn:xmpp:call-invites:0'><jingle sid='sid1' jid='mixer@example.com/uuid'/></accept>".parse().unwrap();
let accept = Accept::try_from(elem).unwrap();
assert_eq!(accept.id, "id1");
let AcceptPayload::Jingle(jingle) = accept.payload else {
panic!("Unexpected payload.")
};
assert_eq!(jingle.sid, "sid1");
assert_eq!(jingle.jid.unwrap(), "mixer@example.com/uuid");
}
#[test]
#[ignore]
fn accept_external() {
let elem: Element = "<accept id='id2' xmlns='urn:xmpp:call-invites:0'><external uri='tel:+12345678'/></accept>".parse().unwrap();
let accept = Accept::try_from(elem).unwrap();
assert_eq!(accept.id, "id2");
let AcceptPayload::ExternalUri(uri) = accept.payload else {
panic!("Unexpected payload.")
};
assert_eq!(uri, "tel:+12345678");
}
#[test]
fn reject_example_5() {
let elem: Element = "<reject id='id1' xmlns='urn:xmpp:call-invites:0'/>"
.parse()
.unwrap();
let reject = Reject::try_from(elem).unwrap();
assert_eq!(reject.id, "id1");
}
#[test]
fn left_example_6() {
let elem: Element = "<left id='id1' xmlns='urn:xmpp:call-invites:0'/>"
.parse()
.unwrap();
let left = Left::try_from(elem).unwrap();
assert_eq!(left.id, "id1");
}
}