use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct Attachment {
pub data: AttachmentData,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub media_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub format: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lastmod_time: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub byte_count: Option<u64>,
}
impl Attachment {
pub fn base64(base64: String) -> AttachmentBuilder {
AttachmentBuilder::new(AttachmentData::Base64 {
value: Base64AttachmentData { base64, jws: None },
})
}
pub fn json(json: Value) -> AttachmentBuilder {
AttachmentBuilder::new(AttachmentData::Json {
value: JsonAttachmentData { json, jws: None },
})
}
pub fn links(links: Vec<String>, hash: String) -> AttachmentBuilder {
AttachmentBuilder::new(AttachmentData::Links {
value: LinksAttachmentData {
links,
hash,
jws: None,
},
})
}
}
pub struct AttachmentBuilder {
data: AttachmentData,
id: Option<String>,
description: Option<String>,
filename: Option<String>,
media_type: Option<String>,
format: Option<String>,
lastmod_time: Option<u64>,
byte_count: Option<u64>,
}
impl AttachmentBuilder {
fn new(data: AttachmentData) -> Self {
AttachmentBuilder {
data,
id: None,
description: None,
filename: None,
media_type: None,
format: None,
lastmod_time: None,
byte_count: None,
}
}
pub fn id(mut self, id: String) -> Self {
self.id = Some(id);
self
}
pub fn description(mut self, description: String) -> Self {
self.description = Some(description);
self
}
pub fn filename(mut self, filename: String) -> Self {
self.filename = Some(filename);
self
}
pub fn media_type(mut self, media_type: String) -> Self {
self.media_type = Some(media_type);
self
}
pub fn format(mut self, format: String) -> Self {
self.format = Some(format);
self
}
pub fn lastmod_time(mut self, lastmod_time: u64) -> Self {
self.lastmod_time = Some(lastmod_time);
self
}
pub fn byte_count(mut self, byte_count: u64) -> Self {
self.byte_count = Some(byte_count);
self
}
pub fn jws(mut self, jws: String) -> Self {
match self.data {
AttachmentData::Base64 { ref mut value } => value.jws = Some(jws),
AttachmentData::Json { ref mut value } => value.jws = Some(jws),
AttachmentData::Links { ref mut value } => value.jws = Some(jws),
}
self
}
pub fn finalize(self) -> Attachment {
Attachment {
data: self.data,
id: self.id,
description: self.description,
filename: self.filename,
media_type: self.media_type,
format: self.format,
lastmod_time: self.lastmod_time,
byte_count: self.byte_count,
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
#[serde(untagged)]
pub enum AttachmentData {
Base64 {
#[serde(flatten)]
value: Base64AttachmentData,
},
Json {
#[serde(flatten)]
value: JsonAttachmentData,
},
Links {
#[serde(flatten)]
value: LinksAttachmentData,
},
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct Base64AttachmentData {
pub base64: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub jws: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct JsonAttachmentData {
pub json: Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub jws: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct LinksAttachmentData {
pub links: Vec<String>,
pub hash: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub jws: Option<String>,
}
#[cfg(test)]
mod tests {
use core::panic;
use serde_json::json;
use super::*;
#[test]
fn attachment_base64_works() {
let attachment = Attachment::base64("ZXhhbXBsZQ==".to_owned())
.id("example-1".to_owned())
.description("example-1-description".to_owned())
.filename("attachment-1".to_owned())
.media_type("message/example".to_owned())
.format("json".to_owned())
.lastmod_time(10000)
.byte_count(200)
.jws("jws".to_owned())
.finalize();
let data = match attachment.data {
AttachmentData::Base64 { ref value } => value,
_ => panic!("data isn't base64."),
};
assert_eq!(data.base64, "ZXhhbXBsZQ==");
assert_eq!(data.jws, Some("jws".to_owned()));
assert_eq!(attachment.id, Some("example-1".to_owned()));
assert_eq!(
attachment.description,
Some("example-1-description".to_owned())
);
assert_eq!(attachment.filename, Some("attachment-1".to_owned()));
assert_eq!(attachment.media_type, Some("message/example".to_owned()));
assert_eq!(attachment.format, Some("json".to_owned()));
assert_eq!(attachment.lastmod_time, Some(10000));
assert_eq!(attachment.byte_count, Some(200));
}
#[test]
fn attachment_json_works() {
let attachment = Attachment::json(json!("example"))
.id("example-1".to_owned())
.description("example-1-description".to_owned())
.filename("attachment-1".to_owned())
.media_type("message/example".to_owned())
.format("json".to_owned())
.lastmod_time(10000)
.byte_count(200)
.jws("jws".to_owned())
.finalize();
let data = match attachment.data {
AttachmentData::Json { ref value } => value,
_ => panic!("data isn't json."),
};
assert_eq!(data.json, json!("example"));
assert_eq!(data.jws, Some("jws".to_owned()));
assert_eq!(attachment.id, Some("example-1".to_owned()));
assert_eq!(
attachment.description,
Some("example-1-description".to_owned())
);
assert_eq!(attachment.filename, Some("attachment-1".to_owned()));
assert_eq!(attachment.media_type, Some("message/example".to_owned()));
assert_eq!(attachment.format, Some("json".to_owned()));
assert_eq!(attachment.lastmod_time, Some(10000));
assert_eq!(attachment.byte_count, Some(200));
}
#[test]
fn attachment_links_works() {
let attachment = Attachment::links(
vec!["http://example1".to_owned(), "https://example2".to_owned()],
"50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c".to_owned(),
)
.id("example-1".to_owned())
.description("example-1-description".to_owned())
.filename("attachment-1".to_owned())
.media_type("message/example".to_owned())
.format("json".to_owned())
.lastmod_time(10000)
.byte_count(200)
.jws("jws".to_owned())
.finalize();
let data = match attachment.data {
AttachmentData::Links { ref value } => value,
_ => panic!("data isn't links."),
};
assert_eq!(
data.links,
vec!["http://example1".to_owned(), "https://example2".to_owned()]
);
assert_eq!(
data.hash,
"50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c".to_owned()
);
assert_eq!(data.jws, Some("jws".to_owned()));
assert_eq!(attachment.id, Some("example-1".to_owned()));
assert_eq!(
attachment.description,
Some("example-1-description".to_owned())
);
assert_eq!(attachment.filename, Some("attachment-1".to_owned()));
assert_eq!(attachment.media_type, Some("message/example".to_owned()));
assert_eq!(attachment.format, Some("json".to_owned()));
assert_eq!(attachment.lastmod_time, Some(10000));
assert_eq!(attachment.byte_count, Some(200));
}
}