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