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    #[cfg(not(feature = "disable-validation"))]
 62    use crate::util::error::Error;
 63    use crate::Element;
 64    use std::convert::TryFrom;
 65
 66    #[cfg(target_pointer_width = "32")]
 67    #[test]
 68    fn test_size() {
 69        assert_size!(Metadata, 12);
 70        assert_size!(Info, 64);
 71        assert_size!(Data, 12);
 72    }
 73
 74    #[cfg(target_pointer_width = "64")]
 75    #[test]
 76    fn test_size() {
 77        assert_size!(Metadata, 24);
 78        assert_size!(Info, 120);
 79        assert_size!(Data, 24);
 80    }
 81
 82    #[test]
 83    fn test_simple() {
 84        let elem: Element = "<metadata xmlns='urn:xmpp:avatar:metadata'>
 85                                 <info bytes='12345' width='64' height='64'
 86                                       id='111f4b3c50d7b0df729d299bc6f8e9ef9066971f'
 87                                       type='image/png'/>
 88                             </metadata>"
 89            .parse()
 90            .unwrap();
 91        let metadata = Metadata::try_from(elem).unwrap();
 92        assert_eq!(metadata.infos.len(), 1);
 93        let info = &metadata.infos[0];
 94        assert_eq!(info.bytes, 12345);
 95        assert_eq!(info.width, Some(64));
 96        assert_eq!(info.height, Some(64));
 97        assert_eq!(info.id.algo, Algo::Sha_1);
 98        assert_eq!(info.type_, "image/png");
 99        assert_eq!(info.url, None);
100        assert_eq!(
101            info.id.hash,
102            [
103                17, 31, 75, 60, 80, 215, 176, 223, 114, 157, 41, 155, 198, 248, 233, 239, 144, 102,
104                151, 31
105            ]
106        );
107
108        let elem: Element = "<data xmlns='urn:xmpp:avatar:data'>AAAA</data>"
109            .parse()
110            .unwrap();
111        let data = Data::try_from(elem).unwrap();
112        assert_eq!(data.data, b"\0\0\0");
113    }
114
115    #[cfg(not(feature = "disable-validation"))]
116    #[test]
117    fn test_invalid() {
118        let elem: Element = "<data xmlns='urn:xmpp:avatar:data' id='coucou'/>"
119            .parse()
120            .unwrap();
121        let error = Data::try_from(elem).unwrap_err();
122        let message = match error {
123            Error::ParseError(string) => string,
124            _ => panic!(),
125        };
126        assert_eq!(message, "Unknown attribute in data element.")
127    }
128}