use serde::Serialize;
use crate::error::RedispatchXmlError;
use crate::parse::Document;
pub fn serialize(doc: &Document) -> Result<Vec<u8>, RedispatchXmlError> {
let doc_type = doc.document_type();
let bytes = match doc {
Document::Activation(d) => serialize_as(d.as_ref(), true)?,
Document::PlannedResourceSchedule(d) => serialize_as(d.as_ref(), true)?,
Document::Acknowledgement(d) => serialize_as(d.as_ref(), true)?,
Document::Stammdaten(d) => serialize_as(d.as_ref(), true)?,
Document::StatusRequest(d) => serialize_as(d.as_ref(), true)?,
Document::Unavailability(d) => serialize_as(d.as_ref(), true)?,
Document::Kaskade(d) => serialize_as(d.as_ref(), true)?,
Document::NetworkConstraint(d) => serialize_as(d.as_ref(), true)?,
Document::Kostenblatt(d) => serialize_as(d.as_ref(), true)?,
};
Ok(inject_default_namespace(bytes, doc_type))
}
fn inject_default_namespace(bytes: Vec<u8>, doc_type: crate::documents::DocumentType) -> Vec<u8> {
let Some(ns) = doc_type.expected_namespace() else {
return bytes;
};
let Ok(text) = String::from_utf8(bytes) else {
return Vec::new(); };
let Some(root_start) = text
.find("?>")
.map(|i| i + 2)
.and_then(|from| text[from..].find('<').map(|j| from + j))
else {
return text.into_bytes();
};
if text[root_start..].contains("xmlns=")
&& text[root_start
..text[root_start..]
.find('>')
.map_or(text.len(), |k| root_start + k)]
.contains("xmlns=")
{
return text.into_bytes(); }
let Some(rel_end) = text[root_start..].find(['>', ' ']) else {
return text.into_bytes();
};
let insert_at = root_start + rel_end;
let mut out = String::with_capacity(text.len() + ns.len() + 10);
out.push_str(&text[..insert_at]);
out.push_str(&format!(" xmlns=\"{ns}\""));
out.push_str(&text[insert_at..]);
out.into_bytes()
}
pub fn serialize_as<T: Serialize>(
doc: &T,
add_xml_decl: bool,
) -> Result<Vec<u8>, RedispatchXmlError> {
let xml_str =
quick_xml::se::to_string(doc).map_err(|e| RedispatchXmlError::Serialize(e.to_string()))?;
let mut out = Vec::with_capacity(xml_str.len() + 40);
if add_xml_decl {
out.extend_from_slice(b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
}
out.extend_from_slice(xml_str.as_bytes());
Ok(out)
}