upnp_rs/common/xml/
write.rs

1/*!
2One-line description.
3
4More detailed description, with
5
6# Example
7
8*/
9
10use 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// ------------------------------------------------------------------------------------------------
20// Public Types
21// ------------------------------------------------------------------------------------------------
22
23#[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
44// ------------------------------------------------------------------------------------------------
45// Public Functions
46// ------------------------------------------------------------------------------------------------
47
48pub 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
118// ------------------------------------------------------------------------------------------------
119// Implementations
120// ------------------------------------------------------------------------------------------------
121
122impl 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
128// ------------------------------------------------------------------------------------------------
129
130// ------------------------------------------------------------------------------------------------
131
132impl<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// ------------------------------------------------------------------------------------------------
162// Private Types
163// ------------------------------------------------------------------------------------------------
164
165// ------------------------------------------------------------------------------------------------
166// Private Functions
167// ------------------------------------------------------------------------------------------------
168
169// ------------------------------------------------------------------------------------------------
170// Modules
171// ------------------------------------------------------------------------------------------------