stanza_id.rs

  1// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use xso::{AsXml, FromXml};
  8
  9use crate::message::MessagePayload;
 10use crate::ns;
 11use jid::Jid;
 12
 13/// Gives the identifier a service has stamped on this stanza, often in
 14/// order to identify it inside of [an archive](../mam/index.html).
 15#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
 16#[xml(namespace = ns::SID, name = "stanza-id")]
 17pub struct StanzaId {
 18    /// The id associated to this stanza by another entity.
 19    #[xml(attribute)]
 20    pub id: String,
 21
 22    /// The entity who stamped this stanza-id.
 23    #[xml(attribute)]
 24    pub by: Jid,
 25}
 26
 27impl MessagePayload for StanzaId {}
 28
 29/// A hack for MUC before version 1.31 to track a message which may have
 30/// its 'id' attribute changed.
 31#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
 32#[xml(namespace = ns::SID, name = "origin-id")]
 33pub struct OriginId {
 34    /// The id this client set for this stanza.
 35    #[xml(attribute)]
 36    pub id: String,
 37}
 38
 39impl MessagePayload for OriginId {}
 40
 41#[cfg(test)]
 42mod tests {
 43    use super::*;
 44    use jid::BareJid;
 45    use minidom::Element;
 46    use xso::error::{Error, FromElementError};
 47
 48    #[cfg(target_pointer_width = "32")]
 49    #[test]
 50    fn test_size() {
 51        assert_size!(StanzaId, 28);
 52        assert_size!(OriginId, 12);
 53    }
 54
 55    #[cfg(target_pointer_width = "64")]
 56    #[test]
 57    fn test_size() {
 58        assert_size!(StanzaId, 56);
 59        assert_size!(OriginId, 24);
 60    }
 61
 62    #[test]
 63    fn test_simple() {
 64        let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0' id='coucou' by='coucou@coucou'/>"
 65            .parse()
 66            .unwrap();
 67        let stanza_id = StanzaId::try_from(elem).unwrap();
 68        assert_eq!(stanza_id.id, String::from("coucou"));
 69        assert_eq!(stanza_id.by, BareJid::new("coucou@coucou").unwrap());
 70
 71        let elem: Element = "<origin-id xmlns='urn:xmpp:sid:0' id='coucou'/>"
 72            .parse()
 73            .unwrap();
 74        let origin_id = OriginId::try_from(elem).unwrap();
 75        assert_eq!(origin_id.id, String::from("coucou"));
 76    }
 77
 78    #[test]
 79    #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
 80    fn test_invalid_child() {
 81        let elem: Element =
 82            "<stanza-id xmlns='urn:xmpp:sid:0' by='a@b' id='x'><coucou/></stanza-id>"
 83                .parse()
 84                .unwrap();
 85        let error = StanzaId::try_from(elem).unwrap_err();
 86        let message = match error {
 87            FromElementError::Invalid(Error::Other(string)) => string,
 88            _ => panic!(),
 89        };
 90        assert_eq!(message, "Unknown child in StanzaId element.");
 91    }
 92
 93    #[test]
 94    fn test_invalid_id() {
 95        let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0'/>".parse().unwrap();
 96        let error = StanzaId::try_from(elem).unwrap_err();
 97        let message = match error {
 98            FromElementError::Invalid(Error::Other(string)) => string,
 99            _ => panic!(),
100        };
101        assert_eq!(
102            message,
103            "Required attribute field 'id' on StanzaId element missing."
104        );
105    }
106
107    #[test]
108    fn test_invalid_by() {
109        let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0' id='coucou'/>"
110            .parse()
111            .unwrap();
112        let error = StanzaId::try_from(elem).unwrap_err();
113        let message = match error {
114            FromElementError::Invalid(Error::Other(string)) => string,
115            _ => panic!(),
116        };
117        assert_eq!(
118            message,
119            "Required attribute field 'by' on StanzaId element missing."
120        );
121    }
122
123    #[test]
124    fn test_serialise() {
125        let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0' id='coucou' by='coucou@coucou'/>"
126            .parse()
127            .unwrap();
128        let stanza_id = StanzaId {
129            id: String::from("coucou"),
130            by: Jid::new("coucou@coucou").unwrap(),
131        };
132        let elem2 = stanza_id.into();
133        assert_eq!(elem, elem2);
134    }
135}