android_abx/encode/
xml.rs1use quick_xml::XmlVersion;
2use quick_xml::events::{BytesStart, Event as XmlEvent};
3use quick_xml::reader::Reader;
4
5use super::AbxWriter;
6use crate::{AbxError, Attribute, AttributeValue, Event, InternedStr, Result};
7
8fn utf8(bytes: &[u8]) -> Result<&str> {
9 std::str::from_utf8(bytes).map_err(|_| AbxError::InvalidUtf8)
10}
11
12fn xml_err(e: impl std::fmt::Display) -> AbxError {
13 AbxError::Xml(e.to_string())
14}
15
16fn start_tag_attributes(start: &BytesStart) -> Result<Vec<Attribute>> {
17 let mut attributes = Vec::new();
18 for attr in start.attributes() {
19 let attr = attr.map_err(xml_err)?;
20 let name = utf8(attr.key.as_ref())?;
21 let value = attr
22 .normalized_value(XmlVersion::Implicit1_0)
23 .map_err(xml_err)?;
24 attributes.push(Attribute {
25 name: InternedStr::from(name),
26 value: AttributeValue::String(value.into_owned()),
27 });
28 }
29 Ok(attributes)
30}
31
32pub fn xml_to_abx(xml: &str) -> Result<Vec<u8>> {
59 let mut reader = Reader::from_str(xml);
60 reader.config_mut().trim_text(false);
61
62 let mut w = AbxWriter::new(Vec::new())?;
63 w.write_event(&Event::StartDocument)?;
64
65 loop {
66 match reader.read_event().map_err(xml_err)? {
67 XmlEvent::Start(start) => {
68 let name = utf8(start.name().as_ref())?.to_string();
69 let attributes = start_tag_attributes(&start)?;
70 w.write_event(&Event::StartTag {
71 name: name.into(),
72 attributes,
73 })?;
74 }
75 XmlEvent::Empty(start) => {
76 let name: InternedStr = utf8(start.name().as_ref())?.into();
77 let attributes = start_tag_attributes(&start)?;
78 w.write_event(&Event::StartTag {
79 name: name.clone(),
80 attributes,
81 })?;
82 w.write_event(&Event::EndTag { name })?;
83 }
84 XmlEvent::End(end) => {
85 let name = utf8(end.name().as_ref())?.to_string();
86 w.write_event(&Event::EndTag { name: name.into() })?;
87 }
88 XmlEvent::Text(text) => {
89 let s = text.decode().map_err(xml_err)?;
90 w.write_event(&Event::Text(s.into_owned()))?;
91 }
92 XmlEvent::GeneralRef(bytes_ref) => {
93 let s = bytes_ref.decode().map_err(xml_err)?;
94 w.write_event(&Event::EntityReference(s.into_owned()))?;
95 }
96 XmlEvent::CData(cdata) => {
97 let s = utf8(cdata.as_ref())?.to_string();
98 w.write_event(&Event::CdataSection(s))?;
99 }
100 XmlEvent::Comment(comment) => {
101 let s = utf8(comment.as_ref())?.to_string();
102 w.write_event(&Event::Comment(s))?;
103 }
104 XmlEvent::PI(pi) => {
105 let s = utf8(pi.as_ref())?.to_string();
106 w.write_event(&Event::ProcessingInstruction(s))?;
107 }
108 XmlEvent::DocType(doctype) => {
109 let s = utf8(doctype.as_ref())?.to_string();
110 w.write_event(&Event::DocDecl(s))?;
111 }
112 XmlEvent::Decl(_) => {}
113 XmlEvent::Eof => break,
114 }
115 }
116
117 w.write_event(&Event::EndDocument)?;
118 Ok(w.into_inner())
119}