1use std::borrow::Cow;
2use std::fmt::Debug;
3use std::io::Write;
4use std::mem::replace;
5
6use quick_xml::{
7 escape::escape,
8 events::{BytesEnd, BytesStart, BytesText, Event},
9 Writer,
10};
11
12use super::{Error, ErrorKind, RawByteStr};
13
14pub trait WithSerializer {
16 type Serializer<'x>: Serializer<'x>
18 where
19 Self: 'x;
20
21 fn serializer<'ser>(
27 &'ser self,
28 name: Option<&'ser str>,
29 is_root: bool,
30 ) -> Result<Self::Serializer<'ser>, Error>;
31}
32
33impl<X> WithSerializer for X
34where
35 X: SerializeBytes + Debug,
36{
37 type Serializer<'x>
38 = ContentSerializer<'x, X>
39 where
40 Self: 'x;
41
42 fn serializer<'ser>(
43 &'ser self,
44 name: Option<&'ser str>,
45 is_root: bool,
46 ) -> Result<Self::Serializer<'ser>, Error> {
47 Ok(ContentSerializer::new(self, name, is_root))
48 }
49}
50
51pub trait Serializer<'ser>: Iterator<Item = Result<Event<'ser>, Error>> + Debug {}
54
55impl<'ser, X> Serializer<'ser> for X where
56 X: Iterator<Item = Result<Event<'ser>, Error>> + Debug + Sized
57{
58}
59
60pub trait WithBoxedSerializer {
63 fn serializer<'ser>(
69 &'ser self,
70 name: Option<&'ser str>,
71 is_root: bool,
72 ) -> Result<BoxedSerializer<'ser>, Error>;
73}
74
75impl<X> WithBoxedSerializer for X
76where
77 X: WithSerializer,
78{
79 fn serializer<'ser>(
80 &'ser self,
81 name: Option<&'ser str>,
82 is_root: bool,
83 ) -> Result<BoxedSerializer<'ser>, Error> {
84 Ok(Box::new(WithSerializer::serializer(self, name, is_root)?))
85 }
86}
87
88pub type BoxedSerializer<'ser> =
90 Box<dyn Serializer<'ser, Item = Result<Event<'ser>, Error>> + 'ser>;
91
92pub trait SerializeSync: Sized {
95 type Error;
97
98 fn serialize<W: Write>(&self, root: &str, writer: &mut Writer<W>) -> Result<(), Self::Error>;
104}
105
106impl<X> SerializeSync for X
107where
108 X: WithSerializer,
109{
110 type Error = Error;
111
112 fn serialize<W: Write>(&self, root: &str, writer: &mut Writer<W>) -> Result<(), Self::Error> {
113 SerializeHelper::new(self, Some(root), writer)?.serialize_sync()
114 }
115}
116
117#[cfg(feature = "async")]
120pub trait SerializeAsync: Sized {
121 type Future<'x>: std::future::Future<Output = Result<(), Self::Error>> + 'x
123 where
124 Self: 'x;
125
126 type Error;
128
129 fn serialize_async<'a, W: tokio::io::AsyncWrite + Unpin>(
131 &'a self,
132 root: &'a str,
133 writer: &'a mut Writer<W>,
134 ) -> Self::Future<'a>;
135}
136
137#[cfg(feature = "async")]
138impl<X> SerializeAsync for X
139where
140 X: WithSerializer,
141{
142 type Future<'x>
143 = std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), Self::Error>> + 'x>>
144 where
145 X: 'x;
146
147 type Error = Error;
148
149 fn serialize_async<'a, W: tokio::io::AsyncWrite + Unpin>(
150 &'a self,
151 root: &'a str,
152 writer: &'a mut Writer<W>,
153 ) -> Self::Future<'a> {
154 Box::pin(async move {
155 SerializeHelper::new(self, Some(root), writer)?
156 .serialize_async()
157 .await
158 })
159 }
160}
161
162pub trait SerializeBytes: Sized {
167 fn serialize_bytes(&self) -> Result<Option<Cow<'_, str>>, Error>;
176}
177
178impl<X> SerializeBytes for X
179where
180 X: ToString,
181{
182 fn serialize_bytes(&self) -> Result<Option<Cow<'_, str>>, Error> {
183 Ok(Some(Cow::Owned(self.to_string())))
184 }
185}
186
187#[derive(Debug)]
190#[allow(missing_docs)]
191pub enum ContentSerializer<'ser, T> {
192 Begin {
193 name: Option<&'ser str>,
194 value: &'ser T,
195 },
196 Data {
197 name: Option<&'ser str>,
198 data: Cow<'ser, str>,
199 },
200 End {
201 name: &'ser str,
202 },
203 Done,
204}
205
206impl<'ser, T> ContentSerializer<'ser, T>
207where
208 T: SerializeBytes + Debug,
209{
210 pub fn new(value: &'ser T, name: Option<&'ser str>, is_root: bool) -> Self {
221 let _is_root = is_root;
222
223 Self::Begin { name, value }
224 }
225}
226
227impl<'ser, T> Iterator for ContentSerializer<'ser, T>
228where
229 T: SerializeBytes + Debug,
230{
231 type Item = Result<Event<'ser>, Error>;
232
233 fn next(&mut self) -> Option<Self::Item> {
234 loop {
235 match replace(self, Self::Done) {
236 Self::Begin { name, value } => match value.serialize_bytes() {
237 Ok(None) => return name.map(|name| Ok(Event::Empty(BytesStart::new(name)))),
238 Ok(Some(data)) => {
239 if data.contains("]]>") {
240 return Some(Err(ErrorKind::InvalidData(RawByteStr::from_slice(
241 data.as_bytes(),
242 ))
243 .into()));
244 }
245
246 *self = Self::Data { name, data };
247
248 if let Some(name) = name {
249 return Some(Ok(Event::Start(BytesStart::new(name))));
250 }
251 }
252 Err(error) => return Some(Err(error)),
253 },
254 Self::Data { name, data } => {
255 if let Some(name) = name {
256 *self = Self::End { name };
257 }
258
259 return Some(Ok(Event::Text(BytesText::from_escaped(escape(data)))));
260 }
261 Self::End { name } => return Some(Ok(Event::End(BytesEnd::new(name)))),
262 Self::Done => return None,
263 }
264 }
265 }
266}
267
268#[derive(Debug)]
271#[allow(missing_docs)]
272pub enum IterSerializer<'ser, T, TItem>
273where
274 &'ser T: IntoIterator<Item = &'ser TItem>,
275 <&'ser T as IntoIterator>::IntoIter: Debug,
276 TItem: WithSerializer + 'ser,
277{
278 Pending {
279 name: Option<&'ser str>,
280 iter: <&'ser T as IntoIterator>::IntoIter,
281 },
282 Emitting {
283 name: Option<&'ser str>,
284 iter: <&'ser T as IntoIterator>::IntoIter,
285 serializer: TItem::Serializer<'ser>,
286 },
287 Done,
288}
289
290impl<'ser, T, TItem> Iterator for IterSerializer<'ser, T, TItem>
291where
292 T: 'ser,
293 &'ser T: IntoIterator<Item = &'ser TItem>,
294 <&'ser T as IntoIterator>::IntoIter: Debug,
295 TItem: WithSerializer + 'ser,
296{
297 type Item = Result<Event<'ser>, Error>;
298
299 fn next(&mut self) -> Option<Self::Item> {
300 loop {
301 match replace(self, Self::Done) {
302 Self::Pending { name, mut iter } => {
303 let item = iter.next()?;
304
305 match item.serializer(name, false) {
306 Ok(serializer) => {
307 *self = Self::Emitting {
308 name,
309 iter,
310 serializer,
311 }
312 }
313 Err(error) => return Some(Err(error)),
314 }
315 }
316 Self::Emitting {
317 name,
318 iter,
319 mut serializer,
320 } => {
321 if let Some(ret) = serializer.next() {
322 *self = Self::Emitting {
323 name,
324 iter,
325 serializer,
326 };
327
328 return Some(ret);
329 }
330
331 *self = Self::Pending { name, iter };
332 }
333 Self::Done => return None,
334 }
335 }
336 }
337}
338
339impl<'ser, T, TItem> IterSerializer<'ser, T, TItem>
340where
341 T: Debug + 'ser,
342 &'ser T: IntoIterator<Item = &'ser TItem>,
343 <&'ser T as IntoIterator>::IntoIter: Debug,
344 TItem: WithSerializer + Debug + 'ser,
345{
346 pub fn new(value: &'ser T, name: Option<&'ser str>, is_root: bool) -> Self {
348 let _is_root = is_root;
349
350 Self::Pending {
351 name,
352 iter: value.into_iter(),
353 }
354 }
355}
356
357struct SerializeHelper<'a, T, W>
360where
361 T: WithSerializer + 'a,
362{
363 writer: &'a mut Writer<W>,
364 serializer: T::Serializer<'a>,
365}
366
367impl<'a, T, W> SerializeHelper<'a, T, W>
368where
369 T: WithSerializer,
370{
371 fn new(value: &'a T, name: Option<&'a str>, writer: &'a mut Writer<W>) -> Result<Self, Error> {
372 let serializer = value.serializer(name, true)?;
373
374 Ok(Self { writer, serializer })
375 }
376}
377
378impl<T, W> SerializeHelper<'_, T, W>
379where
380 T: WithSerializer,
381 W: Write,
382{
383 fn serialize_sync(&mut self) -> Result<(), Error> {
384 for event in self.serializer.by_ref() {
385 self.writer
386 .write_event(event?)
387 .map_err(|error| ErrorKind::XmlError(error.into()))?;
388 }
389
390 Ok(())
391 }
392}
393
394#[cfg(feature = "async")]
395impl<T, W> SerializeHelper<'_, T, W>
396where
397 T: WithSerializer,
398 W: tokio::io::AsyncWrite + Unpin,
399{
400 async fn serialize_async(&mut self) -> Result<(), Error> {
401 for event in self.serializer.by_ref() {
402 self.writer
403 .write_event_async(event?)
404 .await
405 .map_err(ErrorKind::XmlError)?;
406 }
407
408 Ok(())
409 }
410}