winprint_ext/ticket/document/
writer.rs1use super::{NS_PSF, NS_XSI};
2use std::{borrow::Cow, io::Write};
3use xml::{
4 attribute::Attribute, name::OwnedName, namespace::Namespace, writer::XmlEvent, EmitterConfig,
5 EventWriter,
6};
7
8impl XmlDocumentRoot for super::PrintCapabilitiesDocument {}
10impl XmlDocumentRoot for super::PrintTicketDocument {}
11
12pub trait XmlSerializer {
14 fn collect_namespace(&self, ns: &mut Namespace);
16 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error>;
18}
19
20pub trait XmlDocumentRoot: XmlSerializer {
22 fn to_xml(&self) -> Vec<u8> {
24 let mut writer = EmitterConfig::new()
25 .perform_indent(false)
26 .create_writer(Vec::new());
27 let mut ns = Namespace::empty();
28 self.collect_namespace(&mut ns);
29 self.write_to(&mut writer).unwrap();
30 writer.into_inner()
31 }
32}
33
34impl XmlSerializer for super::PrintCapabilitiesDocument {
35 fn collect_namespace(&self, ns: &mut Namespace) {
36 ns.put("psf", NS_PSF);
37 self.properties.iter().for_each(|x| x.collect_namespace(ns));
38 self.parameter_defs
39 .iter()
40 .for_each(|x| x.collect_namespace(ns));
41 self.features.iter().for_each(|x| x.collect_namespace(ns));
42 }
43
44 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
45 {
46 let mut ns = Namespace::empty();
47 self.collect_namespace(&mut ns);
48 let event = XmlEvent::StartElement {
49 name: "psf:PrintCapabilities".into(),
50 attributes: Cow::Owned(vec![Attribute::new("version".into(), "1")]),
51 namespace: Cow::Owned(ns),
52 };
53 writer.write(event)?;
54 }
55 self.properties
56 .iter()
57 .try_for_each(|x| x.write_to(writer))?;
58 self.parameter_defs
59 .iter()
60 .try_for_each(|x| x.write_to(writer))?;
61 self.features.iter().try_for_each(|x| x.write_to(writer))?;
62 writer.write(XmlEvent::end_element())?;
63 Ok(())
64 }
65}
66
67impl XmlSerializer for super::PrintTicketDocument {
68 fn collect_namespace(&self, ns: &mut Namespace) {
69 ns.put("psf", NS_PSF);
70 self.properties.iter().for_each(|x| x.collect_namespace(ns));
71 self.parameter_inits
72 .iter()
73 .for_each(|x| x.collect_namespace(ns));
74 self.features.iter().for_each(|x| x.collect_namespace(ns));
75 }
76
77 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
78 {
79 let mut ns = Namespace::empty();
80 self.collect_namespace(&mut ns);
81 let event = XmlEvent::StartElement {
82 name: "psf:PrintTicket".into(),
83 attributes: Cow::Owned(vec![Attribute::new("version".into(), "1")]),
84 namespace: Cow::Owned(ns),
85 };
86 writer.write(event)?;
87 }
88 self.properties
89 .iter()
90 .try_for_each(|x| x.write_to(writer))?;
91 self.parameter_inits
92 .iter()
93 .try_for_each(|x| x.write_to(writer))?;
94 self.features.iter().try_for_each(|x| x.write_to(writer))?;
95 writer.write(XmlEvent::end_element())?;
96 Ok(())
97 }
98}
99
100impl XmlSerializer for super::PrintFeature {
101 fn collect_namespace(&self, ns: &mut Namespace) {
102 ns.put("psf", NS_PSF);
103 collect_namespace_from_name(&self.name, ns);
104 self.options.iter().for_each(|x| x.collect_namespace(ns));
105 self.properties.iter().for_each(|x| x.collect_namespace(ns));
106 self.features.iter().for_each(|x| x.collect_namespace(ns));
107 }
108
109 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
110 writer.write(
111 XmlEvent::start_element("psf:Feature").attr("name", format_name(&self.name).as_ref()),
112 )?;
113 self.options.iter().try_for_each(|x| x.write_to(writer))?;
114 self.properties
115 .iter()
116 .try_for_each(|x| x.write_to(writer))?;
117 self.features.iter().try_for_each(|x| x.write_to(writer))?;
118 writer.write(XmlEvent::end_element())?;
119 Ok(())
120 }
121}
122
123impl XmlSerializer for super::ParameterInit {
124 fn collect_namespace(&self, ns: &mut Namespace) {
125 ns.put("psf", NS_PSF);
126 collect_namespace_from_name(&self.name, ns);
127 self.value.collect_namespace(ns);
128 }
129
130 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
131 writer.write(
132 XmlEvent::start_element("psf:ParameterInit")
133 .attr("name", format_name(&self.name).as_ref()),
134 )?;
135 self.value.write_to(writer)?;
136 writer.write(XmlEvent::end_element())?;
137 Ok(())
138 }
139}
140
141impl XmlSerializer for super::ParameterDef {
142 fn collect_namespace(&self, ns: &mut Namespace) {
143 ns.put("psf", NS_PSF);
144 collect_namespace_from_name(&self.name, ns);
145 for x in &self.properties {
146 x.collect_namespace(ns);
147 }
148 }
149
150 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
151 writer.write(
152 XmlEvent::start_element("psf:ParameterDef")
153 .attr("name", format_name(&self.name).as_ref()),
154 )?;
155 for x in &self.properties {
156 x.write_to(writer)?;
157 }
158 writer.write(XmlEvent::end_element())?;
159 Ok(())
160 }
161}
162
163impl XmlSerializer for super::PrintFeatureOption {
164 fn collect_namespace(&self, ns: &mut Namespace) {
165 ns.put("psf", NS_PSF);
166 if let Some(name) = &self.name {
167 collect_namespace_from_name(name, ns);
168 }
169 self.scored_properties
170 .iter()
171 .for_each(|x| x.collect_namespace(ns));
172 self.properties.iter().for_each(|x| x.collect_namespace(ns));
173 }
174
175 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
176 start_element_with_optional_name(writer, "psf:Option", self.name.as_ref())?;
177 self.scored_properties
178 .iter()
179 .try_for_each(|x| x.write_to(writer))?;
180 self.properties
181 .iter()
182 .try_for_each(|x| x.write_to(writer))?;
183 writer.write(XmlEvent::end_element())?;
184 Ok(())
185 }
186}
187
188impl XmlSerializer for super::ScoredProperty {
189 fn collect_namespace(&self, ns: &mut Namespace) {
190 ns.put("psf", NS_PSF);
191 if let Some(name) = &self.name {
192 collect_namespace_from_name(name, ns);
193 }
194 if let Some(parameter_ref) = &self.parameter_ref {
195 collect_namespace_from_name(parameter_ref, ns);
196 }
197 if let Some(value) = &self.value {
198 value.collect_namespace(ns);
199 }
200 self.scored_properties
201 .iter()
202 .for_each(|x| x.collect_namespace(ns));
203 self.properties.iter().for_each(|x| x.collect_namespace(ns));
204 }
205
206 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
207 start_element_with_optional_name(writer, "psf:ScoredProperty", self.name.as_ref())?;
208 if let Some(parameter_ref) = &self.parameter_ref {
209 writer.write(
210 XmlEvent::start_element("psf:ParameterRef")
211 .attr("name", format_name(parameter_ref).as_ref()),
212 )?;
213 writer.write(XmlEvent::end_element())?;
214 }
215 if let Some(value) = &self.value {
216 value.write_to(writer)?;
217 }
218 self.scored_properties
219 .iter()
220 .try_for_each(|x| x.write_to(writer))?;
221 self.properties
222 .iter()
223 .try_for_each(|x| x.write_to(writer))?;
224 writer.write(XmlEvent::end_element())?;
225 Ok(())
226 }
227}
228
229impl XmlSerializer for super::Property {
230 fn collect_namespace(&self, ns: &mut Namespace) {
231 ns.put("psf", NS_PSF);
232 collect_namespace_from_name(&self.name, ns);
233 if let Some(value) = &self.value {
234 value.collect_namespace(ns);
235 }
236 self.properties.iter().for_each(|x| x.collect_namespace(ns));
237 }
238
239 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
240 writer.write(
241 XmlEvent::start_element("psf:Property").attr("name", format_name(&self.name).as_ref()),
242 )?;
243 if let Some(value) = &self.value {
244 value.write_to(writer)?;
245 }
246 self.properties
247 .iter()
248 .try_for_each(|x| x.write_to(writer))?;
249 writer.write(XmlEvent::end_element())?;
250 Ok(())
251 }
252}
253
254impl XmlSerializer for super::PropertyValue {
255 fn collect_namespace(&self, ns: &mut Namespace) {
256 ns.put("psf", NS_PSF);
257 ns.put("xsi", NS_XSI);
258 collect_namespace_from_name(&self.xsi_type(), ns);
259 }
260
261 fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), xml::writer::Error> {
262 let xsi_type = self.xsi_type();
263 writer.write(
264 XmlEvent::start_element("psf:Value").attr("xsi:type", format_name(&xsi_type).as_ref()),
265 )?;
266 match self {
267 super::PropertyValue::String(s) => {
268 writer.write(XmlEvent::characters(s))?;
269 }
270 super::PropertyValue::Integer(i) => {
271 writer.write(XmlEvent::characters(&i.to_string()))?;
272 }
273 super::PropertyValue::QName(q) => {
274 writer.write(XmlEvent::characters(&q.to_string()))?;
275 }
276 super::PropertyValue::Unknown(_, s) => {
277 writer.write(XmlEvent::characters(s))?;
278 }
279 }
280 writer.write(XmlEvent::end_element())?;
281 Ok(())
282 }
283}
284
285fn collect_namespace_from_name(name: &OwnedName, ns: &mut Namespace) {
286 if let (Some(prefix), Some(namespace)) = (name.prefix_ref(), name.namespace_ref()) {
287 ns.put(prefix, namespace);
288 }
289}
290
291fn format_name(name: &OwnedName) -> Cow<'_, String> {
293 if let Some(prefix) = name.prefix_ref() {
294 Cow::Owned(format!("{}:{}", prefix, name.local_name))
295 } else {
296 Cow::Borrowed(&name.local_name)
297 }
298}
299
300fn start_element_with_optional_name<W: Write>(
301 writer: &mut EventWriter<W>,
302 elem_name: &str,
303 name: Option<&OwnedName>,
304) -> Result<(), xml::writer::Error> {
305 if let Some(name) = name {
306 writer
307 .write(XmlEvent::start_element(elem_name).attr("name", format_name(name).as_ref()))?;
308 } else {
309 writer.write(XmlEvent::start_element(elem_name))?;
310 }
311 Ok(())
312}
313
314#[cfg(test)]
315mod tests {
316 use super::XmlDocumentRoot;
317 use crate::ticket::document::{
318 reader::ParsableXmlDocument, PrintCapabilitiesDocument, PrintTicketDocument,
319 };
320
321 #[test]
322 fn serialize_for_print_ticket() {
323 let origin = include_bytes!("../../../test_data/print_ticket.xml");
324 let origin_document = PrintTicketDocument::parse_from_bytes(origin).unwrap();
325 let xml1 = origin_document.to_xml();
326 let document = PrintTicketDocument::parse_from_bytes(&xml1).unwrap();
327 let xml2 = document.to_xml();
328 assert_eq!(xml1, xml2);
329 }
330
331 #[test]
332 fn serialize_print_capabilities() {
333 let origin = include_bytes!("../../../test_data/print_capabilities.xml");
334 let origin_document = PrintCapabilitiesDocument::parse_from_bytes(origin).unwrap();
335 let xml1 = origin_document.to_xml();
336 let document = PrintCapabilitiesDocument::parse_from_bytes(&xml1).unwrap();
337 let xml2 = document.to_xml();
338 assert_eq!(xml1, xml2);
339 }
340}