dialtone_common 0.1.0

Dialtone Common Code
Documentation
use serde::{Deserialize, Serialize};

/// Image attributes are structures similar to activity pub objects but
/// are children of an activity pub object and without an ID. For actors,
/// these are "icon" and "image".

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(untagged)]
pub enum ImageAttributes {
    SingleUrl(String),
    MultipleUrls(Vec<String>),
    SingleObj(ImageAttributeObj),
    MultipleObjs(Vec<ImageAttributeObj>),
}

/// ImageAttributes only have one type, which is "image"
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub enum ImageAttributeType {
    Image,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct ImageAttributeObj {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub summary: Option<String>,

    pub url: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub width: Option<u32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub height: Option<u32>,

    #[serde(rename = "mediaType")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub media_type: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(rename = "type")]
    pub ap_type: Option<ImageAttributeType>,
}

impl ImageAttributes {
    pub fn icons_vec(&self) -> Vec<ImageAttributeObj> {
        match self {
            ImageAttributes::SingleUrl(url) => {
                vec![ImageAttributeObj::from(url.to_string())]
            }
            ImageAttributes::MultipleUrls(urls) => urls
                .iter()
                .map(|url| ImageAttributeObj::from(url.to_string()))
                .collect(),
            ImageAttributes::SingleObj(obj) => {
                vec![obj.clone()]
            }
            ImageAttributes::MultipleObjs(objs) => objs.clone(),
        }
    }

    pub fn first(&self) -> Option<ImageAttributeObj> {
        match self {
            ImageAttributes::SingleUrl(url) => {
                Option::from(ImageAttributeObj::from(url.to_string()))
            }
            ImageAttributes::MultipleUrls(urls) => urls
                .iter()
                .map(|url| ImageAttributeObj::from(url.to_string()))
                .take(1)
                .next(),
            ImageAttributes::SingleObj(obj) => Option::from(obj.clone()),
            ImageAttributes::MultipleObjs(objs) => objs.iter().next().cloned(),
        }
    }
}

impl From<String> for ImageAttributeObj {
    fn from(url: String) -> ImageAttributeObj {
        ImageAttributeObj {
            summary: None,
            url,
            width: None,
            height: None,
            media_type: None,
            ap_type: Option::from(ImageAttributeType::Image),
        }
    }
}

#[cfg(test)]
mod icon_tests {
    use super::*;

    #[test]
    fn parse_single_url() {
        let u1 = "http://example.com/icon.png";
        let j = format!("\"{}\"", u1);
        let icon: ImageAttributes = serde_json::from_str(&j).unwrap();
        let v = icon.icons_vec();
        assert_eq!(1, v.len());
        assert_eq!(u1.to_string(), v[0].url);
    }

    #[test]
    fn parse_array_of_urls() {
        let u1 = "http://example.com/icon.png";
        let u2 = "http://example.org/foo.png";
        let j = format!("[\"{}\",\"{}\"]", u1, u2);
        let icon: ImageAttributes = serde_json::from_str(&j).unwrap();
        let v = icon.icons_vec();
        assert_eq!(2, v.len());
        assert_eq!(u1.to_string(), v[0].url);
        assert_eq!(u2.to_string(), v[1].url);
    }

    #[test]
    fn parse_obj() {
        let u1 = "http://example.com/icon.png";
        let j = format!("{{\"url\":\"{}\"}}", u1);
        let icon: ImageAttributes = serde_json::from_str(&j).unwrap();
        let v = icon.icons_vec();
        assert_eq!(1, v.len());
        assert_eq!(u1.to_string(), v[0].url);
    }

    #[test]
    fn parse_multiple_objs() {
        let u1 = "http://example.com/icon.png";
        let u2 = "http://example.org/foo.png";
        let j = format!("[{{\"url\":\"{}\"}},{{\"url\":\"{}\"}}]", u1, u2);
        let icon: ImageAttributes = serde_json::from_str(&j).unwrap();
        let v = icon.icons_vec();
        assert_eq!(2, v.len());
        assert_eq!(u1.to_string(), v[0].url);
        assert_eq!(u2.to_string(), v[1].url);
    }

    #[test]
    fn size_of_icons() {
        println!(
            "Size of Icons is {}",
            std::mem::size_of::<ImageAttributes>()
        )
    }
}