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
178pub trait SerializeBytesToString: ToString {}
181
182impl<X> SerializeBytes for X
183where
184 X: SerializeBytesToString,
185{
186 fn serialize_bytes(&self) -> Result<Option<Cow<'_, str>>, Error> {
187 Ok(Some(Cow::Owned(self.to_string())))
188 }
189}
190
191impl SerializeBytesToString for bool {}
192impl SerializeBytesToString for String {}
193
194impl SerializeBytesToString for u8 {}
195impl SerializeBytesToString for u16 {}
196impl SerializeBytesToString for u32 {}
197impl SerializeBytesToString for u64 {}
198impl SerializeBytesToString for usize {}
199
200impl SerializeBytesToString for i8 {}
201impl SerializeBytesToString for i16 {}
202impl SerializeBytesToString for i32 {}
203impl SerializeBytesToString for i64 {}
204impl SerializeBytesToString for isize {}
205
206impl SerializeBytesToString for f32 {}
207impl SerializeBytesToString for f64 {}
208
209#[cfg(feature = "num")]
210impl SerializeBytesToString for num::BigInt {}
211
212#[cfg(feature = "num")]
213impl SerializeBytesToString for num::BigUint {}
214
215#[derive(Debug)]
218#[allow(missing_docs)]
219pub enum ContentSerializer<'ser, T> {
220 Begin {
221 name: Option<&'ser str>,
222 value: &'ser T,
223 },
224 Data {
225 name: Option<&'ser str>,
226 data: Cow<'ser, str>,
227 },
228 End {
229 name: &'ser str,
230 },
231 Done,
232}
233
234impl<'ser, T> ContentSerializer<'ser, T>
235where
236 T: SerializeBytes + Debug,
237{
238 pub fn new(value: &'ser T, name: Option<&'ser str>, is_root: bool) -> Self {
249 let _is_root = is_root;
250
251 Self::Begin { name, value }
252 }
253}
254
255impl<'ser, T> Iterator for ContentSerializer<'ser, T>
256where
257 T: SerializeBytes + Debug,
258{
259 type Item = Result<Event<'ser>, Error>;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 loop {
263 match replace(self, Self::Done) {
264 Self::Begin { name, value } => match value.serialize_bytes() {
265 Ok(None) => return name.map(|name| Ok(Event::Empty(BytesStart::new(name)))),
266 Ok(Some(data)) => {
267 if data.contains("]]>") {
268 return Some(Err(ErrorKind::InvalidData(RawByteStr::from_slice(
269 data.as_bytes(),
270 ))
271 .into()));
272 }
273
274 *self = Self::Data { name, data };
275
276 if let Some(name) = name {
277 return Some(Ok(Event::Start(BytesStart::new(name))));
278 }
279 }
280 Err(error) => return Some(Err(error)),
281 },
282 Self::Data { name, data } => {
283 if let Some(name) = name {
284 *self = Self::End { name };
285 }
286
287 return Some(Ok(Event::Text(BytesText::from_escaped(escape(data)))));
288 }
289 Self::End { name } => return Some(Ok(Event::End(BytesEnd::new(name)))),
290 Self::Done => return None,
291 }
292 }
293 }
294}
295
296#[derive(Debug)]
299#[allow(missing_docs)]
300pub enum IterSerializer<'ser, T, TItem>
301where
302 T: IntoIterator<Item = &'ser TItem> + 'ser,
303 <T as IntoIterator>::IntoIter: Debug,
304 TItem: WithSerializer + 'ser,
305{
306 Pending {
307 name: Option<&'ser str>,
308 iter: <T as IntoIterator>::IntoIter,
309 },
310 Emitting {
311 name: Option<&'ser str>,
312 iter: <T as IntoIterator>::IntoIter,
313 serializer: TItem::Serializer<'ser>,
314 },
315 Done,
316}
317
318impl<'ser, T, TItem> Iterator for IterSerializer<'ser, T, TItem>
319where
320 T: IntoIterator<Item = &'ser TItem> + 'ser,
321 <T as IntoIterator>::IntoIter: Debug,
322 TItem: WithSerializer + 'ser,
323{
324 type Item = Result<Event<'ser>, Error>;
325
326 fn next(&mut self) -> Option<Self::Item> {
327 loop {
328 match replace(self, Self::Done) {
329 Self::Pending { name, mut iter } => {
330 let item = iter.next()?;
331
332 match item.serializer(name, false) {
333 Ok(serializer) => {
334 *self = Self::Emitting {
335 name,
336 iter,
337 serializer,
338 }
339 }
340 Err(error) => return Some(Err(error)),
341 }
342 }
343 Self::Emitting {
344 name,
345 iter,
346 mut serializer,
347 } => {
348 if let Some(ret) = serializer.next() {
349 *self = Self::Emitting {
350 name,
351 iter,
352 serializer,
353 };
354
355 return Some(ret);
356 }
357
358 *self = Self::Pending { name, iter };
359 }
360 Self::Done => return None,
361 }
362 }
363 }
364}
365
366impl<'ser, T, TItem> IterSerializer<'ser, T, TItem>
367where
368 T: IntoIterator<Item = &'ser TItem> + 'ser,
369 <T as IntoIterator>::IntoIter: Debug,
370 TItem: WithSerializer + 'ser,
371{
372 pub fn new(value: T, name: Option<&'ser str>, is_root: bool) -> Self {
374 let _is_root = is_root;
375
376 Self::Pending {
377 name,
378 iter: value.into_iter(),
379 }
380 }
381}
382
383struct SerializeHelper<'a, T, W>
386where
387 T: WithSerializer + 'a,
388{
389 writer: &'a mut Writer<W>,
390 serializer: T::Serializer<'a>,
391}
392
393impl<'a, T, W> SerializeHelper<'a, T, W>
394where
395 T: WithSerializer,
396{
397 fn new(value: &'a T, name: Option<&'a str>, writer: &'a mut Writer<W>) -> Result<Self, Error> {
398 let serializer = value.serializer(name, true)?;
399
400 Ok(Self { writer, serializer })
401 }
402}
403
404impl<T, W> SerializeHelper<'_, T, W>
405where
406 T: WithSerializer,
407 W: Write,
408{
409 fn serialize_sync(&mut self) -> Result<(), Error> {
410 for event in self.serializer.by_ref() {
411 self.writer
412 .write_event(event?)
413 .map_err(|error| ErrorKind::XmlError(error.into()))?;
414 }
415
416 Ok(())
417 }
418}
419
420#[cfg(feature = "async")]
421impl<T, W> SerializeHelper<'_, T, W>
422where
423 T: WithSerializer,
424 W: tokio::io::AsyncWrite + Unpin,
425{
426 async fn serialize_async(&mut self) -> Result<(), Error> {
427 for event in self.serializer.by_ref() {
428 self.writer
429 .write_event_async(event?)
430 .await
431 .map_err(ErrorKind::XmlError)?;
432 }
433
434 Ok(())
435 }
436}