core_invoice/
attachment.rs1use crate::error::AttachmentError;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Attachment {
8 pub bytes: Vec<u8>,
10 pub mime: String,
12 pub filename: String,
14}
15
16impl Attachment {
17 pub const RECEIVER_MUST_ACCEPT: &'static [&'static str] = &[
19 "application/pdf",
20 "image/png",
21 "image/jpeg",
22 "text/csv",
23 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
24 "application/vnd.oasis.opendocument.spreadsheet",
25 ];
26
27 pub fn new(
29 bytes: Vec<u8>,
30 mime: impl Into<String>,
31 filename: impl Into<String>,
32 ) -> Result<Self, AttachmentError> {
33 let mime = mime.into();
34 let filename = filename.into();
35 if mime.trim().is_empty() {
36 return Err(AttachmentError::EmptyMime);
37 }
38 if filename.trim().is_empty() {
39 return Err(AttachmentError::EmptyFilename);
40 }
41 Ok(Self {
42 bytes,
43 mime,
44 filename,
45 })
46 }
47
48 pub fn is_universally_accepted(&self) -> bool {
50 Self::RECEIVER_MUST_ACCEPT.contains(&self.mime.as_str())
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn rejects_blank_mime_or_filename() {
60 assert!(Attachment::new(vec![], "", "x.pdf").is_err());
61 assert!(Attachment::new(vec![], "application/pdf", " ").is_err());
62 let a = Attachment::new(b"%PDF".to_vec(), "application/pdf", "terms.pdf").unwrap();
63 assert!(a.is_universally_accepted());
64 }
65}