use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Attachment {
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub grant_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub content_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub content_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_inline: Option<bool>,
}
impl Attachment {
pub fn builder() -> AttachmentBuilder {
AttachmentBuilder::default()
}
}
#[derive(Debug, Clone, Default)]
pub struct AttachmentBuilder {
id: Option<String>,
grant_id: Option<String>,
filename: Option<String>,
content_type: Option<String>,
size: Option<u64>,
content_id: Option<String>,
is_inline: Option<bool>,
}
impl AttachmentBuilder {
pub fn id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
pub fn grant_id(mut self, grant_id: impl Into<String>) -> Self {
self.grant_id = Some(grant_id.into());
self
}
pub fn filename(mut self, filename: impl Into<String>) -> Self {
self.filename = Some(filename.into());
self
}
pub fn content_type(mut self, content_type: impl Into<String>) -> Self {
self.content_type = Some(content_type.into());
self
}
pub fn size(mut self, size: u64) -> Self {
self.size = Some(size);
self
}
pub fn content_id(mut self, content_id: impl Into<String>) -> Self {
self.content_id = Some(content_id.into());
self
}
pub fn is_inline(mut self, is_inline: bool) -> Self {
self.is_inline = Some(is_inline);
self
}
pub fn build(self) -> Attachment {
Attachment {
id: self.id.expect("Attachment ID is required"),
grant_id: self.grant_id,
filename: self.filename,
content_type: self.content_type,
size: self.size,
content_id: self.content_id,
is_inline: self.is_inline,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_attachment_creation() {
let attachment = Attachment {
id: "att_123".to_string(),
grant_id: Some("grant_123".to_string()),
filename: Some("document.pdf".to_string()),
content_type: Some("application/pdf".to_string()),
size: Some(12345),
content_id: None,
is_inline: Some(false),
};
assert_eq!(attachment.id, "att_123");
assert_eq!(attachment.filename, Some("document.pdf".to_string()));
assert_eq!(attachment.size, Some(12345));
}
#[test]
fn test_attachment_builder() {
let attachment = Attachment::builder()
.id("att_123")
.filename("test.pdf")
.content_type("application/pdf")
.size(1024)
.is_inline(false)
.build();
assert_eq!(attachment.id, "att_123");
assert_eq!(attachment.filename, Some("test.pdf".to_string()));
assert_eq!(attachment.content_type, Some("application/pdf".to_string()));
assert_eq!(attachment.size, Some(1024));
assert_eq!(attachment.is_inline, Some(false));
}
#[test]
fn test_attachment_inline() {
let attachment = Attachment::builder()
.id("att_inline")
.filename("image.png")
.content_type("image/png")
.content_id("img001")
.is_inline(true)
.build();
assert_eq!(attachment.content_id, Some("img001".to_string()));
assert_eq!(attachment.is_inline, Some(true));
}
#[test]
fn test_attachment_serialization() {
let attachment = Attachment {
id: "att_123".to_string(),
grant_id: Some("grant_123".to_string()),
filename: Some("test.pdf".to_string()),
content_type: Some("application/pdf".to_string()),
size: Some(5000),
content_id: None,
is_inline: Some(false),
};
let json = serde_json::to_string(&attachment).unwrap();
assert!(json.contains("att_123"));
assert!(json.contains("test.pdf"));
assert!(json.contains("5000"));
let deserialized: Attachment = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, attachment);
}
#[test]
fn test_attachment_minimal() {
let attachment = Attachment::builder().id("att_minimal").build();
assert_eq!(attachment.id, "att_minimal");
assert_eq!(attachment.filename, None);
assert_eq!(attachment.size, None);
}
#[test]
#[should_panic(expected = "Attachment ID is required")]
fn test_attachment_builder_without_id() {
Attachment::builder().filename("test.pdf").build();
}
}