jingle_ibb.rs

  1use std::str::FromStr;
  2
  3use minidom::Element;
  4
  5use error::Error;
  6
  7use ns;
  8
  9use ibb::Stanza;
 10
 11#[derive(Debug, Clone)]
 12pub struct Transport {
 13    block_size: u16,
 14    sid: String,
 15    stanza: Stanza,
 16}
 17
 18fn optional_attr<T: FromStr>(root: &Element, attr: &str) -> Option<T> {
 19    root.attr(attr)
 20        .and_then(|value| value.parse().ok())
 21}
 22
 23fn required_attr<T: FromStr>(root: &Element, attr: &str, err: Error) -> Result<T, Error> {
 24    optional_attr(root, attr).ok_or(err)
 25}
 26
 27pub fn parse_jingle_ibb(root: &Element) -> Result<Transport, Error> {
 28    if root.is("transport", ns::JINGLE_IBB) {
 29        for _ in root.children() {
 30            return Err(Error::ParseError("Unknown child in JingleIBB element."));
 31        }
 32        let block_size = required_attr(root, "block-size", Error::ParseError("Required attribute 'block-size' missing in JingleIBB element."))?;
 33        let sid = required_attr(root, "sid", Error::ParseError("Required attribute 'sid' missing in JingleIBB element."))?;
 34        let stanza = root.attr("stanza")
 35                         .unwrap_or("iq")
 36                         .parse()?;
 37        Ok(Transport {
 38            block_size: block_size,
 39            sid: sid,
 40            stanza: stanza
 41        })
 42    } else {
 43        Err(Error::ParseError("This is not an JingleIBB element."))
 44    }
 45}
 46
 47#[cfg(test)]
 48mod tests {
 49    use minidom::Element;
 50    use error::Error;
 51    use ibb;
 52    use jingle_ibb;
 53
 54    #[test]
 55    fn test_simple() {
 56        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='3' sid='coucou'/>".parse().unwrap();
 57        let transport = jingle_ibb::parse_jingle_ibb(&elem).unwrap();
 58        assert_eq!(transport.block_size, 3);
 59        assert_eq!(transport.sid, "coucou");
 60        assert_eq!(transport.stanza, ibb::Stanza::Iq);
 61    }
 62
 63    #[test]
 64    fn test_invalid() {
 65        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1'/>".parse().unwrap();
 66        let error = jingle_ibb::parse_jingle_ibb(&elem).unwrap_err();
 67        let message = match error {
 68            Error::ParseError(string) => string,
 69            _ => panic!(),
 70        };
 71        assert_eq!(message, "Required attribute 'block-size' missing in JingleIBB element.");
 72
 73        // TODO: maybe make a better error message here.
 74        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='-5'/>".parse().unwrap();
 75        let error = jingle_ibb::parse_jingle_ibb(&elem).unwrap_err();
 76        let message = match error {
 77            Error::ParseError(string) => string,
 78            _ => panic!(),
 79        };
 80        assert_eq!(message, "Required attribute 'block-size' missing in JingleIBB element.");
 81
 82        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='128'/>".parse().unwrap();
 83        let error = jingle_ibb::parse_jingle_ibb(&elem).unwrap_err();
 84        let message = match error {
 85            Error::ParseError(string) => string,
 86            _ => panic!(),
 87        };
 88        assert_eq!(message, "Required attribute 'sid' missing in JingleIBB element.");
 89    }
 90
 91    #[test]
 92    fn test_invalid_stanza() {
 93        let elem: Element = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='128' sid='coucou' stanza='fdsq'/>".parse().unwrap();
 94        let error = jingle_ibb::parse_jingle_ibb(&elem).unwrap_err();
 95        let message = match error {
 96            Error::ParseError(string) => string,
 97            _ => panic!(),
 98        };
 99        assert_eq!(message, "Invalid 'stanza' attribute.");
100    }
101}