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