hashes.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 std::convert::TryFrom;
 8
 9use minidom::Element;
10
11use error::Error;
12
13use ns;
14
15#[derive(Debug, Clone, PartialEq)]
16pub struct Hash {
17    pub algo: String,
18    pub hash: String,
19}
20
21impl<'a> TryFrom<&'a Element> for Hash {
22    type Error = Error;
23
24    fn try_from(elem: &'a Element) -> Result<Hash, Error> {
25        if !elem.is("hash", ns::HASHES) {
26            return Err(Error::ParseError("This is not a hash element."));
27        }
28        for _ in elem.children() {
29            return Err(Error::ParseError("Unknown child in hash element."));
30        }
31        let algo = elem.attr("algo").ok_or(Error::ParseError("Mandatory argument 'algo' not present in hash element."))?.to_owned();
32        let hash = match elem.text().as_ref() {
33            "" => return Err(Error::ParseError("Hash element shouldn’t be empty.")),
34            text => text.to_owned(),
35        };
36        Ok(Hash {
37            algo: algo,
38            hash: hash,
39        })
40    }
41}
42
43impl<'a> Into<Element> for &'a Hash {
44    fn into(self) -> Element {
45        Element::builder("hash")
46                .ns(ns::HASHES)
47                .attr("algo", self.algo.clone())
48                .append(self.hash.clone())
49                .build()
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_simple() {
59        let elem: Element = "<hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=</hash>".parse().unwrap();
60        let hash = Hash::try_from(&elem).unwrap();
61        assert_eq!(hash.algo, "sha-256");
62        assert_eq!(hash.hash, "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=");
63    }
64
65    #[test]
66    fn test_unknown() {
67        let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0'/>".parse().unwrap();
68        let error = Hash::try_from(&elem).unwrap_err();
69        let message = match error {
70            Error::ParseError(string) => string,
71            _ => panic!(),
72        };
73        assert_eq!(message, "This is not a hash element.");
74    }
75
76    #[test]
77    fn test_invalid_child() {
78        let elem: Element = "<hash xmlns='urn:xmpp:hashes:2'><coucou/></hash>".parse().unwrap();
79        let error = Hash::try_from(&elem).unwrap_err();
80        let message = match error {
81            Error::ParseError(string) => string,
82            _ => panic!(),
83        };
84        assert_eq!(message, "Unknown child in hash element.");
85    }
86}