jingle_ibb.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 try_from::TryFrom;
  8use std::str::FromStr;
  9
 10use minidom::{Element, IntoAttributeValue};
 11
 12use error::Error;
 13
 14use ns;
 15
 16use ibb::Stanza;
 17
 18generate_id!(StreamId);
 19
 20#[derive(Debug, Clone)]
 21pub struct Transport {
 22    pub block_size: u16,
 23    pub sid: StreamId,
 24    pub stanza: Stanza,
 25}
 26
 27impl TryFrom<Element> for Transport {
 28    type Err = Error;
 29
 30    fn try_from(elem: Element) -> Result<Transport, Error> {
 31        if !elem.is("transport", ns::JINGLE_IBB) {
 32            return Err(Error::ParseError("This is not an JingleIBB element."))
 33        }
 34        for _ in elem.children() {
 35            return Err(Error::ParseError("Unknown child in JingleIBB element."));
 36        }
 37        Ok(Transport {
 38            block_size: get_attr!(elem, "block-size", required),
 39            sid: get_attr!(elem, "sid", required),
 40            stanza: get_attr!(elem, "stanza", default),
 41        })
 42    }
 43}
 44
 45impl From<Transport> for Element {
 46    fn from(transport: Transport) -> Element {
 47        Element::builder("transport")
 48                .ns(ns::JINGLE_IBB)
 49                .attr("block-size", transport.block_size)
 50                .attr("sid", transport.sid)
 51                .attr("stanza", transport.stanza)
 52                .build()
 53    }
 54}
 55
 56#[cfg(test)]
 57mod tests {
 58    use super::*;
 59    use std::error::Error as StdError;
 60
 61    #[test]
 62    fn test_simple() {
 63        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='3' sid='coucou'/>".parse().unwrap();
 64        let transport = Transport::try_from(elem).unwrap();
 65        assert_eq!(transport.block_size, 3);
 66        assert_eq!(transport.sid, StreamId(String::from("coucou")));
 67        assert_eq!(transport.stanza, Stanza::Iq);
 68    }
 69
 70    #[test]
 71    fn test_invalid() {
 72        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1'/>".parse().unwrap();
 73        let error = Transport::try_from(elem).unwrap_err();
 74        let message = match error {
 75            Error::ParseError(string) => string,
 76            _ => panic!(),
 77        };
 78        assert_eq!(message, "Required attribute 'block-size' missing.");
 79
 80        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='65536'/>".parse().unwrap();
 81        let error = Transport::try_from(elem).unwrap_err();
 82        let message = match error {
 83            Error::ParseIntError(error) => error,
 84            _ => panic!(),
 85        };
 86        assert_eq!(message.description(), "number too large to fit in target type");
 87
 88        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='-5'/>".parse().unwrap();
 89        let error = Transport::try_from(elem).unwrap_err();
 90        let message = match error {
 91            Error::ParseIntError(error) => error,
 92            _ => panic!(),
 93        };
 94        assert_eq!(message.description(), "invalid digit found in string");
 95
 96        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='128'/>".parse().unwrap();
 97        let error = Transport::try_from(elem).unwrap_err();
 98        let message = match error {
 99            Error::ParseError(string) => string,
100            _ => panic!(),
101        };
102        assert_eq!(message, "Required attribute 'sid' missing.");
103    }
104
105    #[test]
106    fn test_invalid_stanza() {
107        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='128' sid='coucou' stanza='fdsq'/>".parse().unwrap();
108        let error = Transport::try_from(elem).unwrap_err();
109        let message = match error {
110            Error::ParseError(string) => string,
111            _ => panic!(),
112        };
113        assert_eq!(message, "Unknown value for 'stanza' attribute.");
114    }
115}