xml_data/quick_xml/
serializer.rs

1use crate::{
2	serializer::{
3		self,
4		Element,
5	},
6	Result,
7};
8use quick_xml::{
9	events::{
10		BytesDecl,
11		BytesEnd,
12		BytesStart,
13		BytesText,
14		Event,
15		attributes::Attribute,
16	},
17};
18use std::borrow::Cow;
19use std::io;
20
21fn cow_bytes<'a>(value: Cow<'a, str>) -> Cow<'a, [u8]> {
22	match value {
23		Cow::Owned(v) => Cow::Owned(v.into()),
24		Cow::Borrowed(v) => Cow::Borrowed(v.as_bytes()),
25	}
26}
27
28/// Serialize element into full document in memory
29pub fn serialize_document<E: Element>(element: &E) -> Result<String> {
30	let mut buf = Vec::new();
31	let mut writer = quick_xml::Writer::new(&mut buf);
32	let mut serializer = Serializer::new(&mut writer);
33	serializer.serialize_document(element)?;
34	// there shouldn't be any way to write binary (non-utf8) data to the buffer
35	Ok(String::from_utf8(buf).expect("buffer should be utf-8 clean"))
36}
37
38/// Serializer adaptor for `quick_xml::Writer`
39pub struct Serializer<'w, W: io::Write> {
40	writer: &'w mut quick_xml::Writer<W>,
41}
42
43impl<'w, W: io::Write> Serializer<'w, W> {
44	/// New adaptor using the writer
45	pub fn new(writer: &'w mut quick_xml::Writer<W>) -> Self {
46		Self { writer }
47	}
48
49	/// Serialize full document from root element
50	pub fn serialize_document<E: Element>(&mut self, element: &E) -> Result<()> {
51		self.writer.write_event(Event::Decl(BytesDecl::new(
52			b"1.1",
53			Some(b"utf-8"),
54			None,
55		)))?;
56		self.serialize_element(element)
57	}
58
59	/// Serialize single element
60	pub fn serialize_element<E: Element>(&mut self, element: &E) -> Result<()> {
61		let tag = cow_bytes(element.tag());
62		let mut ser = SRef {
63			serializer: self,
64			end: Some(BytesEnd::owned(tag.to_vec())),
65			start: Some(BytesStart::owned_name(tag)),
66		};
67		element.serialize(&mut ser)?;
68		ser.close()?;
69		Ok(())
70	}
71}
72
73struct SRef<'a, 'w, W: io::Write> {
74	serializer: &'a mut Serializer<'w, W>,
75	start: Option<BytesStart<'static>>,
76	end: Option<BytesEnd<'static>>,
77}
78
79impl<'a, 'w, W: io::Write> SRef<'a, 'w, W> {
80	fn start(&mut self) -> Result<()> {
81		if let Some(s) = self.start.take() {
82			self.serializer.writer.write_event(Event::Start(s))?;
83		} else {
84			assert!(self.end.is_some(), "element already closed");
85		}
86		Ok(())
87	}
88
89	fn close(&mut self) -> Result<()> {
90		if let Some(s) = self.start.take() {
91			self.serializer.writer.write_event(Event::Empty(s))?;
92			self.end = None;
93		} else if let Some(e) = self.end.take() {
94			self.serializer.writer.write_event(Event::End(e))?;
95		}
96		Ok(())
97	}
98}
99
100impl<'a, 'w, W: io::Write> serializer::Serializer for &'_ mut SRef<'a, 'w, W> {
101	fn serialize_attribute(&mut self, key: &str, value: Cow<'_, str>) -> Result<()> {
102		let start = self.start.as_mut().expect("element already started");
103		let key = key.as_bytes();
104		let value = cow_bytes(value);
105		start.push_attribute(Attribute {
106			key,
107			value,
108		});
109		Ok(())
110	}
111
112	fn serialize_text(&mut self, text: Cow<'_, str>) -> Result<()> {
113		self.start()?;
114		self.serializer.writer.write_event(Event::Text(BytesText::from_plain_str(&text)))?;
115		Ok(())
116	}
117
118	fn serialize_element<E: Element>(&mut self, element: &E) -> Result<()> {
119		self.start()?;
120		self.serializer.serialize_element(element)
121	}
122}
123
124#[cfg(test)]
125mod test {
126	use crate::test_struct::*;
127	use super::*;
128
129	#[test]
130	fn test() {
131		assert_eq!(
132			serialize_document(&Data::TEST_RESULT_1).unwrap(),
133			Data::TEST_SERIALIZE_DOCUMENT_1,
134		);
135	}
136}