Skip to main content

core_invoice/
attachment.rs

1//! Binary [`Attachment`]: bytes, MIME, and filename (BT-125).
2
3use crate::error::AttachmentError;
4
5/// Binary object: bytes + mime + filename, all mandatory and non-blank.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Attachment {
8    /// BT-125 attached document bytes.
9    pub bytes: Vec<u8>,
10    /// MIME code of BT-125. Mandatory, non-blank.
11    pub mime: String,
12    /// Filename of BT-125. Mandatory, non-blank.
13    pub filename: String,
14}
15
16impl Attachment {
17    /// CEN receiver-must-accept MIME list. Advisory; the constructor does not restrict to this.
18    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    /// Bytes + mime + filename. Blank mime or filename is `Err`.
28    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    /// Whether mime is on the CEN receiver-must-accept list.
49    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}