use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(untagged)]
pub enum ImageAttributes {
SingleUrl(String),
MultipleUrls(Vec<String>),
SingleObj(ImageAttributeObj),
MultipleObjs(Vec<ImageAttributeObj>),
}
#[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>()
)
}
}