redispatch_xml/
serialize.rs1use serde::Serialize;
4
5use crate::error::RedispatchXmlError;
6use crate::parse::Document;
7
8pub fn serialize(doc: &Document) -> Result<Vec<u8>, RedispatchXmlError> {
19 let doc_type = doc.document_type();
20 let bytes = match doc {
21 Document::Activation(d) => serialize_as(d.as_ref(), true)?,
22 Document::PlannedResourceSchedule(d) => serialize_as(d.as_ref(), true)?,
23 Document::Acknowledgement(d) => serialize_as(d.as_ref(), true)?,
24 Document::Stammdaten(d) => serialize_as(d.as_ref(), true)?,
25 Document::StatusRequest(d) => serialize_as(d.as_ref(), true)?,
26 Document::Unavailability(d) => serialize_as(d.as_ref(), true)?,
27 Document::Kaskade(d) => serialize_as(d.as_ref(), true)?,
28 Document::NetworkConstraint(d) => serialize_as(d.as_ref(), true)?,
29 Document::Kostenblatt(d) => serialize_as(d.as_ref(), true)?,
30 };
31 Ok(inject_default_namespace(bytes, doc_type))
32}
33
34fn inject_default_namespace(bytes: Vec<u8>, doc_type: crate::documents::DocumentType) -> Vec<u8> {
44 let Some(ns) = doc_type.expected_namespace() else {
45 return bytes;
46 };
47 let Ok(text) = String::from_utf8(bytes) else {
48 return Vec::new(); };
50 let Some(root_start) = text
52 .find("?>")
53 .map(|i| i + 2)
54 .and_then(|from| text[from..].find('<').map(|j| from + j))
55 else {
56 return text.into_bytes();
57 };
58 if text[root_start..].contains("xmlns=")
59 && text[root_start
60 ..text[root_start..]
61 .find('>')
62 .map_or(text.len(), |k| root_start + k)]
63 .contains("xmlns=")
64 {
65 return text.into_bytes(); }
67 let Some(rel_end) = text[root_start..].find(['>', ' ']) else {
68 return text.into_bytes();
69 };
70 let insert_at = root_start + rel_end;
71 let mut out = String::with_capacity(text.len() + ns.len() + 10);
72 out.push_str(&text[..insert_at]);
73 out.push_str(&format!(" xmlns=\"{ns}\""));
74 out.push_str(&text[insert_at..]);
75 out.into_bytes()
76}
77
78pub fn serialize_as<T: Serialize>(
84 doc: &T,
85 add_xml_decl: bool,
86) -> Result<Vec<u8>, RedispatchXmlError> {
87 let xml_str =
88 quick_xml::se::to_string(doc).map_err(|e| RedispatchXmlError::Serialize(e.to_string()))?;
89 let mut out = Vec::with_capacity(xml_str.len() + 40);
90 if add_xml_decl {
91 out.extend_from_slice(b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
92 }
93 out.extend_from_slice(xml_str.as_bytes());
94 Ok(out)
95}