avatar.rs

  1// Copyright (c) 2019 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 crate::hashes::Sha1HexAttribute;
  8use crate::pubsub::PubSubPayload;
  9use crate::util::helpers::WhitespaceAwareBase64;
 10
 11generate_element!(
 12    /// Communicates information about an avatar.
 13    Metadata, "metadata", AVATAR_METADATA,
 14    children: [
 15        /// List of information elements describing this avatar.
 16        infos: Vec<Info> = ("info", AVATAR_METADATA) => Info
 17    ]
 18);
 19
 20impl PubSubPayload for Metadata {}
 21
 22generate_element!(
 23    /// Communicates avatar metadata.
 24    Info, "info", AVATAR_METADATA,
 25    attributes: [
 26        /// The size of the image data in bytes.
 27        bytes: Required<u16> = "bytes",
 28
 29        /// The width of the image in pixels.
 30        width: Option<u16> = "width",
 31
 32        /// The height of the image in pixels.
 33        height: Option<u16> = "height",
 34
 35        /// The SHA-1 hash of the image data for the specified content-type.
 36        id: Required<Sha1HexAttribute> = "id",
 37
 38        /// The IANA-registered content type of the image data.
 39        type_: Required<String> = "type",
 40
 41        /// The http: or https: URL at which the image data file is hosted.
 42        url: Option<String> = "url",
 43    ]
 44);
 45
 46generate_element!(
 47    /// The actual avatar data.
 48    Data, "data", AVATAR_DATA,
 49    text: (
 50        /// Vector of bytes representing the avatar’s image.
 51        data: WhitespaceAwareBase64<Vec<u8>>
 52    )
 53);
 54
 55impl PubSubPayload for Data {}
 56
 57#[cfg(test)]
 58mod tests {
 59    use super::*;
 60    use crate::hashes::Algo;
 61    use crate::util::error::Error;
 62    use minidom::Element;
 63    use std::convert::TryFrom;
 64
 65    #[cfg(target_pointer_width = "32")]
 66    #[test]
 67    fn test_size() {
 68        assert_size!(Metadata, 12);
 69        assert_size!(Info, 64);
 70        assert_size!(Data, 12);
 71    }
 72
 73    #[cfg(target_pointer_width = "64")]
 74    #[test]
 75    fn test_size() {
 76        assert_size!(Metadata, 24);
 77        assert_size!(Info, 120);
 78        assert_size!(Data, 24);
 79    }
 80
 81    #[test]
 82    fn test_simple() {
 83        let elem: Element = "<metadata xmlns='urn:xmpp:avatar:metadata'>
 84                                 <info bytes='12345' width='64' height='64'
 85                                       id='111f4b3c50d7b0df729d299bc6f8e9ef9066971f'
 86                                       type='image/png'/>
 87                             </metadata>"
 88            .parse()
 89            .unwrap();
 90        let metadata = Metadata::try_from(elem).unwrap();
 91        assert_eq!(metadata.infos.len(), 1);
 92        let info = &metadata.infos[0];
 93        assert_eq!(info.bytes, 12345);
 94        assert_eq!(info.width, Some(64));
 95        assert_eq!(info.height, Some(64));
 96        assert_eq!(info.id.algo, Algo::Sha_1);
 97        assert_eq!(info.type_, "image/png");
 98        assert_eq!(info.url, None);
 99        assert_eq!(
100            info.id.hash,
101            [
102                17, 31, 75, 60, 80, 215, 176, 223, 114, 157, 41, 155, 198, 248, 233, 239, 144, 102,
103                151, 31
104            ]
105        );
106
107        let elem: Element = "<data xmlns='urn:xmpp:avatar:data'>AAAA</data>"
108            .parse()
109            .unwrap();
110        let data = Data::try_from(elem).unwrap();
111        assert_eq!(data.data, b"\0\0\0");
112    }
113
114    #[cfg(not(feature = "disable-validation"))]
115    #[test]
116    fn test_invalid() {
117        let elem: Element = "<data xmlns='urn:xmpp:avatar:data' id='coucou'/>"
118            .parse()
119            .unwrap();
120        let error = Data::try_from(elem).unwrap_err();
121        let message = match error {
122            Error::ParseError(string) => string,
123            _ => panic!(),
124        };
125        assert_eq!(message, "Unknown attribute in data element.")
126    }
127}