stream.rs

  1// Copyright (c) 2018 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 jid::BareJid;
 10
 11use crate::ns;
 12
 13/// The stream opening for client-server communications.
 14#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
 15#[xml(namespace = ns::STREAM, name = "stream")]
 16pub struct Stream {
 17    /// The JID of the entity opening this stream.
 18    #[xml(attribute(default))]
 19    pub from: Option<BareJid>,
 20
 21    /// The JID of the entity receiving this stream opening.
 22    #[xml(attribute(default))]
 23    to: Option<BareJid>,
 24
 25    /// The id of the stream, used for authentication challenges.
 26    #[xml(attribute(default))]
 27    id: Option<String>,
 28
 29    /// The XMPP version used during this stream.
 30    #[xml(attribute(default))]
 31    version: Option<String>,
 32
 33    /// The default human language for all subsequent stanzas, which will
 34    /// be transmitted to other entities for better localisation.
 35    #[xml(lang(default))]
 36    xml_lang: Option<String>,
 37}
 38
 39impl Stream {
 40    /// Creates a simple client→server `<stream:stream>` element.
 41    pub fn new(to: BareJid) -> Stream {
 42        Stream {
 43            from: None,
 44            to: Some(to),
 45            id: None,
 46            version: Some(String::from("1.0")),
 47            xml_lang: None,
 48        }
 49    }
 50
 51    /// Sets the [@from](#structfield.from) attribute on this `<stream:stream>`
 52    /// element.
 53    pub fn with_from(mut self, from: BareJid) -> Stream {
 54        self.from = Some(from);
 55        self
 56    }
 57
 58    /// Sets the [@id](#structfield.id) attribute on this `<stream:stream>`
 59    /// element.
 60    pub fn with_id(mut self, id: String) -> Stream {
 61        self.id = Some(id);
 62        self
 63    }
 64
 65    /// Sets the [@xml:lang](#structfield.xml_lang) attribute on this
 66    /// `<stream:stream>` element.
 67    pub fn with_lang(mut self, xml_lang: String) -> Stream {
 68        self.xml_lang = Some(xml_lang);
 69        self
 70    }
 71
 72    /// Checks whether the version matches the expected one.
 73    pub fn is_version(&self, version: &str) -> bool {
 74        match self.version {
 75            None => false,
 76            Some(ref self_version) => self_version == &String::from(version),
 77        }
 78    }
 79}
 80
 81#[cfg(test)]
 82mod tests {
 83    use super::*;
 84    use minidom::Element;
 85
 86    #[cfg(target_pointer_width = "32")]
 87    #[test]
 88    fn test_size() {
 89        assert_size!(Stream, 68);
 90    }
 91
 92    #[cfg(target_pointer_width = "64")]
 93    #[test]
 94    fn test_size() {
 95        assert_size!(Stream, 136);
 96    }
 97
 98    #[test]
 99    fn test_simple() {
100        let elem: Element = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' xml:lang='en' version='1.0' id='abc' from='some-server.example'/>".parse().unwrap();
101        let stream = Stream::try_from(elem).unwrap();
102        assert_eq!(
103            stream.from,
104            Some(BareJid::new("some-server.example").unwrap())
105        );
106        assert_eq!(stream.to, None);
107        assert_eq!(stream.id, Some(String::from("abc")));
108        assert_eq!(stream.version, Some(String::from("1.0")));
109        assert_eq!(stream.xml_lang, Some(String::from("en")));
110    }
111}