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