1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct DocProperties {
10 #[serde(default)]
11 pub category: String,
12 #[serde(rename = "ContentStatus", default)]
13 pub content_status: String,
14 #[serde(default)]
15 pub created: String,
16 #[serde(default)]
17 pub creator: String,
18 #[serde(default)]
19 pub description: String,
20 #[serde(default)]
21 pub identifier: String,
22 #[serde(default)]
23 pub keywords: String,
24 #[serde(rename = "LastModifiedBy", default)]
25 pub last_modified_by: String,
26 #[serde(default)]
27 pub modified: String,
28 #[serde(default)]
29 pub revision: String,
30 #[serde(default)]
31 pub subject: String,
32 #[serde(default)]
33 pub title: String,
34 #[serde(default)]
35 pub language: String,
36 #[serde(default)]
37 pub version: String,
38}
39
40#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
42pub struct DecodeDcTerms {
43 #[serde(rename = "$value", default)]
44 pub text: String,
45 #[serde(rename = "@xsi:type", default)]
46 pub r#type: Option<String>,
47}
48
49#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
51#[serde(rename = "coreProperties", rename_all = "PascalCase")]
52pub struct DecodeCoreProperties {
53 #[serde(rename = "title", default)]
54 pub title: Option<String>,
55 #[serde(rename = "subject", default)]
56 pub subject: Option<String>,
57 #[serde(rename = "creator", default)]
58 pub creator: Option<String>,
59 #[serde(default)]
60 pub keywords: Option<String>,
61 #[serde(rename = "description", default)]
62 pub description: Option<String>,
63 #[serde(rename = "lastModifiedBy", default)]
64 pub last_modified_by: Option<String>,
65 #[serde(rename = "language", default)]
66 pub language: Option<String>,
67 #[serde(rename = "identifier", default)]
68 pub identifier: Option<String>,
69 #[serde(default)]
70 pub revision: Option<String>,
71 #[serde(rename = "created", default)]
72 pub created: Option<DecodeDcTerms>,
73 #[serde(rename = "modified", default)]
74 pub modified: Option<DecodeDcTerms>,
75 #[serde(rename = "contentStatus", default)]
76 pub content_status: Option<String>,
77 #[serde(default)]
78 pub category: Option<String>,
79 #[serde(default)]
80 pub version: Option<String>,
81}
82
83#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
85pub struct XlsxDcTerms {
86 #[serde(rename = "$value", default)]
87 pub text: String,
88 #[serde(rename = "@xsi:type", default, skip_serializing_if = "Option::is_none")]
89 pub r#type: Option<String>,
90}
91
92#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
94#[serde(rename = "coreProperties", rename_all = "PascalCase")]
95pub struct XlsxCoreProperties {
96 #[serde(rename = "@xmlns:dc", default, skip_serializing_if = "Option::is_none")]
97 pub dc: Option<String>,
98 #[serde(
99 rename = "@xmlns:dcterms",
100 default,
101 skip_serializing_if = "Option::is_none"
102 )]
103 pub dcterms: Option<String>,
104 #[serde(
105 rename = "@xmlns:dcmitype",
106 default,
107 skip_serializing_if = "Option::is_none"
108 )]
109 pub dcmitype: Option<String>,
110 #[serde(
111 rename = "@xmlns:xsi",
112 default,
113 skip_serializing_if = "Option::is_none"
114 )]
115 pub xsi: Option<String>,
116 #[serde(rename = "dc:title", default, skip_serializing_if = "Option::is_none")]
117 pub title: Option<String>,
118 #[serde(
119 rename = "dc:subject",
120 default,
121 skip_serializing_if = "Option::is_none"
122 )]
123 pub subject: Option<String>,
124 #[serde(
125 rename = "dc:creator",
126 default,
127 skip_serializing_if = "Option::is_none"
128 )]
129 pub creator: Option<String>,
130 #[serde(default, skip_serializing_if = "Option::is_none")]
131 pub keywords: Option<String>,
132 #[serde(
133 rename = "dc:description",
134 default,
135 skip_serializing_if = "Option::is_none"
136 )]
137 pub description: Option<String>,
138 #[serde(
139 rename = "lastModifiedBy",
140 default,
141 skip_serializing_if = "Option::is_none"
142 )]
143 pub last_modified_by: Option<String>,
144 #[serde(
145 rename = "dc:language",
146 default,
147 skip_serializing_if = "Option::is_none"
148 )]
149 pub language: Option<String>,
150 #[serde(
151 rename = "dc:identifier",
152 default,
153 skip_serializing_if = "Option::is_none"
154 )]
155 pub identifier: Option<String>,
156 #[serde(default, skip_serializing_if = "Option::is_none")]
157 pub revision: Option<String>,
158 #[serde(
159 rename = "dcterms:created",
160 default,
161 skip_serializing_if = "Option::is_none"
162 )]
163 pub created: Option<XlsxDcTerms>,
164 #[serde(
165 rename = "dcterms:modified",
166 default,
167 skip_serializing_if = "Option::is_none"
168 )]
169 pub modified: Option<XlsxDcTerms>,
170 #[serde(
171 rename = "contentStatus",
172 default,
173 skip_serializing_if = "Option::is_none"
174 )]
175 pub content_status: Option<String>,
176 #[serde(default, skip_serializing_if = "Option::is_none")]
177 pub category: Option<String>,
178 #[serde(default, skip_serializing_if = "Option::is_none")]
179 pub version: Option<String>,
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185 use quick_xml::de::from_str;
186
187 #[test]
188 fn deserialize_created() {
189 let s = r#"<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dcterms:created xsi:type="dcterms:W3CDTF">2019-06-04T22:00:10Z</dcterms:created></cp:coreProperties>"#;
190 let core: DecodeCoreProperties = from_str(s).unwrap();
191 assert_eq!(core.created.as_ref().unwrap().text, "2019-06-04T22:00:10Z");
192 }
193
194 #[test]
195 fn deserialize_created_simple() {
196 let s = r#"<coreProperties xmlns:dcterms="http://purl.org/dc/terms/"><dcterms:created>2019-06-04T22:00:10Z</dcterms:created></coreProperties>"#;
197 let core: DecodeCoreProperties = from_str(s).unwrap();
198 assert_eq!(core.created.as_ref().unwrap().text, "2019-06-04T22:00:10Z");
199 }
200}