upnp_rs/common/xml/
write.rs1use crate::error::{xml_error, Error};
11use crate::syntax::{
12 XML_ATTR_NAMESPACE, XML_DECL_VERSION, XML_ELEM_MAJOR, XML_ELEM_MINOR, XML_ELEM_SPEC_VERSION,
13};
14use crate::SpecVersion;
15use quick_xml::events::{attributes::Attribute, BytesDecl, BytesEnd, BytesStart, BytesText, Event};
16use quick_xml::Writer;
17use std::io::Write;
18
19#[derive(Debug)]
24pub struct Element {
25 name: &'static [u8],
26}
27
28pub trait Writable<T: Write> {
29 fn write(&self, writer: &mut Writer<T>) -> Result<(), Error>;
30}
31
32pub trait RootWritable<T: Write>: Writable<T> {
33 fn write_root(&self, writer: T) -> Result<T, Error> {
34 let mut xml = Writer::new(writer);
35
36 start(&mut xml).map_err(xml_error)?;
37
38 self.write(&mut xml)?;
39
40 Ok(xml.into_inner())
41 }
42}
43
44pub fn start<T: Write>(writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
49 writer
50 .write_event(Event::Decl(BytesDecl::new(XML_DECL_VERSION, None, None)))
51 .map(|_| ())
52}
53
54pub fn element<T: Write>(
55 writer: &mut Writer<T>,
56 name: &'static [u8],
57) -> Result<(), quick_xml::Error> {
58 writer.write_event(Event::Start(BytesStart::borrowed_name(name)))?;
59 writer
60 .write_event(Event::End(BytesEnd::borrowed(name)))
61 .map(|_| ())
62}
63
64pub fn start_element<T: Write>(
65 writer: &mut Writer<T>,
66 name: &'static [u8],
67) -> Result<Element, quick_xml::Error> {
68 writer.write_event(Event::Start(BytesStart::borrowed_name(name)))?;
69 Ok(Element { name })
70}
71
72pub fn start_ns_element<T: Write>(
73 writer: &mut Writer<T>,
74 name: &'static [u8],
75 namespace: &'static str,
76 prefix: Option<&str>,
77) -> Result<Element, quick_xml::Error> {
78 let xmlns = [
79 XML_ATTR_NAMESPACE,
80 if prefix.is_some() { ":" } else { "" },
81 if let Some(p) = prefix { p } else { "" },
82 ]
83 .concat();
84
85 start_element_with(writer, name, vec![(xmlns.as_str(), namespace)])?;
86 Ok(Element { name })
87}
88
89pub fn start_element_with<T: Write>(
90 writer: &mut Writer<T>,
91 name: &'static [u8],
92 attrs: Vec<(&str, &str)>,
93) -> Result<Element, quick_xml::Error> {
94 let mut element = BytesStart::borrowed_name(name);
95 for (name, value) in attrs {
96 element.push_attribute(Attribute::from((name, value)));
97 }
98 writer.write_event(Event::Start(element))?;
99 Ok(Element { name })
100}
101
102pub fn end_element<T: Write>(writer: &mut Writer<T>, name: &[u8]) -> Result<(), quick_xml::Error> {
103 writer
104 .write_event(Event::End(BytesEnd::borrowed(name)))
105 .map(|_| ())
106}
107
108pub fn text_element<T: Write>(
109 writer: &mut Writer<T>,
110 name: &'static [u8],
111 content: &[u8],
112) -> Result<(), quick_xml::Error> {
113 let element = start_element(writer, name)?;
114 writer.write_event(Event::Text(BytesText::from_plain(content)))?;
115 element.end(writer)
116}
117
118impl Element {
123 pub fn end<T: Write>(&self, writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
124 end_element(writer, self.name)
125 }
126}
127
128impl<T: Write> Writable<T> for SpecVersion {
133 fn write(&self, writer: &mut Writer<T>) -> Result<(), Error> {
134 let spec_version = start_element(writer, XML_ELEM_SPEC_VERSION).map_err(xml_error)?;
135 text_element(
136 writer,
137 XML_ELEM_MAJOR,
138 match self {
139 SpecVersion::V10 => "1",
140 SpecVersion::V11 => "1",
141 SpecVersion::V20 => "2",
142 }
143 .as_bytes(),
144 )
145 .map_err(xml_error)?;
146 text_element(
147 writer,
148 XML_ELEM_MINOR,
149 match self {
150 SpecVersion::V10 => "0",
151 SpecVersion::V11 => "1",
152 SpecVersion::V20 => "0",
153 }
154 .as_bytes(),
155 )
156 .map_err(xml_error)?;
157 spec_version.end(writer).map_err(xml_error)
158 }
159}
160
161