use crate::error::{PptxError, PptxResult};
use crate::opc::pack_uri::PackURI;
use crate::opc::part::Part;
#[derive(Debug, Clone)]
pub struct CustomXmlPart {
pub partname: PackURI,
pub xml_data: Vec<u8>,
}
impl CustomXmlPart {
#[must_use]
pub const fn new(partname: PackURI, xml_data: Vec<u8>) -> Self {
Self { partname, xml_data }
}
#[must_use]
pub fn from_str(partname: PackURI, xml: &str) -> Self {
Self {
partname,
xml_data: xml.as_bytes().to_vec(),
}
}
#[must_use]
pub fn data(&self) -> &[u8] {
&self.xml_data
}
pub fn data_str(&self) -> PptxResult<&str> {
std::str::from_utf8(&self.xml_data)
.map_err(|e| PptxError::InvalidXml(format!("custom XML is not valid UTF-8: {e}")))
}
#[must_use]
pub fn into_part(self) -> Part {
Part::new(self.partname, "application/xml", self.xml_data)
}
#[must_use]
pub fn from_part(part: &Part) -> Self {
Self {
partname: part.partname.clone(),
xml_data: part.blob.clone(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_custom_xml_part_new() {
let partname = PackURI::new("/customXml/item1.xml").unwrap();
let data = b"<root><item>hello</item></root>".to_vec();
let part = CustomXmlPart::new(partname.clone(), data.clone());
assert_eq!(part.partname.as_str(), "/customXml/item1.xml");
assert_eq!(part.data(), &data[..]);
}
#[test]
fn test_custom_xml_part_from_str() {
let partname = PackURI::new("/customXml/item1.xml").unwrap();
let xml = "<data><value>42</value></data>";
let part = CustomXmlPart::from_str(partname, xml);
assert_eq!(part.data_str().unwrap(), xml);
}
#[test]
fn test_custom_xml_into_part() {
let partname = PackURI::new("/customXml/item1.xml").unwrap();
let xml = "<test/>";
let custom = CustomXmlPart::from_str(partname, xml);
let opc_part = custom.into_part();
assert_eq!(opc_part.content_type, "application/xml");
assert_eq!(opc_part.partname.as_str(), "/customXml/item1.xml");
assert_eq!(String::from_utf8(opc_part.blob).unwrap(), "<test/>");
}
#[test]
fn test_custom_xml_from_part() {
let partname = PackURI::new("/customXml/item1.xml").unwrap();
let opc_part = Part::new(partname, "application/xml", b"<data/>".to_vec());
let custom = CustomXmlPart::from_part(&opc_part);
assert_eq!(custom.data_str().unwrap(), "<data/>");
}
}