Skip to main content

easyofd_core/attachment/
attachments.rs

1//! 附件容器。
2
3use super::ct_attachment::CTAttachment;
4
5/// 对应 Java: org.ofdrw.core.attachment.Attachments
6///
7/// 附件根容器,对应 Attachments.xml,包含文档中所有附件。
8#[derive(Debug, Clone)]
9pub struct Attachments {
10    /// 文档中所有附件列表。
11    pub items: Vec<CTAttachment>,
12}
13
14impl Attachments {
15    /// 创建一个空的附件容器。
16    #[must_use]
17    pub fn new() -> Self {
18        Self { items: Vec::new() }
19    }
20
21    /// 添加附件。
22    #[must_use]
23    pub fn add_attachment(mut self, attachment: CTAttachment) -> Self {
24        self.items.push(attachment);
25        self
26    }
27
28    /// 返回附件数量。
29    #[must_use]
30    pub fn len(&self) -> usize {
31        self.items.len()
32    }
33
34    /// 是否为空。
35    #[must_use]
36    pub fn is_empty(&self) -> bool {
37        self.items.is_empty()
38    }
39
40    /// 序列化为 XML 字符串。
41    #[must_use]
42    pub fn to_xml_string(&self) -> String {
43        let mut xml = String::from(r#"<?xml version="1.0" encoding="UTF-8"?>"#);
44        xml.push('\n');
45        xml.push_str(r#"<ofd:Attachments xmlns:ofd="http://www.ofdspec.org/2016">"#);
46        for item in &self.items {
47            xml.push('\n');
48            xml.push_str(&item.to_xml_string());
49        }
50        xml.push_str("\n</ofd:Attachments>");
51        xml
52    }
53}
54
55impl Default for Attachments {
56    fn default() -> Self {
57        Self::new()
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_attachments_new() {
67        let a = Attachments::new();
68        assert!(a.items.is_empty());
69        assert!(a.is_empty());
70        assert_eq!(a.len(), 0);
71    }
72
73    #[test]
74    fn test_attachments_default() {
75        let a = Attachments::default();
76        assert!(a.is_empty());
77    }
78
79    #[test]
80    fn test_attachments_add() {
81        let a = Attachments::new()
82            .add_attachment(CTAttachment::new("a1", "readme.txt"))
83            .add_attachment(CTAttachment::new("a2", "data.xlsx"));
84        assert_eq!(a.len(), 2);
85        assert!(!a.is_empty());
86        assert_eq!(a.items[0].id, "a1");
87        assert_eq!(a.items[1].id, "a2");
88    }
89
90    #[test]
91    fn test_attachments_to_xml_string() {
92        let a = Attachments::new()
93            .add_attachment(CTAttachment::new("a1", "test.pdf").format("application/pdf"));
94        let xml = a.to_xml_string();
95        assert!(xml.contains(r#"<?xml version="1.0""#));
96        assert!(xml.contains("ofd:Attachments"));
97        assert!(xml.contains(r#"ID="a1""#));
98        assert!(xml.contains(r#"Name="test.pdf""#));
99        assert!(xml.contains("</ofd:Attachments>"));
100    }
101
102    #[test]
103    fn test_attachments_to_xml_string_empty() {
104        let a = Attachments::new();
105        let xml = a.to_xml_string();
106        assert!(xml.contains("ofd:Attachments"));
107        assert!(xml.contains("</ofd:Attachments>"));
108    }
109
110    #[test]
111    fn test_attachments_clone_debug() {
112        let a = Attachments::new().add_attachment(CTAttachment::new("x", "y.txt"));
113        let a2 = a.clone();
114        assert_eq!(a2.len(), 1);
115        assert!(format!("{a:?}").contains("Attachments"));
116    }
117}