@@ -10,6 +10,10 @@ use crate::events::{attributes::Attribute, BytesCData, BytesStart, BytesText, Ev
10
10
mod async_tokio;
11
11
12
12
/// XML writer. Writes XML [`Event`]s to a [`std::io::Write`] or [`tokio::io::AsyncWrite`] implementor.
13
+ #[ cfg( feature = "serialize" ) ]
14
+ use { crate :: de:: DeError , serde:: Serialize } ;
15
+
16
+ /// XML writer. Writes XML [`Event`]s to a [`std::io::Write`] implementor.
13
17
///
14
18
/// # Examples
15
19
///
@@ -261,6 +265,73 @@ impl<W: Write> Writer<W> {
261
265
start_tag : BytesStart :: new ( name. as_ref ( ) ) ,
262
266
}
263
267
}
268
+
269
+ /// Write an arbitrary serializable object
270
+ ///
271
+ /// ```rust
272
+ /// # use pretty_assertions::assert_eq;
273
+ /// # use serde::Serialize;
274
+ /// # use quick_xml::se::Serializer;
275
+ /// # use quick_xml::events::{BytesStart, Event};
276
+ /// # use quick_xml::writer::Writer;
277
+ /// # use quick_xml::DeError;
278
+ /// # use std::io::Cursor;
279
+ /// # fn main() -> Result<(), DeError> {
280
+ ///
281
+ /// #[derive(Debug, PartialEq, Serialize)]
282
+ /// struct MyData {
283
+ /// question: String,
284
+ /// answer: u32,
285
+ /// }
286
+ ///
287
+ /// let data = MyData {
288
+ /// question: "The Ultimate Question of Life, the Universe, and Everything".into(),
289
+ /// answer: 42,
290
+ /// };
291
+ ///
292
+ /// let mut buffer = Vec::new();
293
+ /// let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
294
+ ///
295
+ /// let start = BytesStart::new("root");
296
+ /// let end = start.to_end();
297
+ ///
298
+ /// writer.write_event(Event::Start(start.clone()))?;
299
+ /// writer.write_serializable("my_data", &data)?;
300
+ /// writer.write_event(Event::End(end))?;
301
+ ///
302
+ /// assert_eq!(
303
+ /// std::str::from_utf8(&buffer)?,
304
+ /// r#"<root>
305
+ /// <my_data>
306
+ /// <question>The Ultimate Question of Life, the Universe, and Everything</question>
307
+ /// <answer>42</answer>
308
+ /// </my_data>
309
+ /// </root>"#
310
+ /// );
311
+ /// # Ok(())
312
+ /// # }
313
+ /// ```
314
+ #[ cfg( feature = "serialize" ) ]
315
+ pub fn write_serializable < T : Serialize > (
316
+ & mut self ,
317
+ tag_name : & str ,
318
+ content : & T ,
319
+ ) -> std:: result:: Result < ( ) , DeError > {
320
+ use crate :: se:: Serializer ;
321
+
322
+ self . write_indent ( ) ?;
323
+ let indent = self . indent . clone ( ) ;
324
+ let mut fmt = ToFmtWrite ( self . get_mut ( ) ) ;
325
+ let mut serializer = Serializer :: with_root ( & mut fmt, Some ( tag_name) ) ?;
326
+
327
+ if let Some ( indent) = indent {
328
+ serializer. set_indent ( indent) ;
329
+ }
330
+
331
+ content. serialize ( serializer) ?;
332
+
333
+ Ok ( ( ) )
334
+ }
264
335
}
265
336
266
337
/// A struct to write an element. Contains methods to add attributes and inner
@@ -341,14 +412,31 @@ impl<'a, W: Write> ElementWriter<'a, W> {
341
412
Ok ( self . writer )
342
413
}
343
414
}
415
+ #[ cfg( feature = "serialize" ) ]
416
+ struct ToFmtWrite < T > ( pub T ) ;
417
+
418
+ #[ cfg( feature = "serialize" ) ]
419
+ impl < T > std:: fmt:: Write for ToFmtWrite < T >
420
+ where
421
+ T : std:: io:: Write ,
422
+ {
423
+ fn write_str ( & mut self , s : & str ) -> std:: fmt:: Result {
424
+ self . 0 . write_all ( s. as_bytes ( ) ) . map_err ( |_| std:: fmt:: Error )
425
+ }
426
+ }
344
427
345
428
#[ derive( Clone ) ]
346
429
pub ( crate ) struct Indentation {
430
+ /// todo: does this even belong here? It has no impact on indentation logic.
347
431
should_line_break : bool ,
432
+ /// The character code to be used for indentations (e.g. ` ` or `\t`)
348
433
indent_char : u8 ,
434
+ /// How many instances of the indent character ought to be used for each level of indentation
349
435
indent_size : usize ,
436
+ /// Used as a cache for the bytes used for indentation
350
437
indents : Vec < u8 > ,
351
- indents_len : usize ,
438
+ /// The current amount of indentation
439
+ current_indent_len : usize ,
352
440
}
353
441
354
442
impl Indentation {
@@ -358,26 +446,27 @@ impl Indentation {
358
446
indent_char,
359
447
indent_size,
360
448
indents : vec ! [ indent_char; 128 ] ,
361
- indents_len : 0 ,
449
+ current_indent_len : 0 , // invariant - needs to remain less than indents.len()
362
450
}
363
451
}
364
452
365
453
/// Increase indentation by one level
366
454
pub fn grow ( & mut self ) {
367
- self . indents_len += self . indent_size ;
368
- if self . indents_len > self . indents . len ( ) {
369
- self . indents . resize ( self . indents_len , self . indent_char ) ;
455
+ self . current_indent_len += self . indent_size ;
456
+ if self . current_indent_len > self . indents . len ( ) {
457
+ self . indents
458
+ . resize ( self . current_indent_len , self . indent_char ) ;
370
459
}
371
460
}
372
461
373
462
/// Decrease indentation by one level. Do nothing, if level already zero
374
463
pub fn shrink ( & mut self ) {
375
- self . indents_len = self . indents_len . saturating_sub ( self . indent_size ) ;
464
+ self . current_indent_len = self . current_indent_len . saturating_sub ( self . indent_size ) ;
376
465
}
377
466
378
467
/// Returns indent string for current level
379
468
pub fn current ( & self ) -> & [ u8 ] {
380
- & self . indents [ ..self . indents_len ]
469
+ & self . indents [ ..self . current_indent_len ]
381
470
}
382
471
}
383
472
@@ -547,6 +636,71 @@ mod indentation {
547
636
) ;
548
637
}
549
638
639
+ #[ cfg( feature = "serialize" ) ]
640
+ #[ test]
641
+ fn serializable ( ) {
642
+ #[ derive( Serialize ) ]
643
+ struct Foo {
644
+ #[ serde( rename = "@attribute" ) ]
645
+ attribute : & ' static str ,
646
+
647
+ element : Bar ,
648
+ list : Vec < & ' static str > ,
649
+
650
+ #[ serde( rename = "$text" ) ]
651
+ text : & ' static str ,
652
+
653
+ val : String ,
654
+ }
655
+
656
+ #[ derive( Serialize ) ]
657
+ struct Bar {
658
+ baz : usize ,
659
+ bat : usize ,
660
+ }
661
+
662
+ let mut buffer = Vec :: new ( ) ;
663
+ let mut writer = Writer :: new_with_indent ( & mut buffer, b' ' , 4 ) ;
664
+
665
+ let content = Foo {
666
+ attribute : "attribute" ,
667
+ element : Bar { baz : 42 , bat : 43 } ,
668
+ list : vec ! [ "first element" , "second element" ] ,
669
+ text : "text" ,
670
+ val : "foo" . to_owned ( ) ,
671
+ } ;
672
+
673
+ let start = BytesStart :: new ( "paired" )
674
+ . with_attributes ( vec ! [ ( "attr1" , "value1" ) , ( "attr2" , "value2" ) ] . into_iter ( ) ) ;
675
+ let end = start. to_end ( ) ;
676
+
677
+ writer
678
+ . write_event ( Event :: Start ( start. clone ( ) ) )
679
+ . expect ( "write start tag failed" ) ;
680
+ writer
681
+ . write_serializable ( "foo_element" , & content)
682
+ . expect ( "write serializable inner contents failed" ) ;
683
+ writer
684
+ . write_event ( Event :: End ( end) )
685
+ . expect ( "write end tag failed" ) ;
686
+
687
+ assert_eq ! (
688
+ std:: str :: from_utf8( & buffer) . unwrap( ) ,
689
+ r#"<paired attr1="value1" attr2="value2">
690
+ <foo_element attribute="attribute">
691
+ <element>
692
+ <baz>42</baz>
693
+ <bat>43</bat>
694
+ </element>
695
+ <list>first element</list>
696
+ <list>second element</list>
697
+ text
698
+ <val>foo</val>
699
+ </foo_element>
700
+ </paired>"#
701
+ ) ;
702
+ }
703
+
550
704
#[ test]
551
705
fn element_writer_empty ( ) {
552
706
let mut buffer = Vec :: new ( ) ;
0 commit comments