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 T: IntoIterator<Item = &'ser TItem> + 'ser,
275 <T as IntoIterator>::IntoIter: Debug,
276 TItem: WithSerializer + 'ser,
277{
278 Pending {
279 name: Option<&'ser str>,
280 iter: <T as IntoIterator>::IntoIter,
281 },
282 Emitting {
283 name: Option<&'ser str>,
284 iter: <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: IntoIterator<Item = &'ser TItem> + 'ser,
293 <T as IntoIterator>::IntoIter: Debug,
294 TItem: WithSerializer + 'ser,
295{
296 type Item = Result<Event<'ser>, Error>;
297
298 fn next(&mut self) -> Option<Self::Item> {
299 loop {
300 match replace(self, Self::Done) {
301 Self::Pending { name, mut iter } => {
302 let item = iter.next()?;
303
304 match item.serializer(name, false) {
305 Ok(serializer) => {
306 *self = Self::Emitting {
307 name,
308 iter,
309 serializer,
310 }
311 }
312 Err(error) => return Some(Err(error)),
313 }
314 }
315 Self::Emitting {
316 name,
317 iter,
318 mut serializer,
319 } => {
320 if let Some(ret) = serializer.next() {
321 *self = Self::Emitting {
322 name,
323 iter,
324 serializer,
325 };
326
327 return Some(ret);
328 }
329
330 *self = Self::Pending { name, iter };
331 }
332 Self::Done => return None,
333 }
334 }
335 }
336}
337
338impl<'ser, T, TItem> IterSerializer<'ser, T, TItem>
339where
340 T: IntoIterator<Item = &'ser TItem> + 'ser,
341 <T as IntoIterator>::IntoIter: Debug,
342 TItem: WithSerializer + 'ser,
343{
344 pub fn new(value: T, name: Option<&'ser str>, is_root: bool) -> Self {
346 let _is_root = is_root;
347
348 Self::Pending {
349 name,
350 iter: value.into_iter(),
351 }
352 }
353}
354
355struct SerializeHelper<'a, T, W>
358where
359 T: WithSerializer + 'a,
360{
361 writer: &'a mut Writer<W>,
362 serializer: T::Serializer<'a>,
363}
364
365impl<'a, T, W> SerializeHelper<'a, T, W>
366where
367 T: WithSerializer,
368{
369 fn new(value: &'a T, name: Option<&'a str>, writer: &'a mut Writer<W>) -> Result<Self, Error> {
370 let serializer = value.serializer(name, true)?;
371
372 Ok(Self { writer, serializer })
373 }
374}
375
376impl<T, W> SerializeHelper<'_, T, W>
377where
378 T: WithSerializer,
379 W: Write,
380{
381 fn serialize_sync(&mut self) -> Result<(), Error> {
382 for event in self.serializer.by_ref() {
383 self.writer
384 .write_event(event?)
385 .map_err(|error| ErrorKind::XmlError(error.into()))?;
386 }
387
388 Ok(())
389 }
390}
391
392#[cfg(feature = "async")]
393impl<T, W> SerializeHelper<'_, T, W>
394where
395 T: WithSerializer,
396 W: tokio::io::AsyncWrite + Unpin,
397{
398 async fn serialize_async(&mut self) -> Result<(), Error> {
399 for event in self.serializer.by_ref() {
400 self.writer
401 .write_event_async(event?)
402 .await
403 .map_err(ErrorKind::XmlError)?;
404 }
405
406 Ok(())
407 }
408}