1use crate::error::{Error, Result};
34use crate::escape::escape;
35use serde::ser::{self, Serialize};
36use std::io::Write;
37use std::sync::Arc;
38
39pub fn to_string<T>(value: &T) -> Result<String>
72where
73 T: Serialize + ?Sized,
74{
75 let mut serializer = Serializer::new();
76 value.serialize(&mut serializer)?;
77 Ok(serializer.into_string())
78}
79
80pub fn to_string_with_root<T>(value: &T, root: &str) -> Result<String>
82where
83 T: Serialize + ?Sized,
84{
85 let mut serializer = Serializer::with_root(root);
86 value.serialize(&mut serializer)?;
87 Ok(serializer.into_string())
88}
89
90pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
92where
93 T: Serialize + ?Sized,
94{
95 Ok(to_string(value)?.into_bytes())
96}
97
98pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
100where
101 W: Write,
102 T: Serialize + ?Sized,
103{
104 let xml = to_string(value)?;
105 let mut writer = writer;
106 writer.write_all(xml.as_bytes())?;
107 Ok(())
108}
109
110#[derive(Clone)]
115enum TagName {
116 Static(&'static str),
117 Shared(Arc<str>),
118}
119
120impl TagName {
121 fn as_str(&self) -> &str {
122 match self {
123 TagName::Static(s) => s,
124 TagName::Shared(s) => s,
125 }
126 }
127}
128
129impl From<&'static str> for TagName {
130 fn from(s: &'static str) -> Self {
131 TagName::Static(s)
132 }
133}
134
135pub struct Serializer {
137 output: String,
138 root: Option<Arc<str>>,
140 current_element: Option<&'static str>,
142 element_stack: Vec<TagName>,
144 is_key: bool,
146 current_key: Option<TagName>,
149 include_declaration: bool,
151 indent_level: usize,
153 indent_str: Option<String>,
155}
156
157impl Serializer {
158 pub fn new() -> Self {
160 Self {
161 output: String::new(),
162 root: None,
163 current_element: None,
164 element_stack: Vec::new(),
165 is_key: false,
166 current_key: None,
167 include_declaration: false,
168 indent_level: 0,
169 indent_str: None,
170 }
171 }
172
173 pub fn with_root(root: &str) -> Self {
175 Self {
176 root: Some(Arc::from(root)),
177 ..Self::new()
178 }
179 }
180
181 pub fn with_indent(mut self, indent: &str) -> Self {
183 self.indent_str = Some(indent.to_string());
184 self
185 }
186
187 pub fn with_declaration(mut self) -> Self {
189 self.include_declaration = true;
190 self
191 }
192
193 pub fn into_string(self) -> String {
199 if self.include_declaration {
200 let mut result = String::with_capacity(self.output.len() + 40);
201 result.push_str("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
202 result.push_str(&self.output);
203 result
204 } else {
205 self.output
206 }
207 }
208
209 fn write_start_tag(&mut self, name: impl Into<TagName>) {
211 let name = name.into();
212 self.write_indent();
213 self.output.push('<');
214 self.output.push_str(name.as_str());
215 self.output.push('>');
216 self.element_stack.push(name);
217 self.indent_level += 1;
218 }
219
220 fn write_start_tag_with_attrs(&mut self, name: impl Into<TagName>, attrs: &[(String, String)]) {
222 let name = name.into();
223 self.write_indent();
224 self.output.push('<');
225 self.output.push_str(name.as_str());
226 for (attr_name, attr_value) in attrs {
227 self.output.push(' ');
228 self.output.push_str(attr_name);
229 self.output.push_str("=\"");
230 self.output.push_str(&escape(attr_value));
231 self.output.push('"');
232 }
233 self.output.push('>');
234 self.element_stack.push(name);
235 self.indent_level += 1;
236 }
237
238 fn undo_start_tag(&mut self, rollback_to: usize) {
243 self.output.truncate(rollback_to);
244 self.element_stack.pop();
245 self.indent_level = self.indent_level.saturating_sub(1);
246 }
247
248 fn write_end_tag(&mut self) {
250 self.indent_level = self.indent_level.saturating_sub(1);
251
252 if let Some(name) = self.element_stack.pop() {
253 self.write_indent();
254 self.output.push_str("</");
255 self.output.push_str(name.as_str());
256 self.output.push('>');
257 }
258 }
259
260 fn write_empty_element(&mut self, name: &str) {
262 self.write_indent();
263 self.output.push('<');
264 self.output.push_str(name);
265 self.output.push_str("/>");
266 }
267
268 fn write_empty_element_with_attrs(&mut self, name: &str, attrs: &[(String, String)]) {
270 self.write_indent();
271 self.output.push('<');
272 self.output.push_str(name);
273 for (attr_name, attr_value) in attrs {
274 self.output.push(' ');
275 self.output.push_str(attr_name);
276 self.output.push_str("=\"");
277 self.output.push_str(&escape(attr_value));
278 self.output.push('"');
279 }
280 self.output.push_str("/>");
281 }
282
283 fn write_element(&mut self, name: &str, content: &str) {
285 self.write_indent();
286 self.output.push('<');
287 self.output.push_str(name);
288 self.output.push('>');
289 self.output.push_str(&escape(content));
290 self.output.push_str("</");
291 self.output.push_str(name);
292 self.output.push('>');
293 }
294
295 fn write_text(&mut self, content: &str) {
297 self.output.push_str(&escape(content));
298 }
299
300 fn write_indent(&mut self) {
302 if let Some(ref indent) = self.indent_str {
303 if !self.output.is_empty() && !self.output.ends_with('\n') {
304 self.output.push('\n');
305 }
306 for _ in 0..self.indent_level {
307 self.output.push_str(indent);
308 }
309 }
310 }
311
312 fn take_element_name(&mut self, fallback: &'static str) -> TagName {
315 self.current_key
316 .take()
317 .or_else(|| self.current_element.map(TagName::Static))
318 .or_else(|| self.root.clone().map(TagName::Shared))
319 .unwrap_or(TagName::Static(fallback))
320 }
321
322 fn emit_scalar(&mut self, text: &str) {
326 if self.is_key {
327 self.current_key = Some(TagName::Shared(Arc::from(text)));
328 self.is_key = false;
329 } else if let Some(key) = self.current_key.take() {
330 self.write_element(key.as_str(), text);
331 } else {
332 self.write_text(text);
333 }
334 }
335
336 fn open_field_wrapper(&mut self) -> bool {
343 match self.current_key.take() {
344 Some(key) => {
345 self.write_start_tag(key);
346 true
347 }
348 None => false,
349 }
350 }
351}
352
353impl Default for Serializer {
354 fn default() -> Self {
355 Self::new()
356 }
357}
358
359impl<'a> ser::Serializer for &'a mut Serializer {
360 type Ok = ();
361 type Error = Error;
362
363 type SerializeSeq = SeqSerializer<'a>;
364 type SerializeTuple = SeqSerializer<'a>;
365 type SerializeTupleStruct = SeqSerializer<'a>;
366 type SerializeTupleVariant = SeqSerializer<'a>;
367 type SerializeMap = MapSerializer<'a>;
368 type SerializeStruct = StructSerializer<'a>;
369 type SerializeStructVariant = StructSerializer<'a>;
370
371 fn serialize_bool(self, v: bool) -> Result<()> {
372 self.emit_scalar(if v { "true" } else { "false" });
373 Ok(())
374 }
375
376 fn serialize_i8(self, v: i8) -> Result<()> {
377 self.serialize_i64(v as i64)
378 }
379
380 fn serialize_i16(self, v: i16) -> Result<()> {
381 self.serialize_i64(v as i64)
382 }
383
384 fn serialize_i32(self, v: i32) -> Result<()> {
385 self.serialize_i64(v as i64)
386 }
387
388 fn serialize_i64(self, v: i64) -> Result<()> {
389 let mut buffer = itoa::Buffer::new();
390 self.emit_scalar(buffer.format(v));
391 Ok(())
392 }
393
394 fn serialize_u8(self, v: u8) -> Result<()> {
395 self.serialize_u64(v as u64)
396 }
397
398 fn serialize_u16(self, v: u16) -> Result<()> {
399 self.serialize_u64(v as u64)
400 }
401
402 fn serialize_u32(self, v: u32) -> Result<()> {
403 self.serialize_u64(v as u64)
404 }
405
406 fn serialize_u64(self, v: u64) -> Result<()> {
407 let mut buffer = itoa::Buffer::new();
408 self.emit_scalar(buffer.format(v));
409 Ok(())
410 }
411
412 fn serialize_f32(self, v: f32) -> Result<()> {
413 self.serialize_f64(v as f64)
414 }
415
416 fn serialize_f64(self, v: f64) -> Result<()> {
417 let mut buffer = ryu::Buffer::new();
418 self.emit_scalar(buffer.format(v));
419 Ok(())
420 }
421
422 fn serialize_char(self, v: char) -> Result<()> {
423 let mut buf = [0u8; 4];
424 self.emit_scalar(v.encode_utf8(&mut buf));
425 Ok(())
426 }
427
428 fn serialize_str(self, v: &str) -> Result<()> {
429 self.emit_scalar(v);
430 Ok(())
431 }
432
433 fn serialize_bytes(self, v: &[u8]) -> Result<()> {
434 const HEX: &[u8; 16] = b"0123456789abcdef";
436 let mut encoded = String::with_capacity(v.len() * 2);
437 for &byte in v {
438 encoded.push(HEX[(byte >> 4) as usize] as char);
439 encoded.push(HEX[(byte & 0x0f) as usize] as char);
440 }
441 self.emit_scalar(&encoded);
442 Ok(())
443 }
444
445 fn serialize_none(self) -> Result<()> {
446 self.current_key = None;
448 Ok(())
449 }
450
451 fn serialize_some<T>(self, value: &T) -> Result<()>
452 where
453 T: Serialize + ?Sized,
454 {
455 value.serialize(self)
456 }
457
458 fn serialize_unit(self) -> Result<()> {
459 if let Some(key) = self.current_key.take() {
460 self.write_empty_element(key.as_str());
461 }
462 Ok(())
463 }
464
465 fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
466 let elem_name = self.take_element_name(name);
467 self.write_empty_element(elem_name.as_str());
468 Ok(())
469 }
470
471 fn serialize_unit_variant(
472 self,
473 _name: &'static str,
474 _variant_index: u32,
475 variant: &'static str,
476 ) -> Result<()> {
477 if let Some(key) = self.current_key.take() {
478 self.write_element(key.as_str(), variant);
479 } else {
480 self.write_empty_element(variant);
481 }
482 Ok(())
483 }
484
485 fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
486 where
487 T: Serialize + ?Sized,
488 {
489 self.current_element = Some(name);
490 value.serialize(self)
491 }
492
493 fn serialize_newtype_variant<T>(
494 self,
495 _name: &'static str,
496 _variant_index: u32,
497 variant: &'static str,
498 value: &T,
499 ) -> Result<()>
500 where
501 T: Serialize + ?Sized,
502 {
503 let wrapped = self.open_field_wrapper();
504 self.write_start_tag(variant);
505 value.serialize(&mut *self)?;
506 self.write_end_tag();
507 if wrapped {
508 self.write_end_tag();
509 }
510 Ok(())
511 }
512
513 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
514 let element_name = self.current_key.take().unwrap_or(TagName::Static("item"));
515 Ok(SeqSerializer {
516 ser: self,
517 element_name,
518 wrapped: false,
519 })
520 }
521
522 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
523 self.serialize_seq(Some(len))
524 }
525
526 fn serialize_tuple_struct(
527 self,
528 name: &'static str,
529 _len: usize,
530 ) -> Result<Self::SerializeTupleStruct> {
531 self.write_start_tag(name);
532 Ok(SeqSerializer {
533 ser: self,
534 element_name: TagName::Static("item"),
535 wrapped: false,
536 })
537 }
538
539 fn serialize_tuple_variant(
540 self,
541 _name: &'static str,
542 _variant_index: u32,
543 variant: &'static str,
544 _len: usize,
545 ) -> Result<Self::SerializeTupleVariant> {
546 let wrapped = self.open_field_wrapper();
547 self.write_start_tag(variant);
548 Ok(SeqSerializer {
549 ser: self,
550 element_name: TagName::Static("item"),
551 wrapped,
552 })
553 }
554
555 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
556 let name = self.current_key.take()
557 .or_else(|| self.root.clone().map(TagName::Shared))
558 .unwrap_or(TagName::Static("map"));
559 self.write_start_tag(name);
560 Ok(MapSerializer { ser: self })
561 }
562
563 fn serialize_struct(self, name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
564 let elem_name = match self.current_key.take() {
565 Some(key) => key,
566 None if self.output.is_empty() && self.element_stack.is_empty() => self
568 .root
569 .clone()
570 .map(TagName::Shared)
571 .unwrap_or(TagName::Static(name)),
572 None => TagName::Static(name),
573 };
574 Ok(StructSerializer {
577 ser: self,
578 elem_name: Some(elem_name),
579 attrs: Vec::new(),
580 attr_insert_pos: None,
581 text_content: None,
582 wrapped: false,
583 })
584 }
585
586 fn serialize_struct_variant(
587 self,
588 _name: &'static str,
589 _variant_index: u32,
590 variant: &'static str,
591 _len: usize,
592 ) -> Result<Self::SerializeStructVariant> {
593 let wrapped = self.open_field_wrapper();
594 Ok(StructSerializer {
595 ser: self,
596 elem_name: Some(TagName::Static(variant)),
597 attrs: Vec::new(),
598 attr_insert_pos: None,
599 text_content: None,
600 wrapped,
601 })
602 }
603}
604
605struct AttrValueSerializer {
607 output: String,
608}
609
610impl AttrValueSerializer {
611 fn new() -> Self {
612 Self { output: String::new() }
613 }
614
615 fn into_string(self) -> String {
616 self.output
617 }
618}
619
620impl ser::Serializer for &mut AttrValueSerializer {
621 type Ok = ();
622 type Error = Error;
623
624 type SerializeSeq = ser::Impossible<(), Error>;
625 type SerializeTuple = ser::Impossible<(), Error>;
626 type SerializeTupleStruct = ser::Impossible<(), Error>;
627 type SerializeTupleVariant = ser::Impossible<(), Error>;
628 type SerializeMap = ser::Impossible<(), Error>;
629 type SerializeStruct = ser::Impossible<(), Error>;
630 type SerializeStructVariant = ser::Impossible<(), Error>;
631
632 fn serialize_bool(self, v: bool) -> Result<()> {
633 self.output.push_str(if v { "true" } else { "false" });
634 Ok(())
635 }
636
637 fn serialize_i8(self, v: i8) -> Result<()> { self.serialize_i64(v as i64) }
638 fn serialize_i16(self, v: i16) -> Result<()> { self.serialize_i64(v as i64) }
639 fn serialize_i32(self, v: i32) -> Result<()> { self.serialize_i64(v as i64) }
640 fn serialize_i64(self, v: i64) -> Result<()> {
641 let mut buffer = itoa::Buffer::new();
642 self.output.push_str(buffer.format(v));
643 Ok(())
644 }
645
646 fn serialize_u8(self, v: u8) -> Result<()> { self.serialize_u64(v as u64) }
647 fn serialize_u16(self, v: u16) -> Result<()> { self.serialize_u64(v as u64) }
648 fn serialize_u32(self, v: u32) -> Result<()> { self.serialize_u64(v as u64) }
649 fn serialize_u64(self, v: u64) -> Result<()> {
650 let mut buffer = itoa::Buffer::new();
651 self.output.push_str(buffer.format(v));
652 Ok(())
653 }
654
655 fn serialize_f32(self, v: f32) -> Result<()> { self.serialize_f64(v as f64) }
656 fn serialize_f64(self, v: f64) -> Result<()> {
657 let mut buffer = ryu::Buffer::new();
658 self.output.push_str(buffer.format(v));
659 Ok(())
660 }
661
662 fn serialize_char(self, v: char) -> Result<()> {
663 self.output.push(v);
664 Ok(())
665 }
666
667 fn serialize_str(self, v: &str) -> Result<()> {
668 self.output.push_str(v);
670 Ok(())
671 }
672
673 fn serialize_bytes(self, _v: &[u8]) -> Result<()> {
674 Err(Error::unsupported("bytes in attribute"))
675 }
676
677 fn serialize_none(self) -> Result<()> { Ok(()) }
678 fn serialize_some<T: ?Sized + Serialize>(self, v: &T) -> Result<()> { v.serialize(self) }
679 fn serialize_unit(self) -> Result<()> { Ok(()) }
680 fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { Ok(()) }
681 fn serialize_unit_variant(self, _name: &'static str, _idx: u32, variant: &'static str) -> Result<()> {
682 self.output.push_str(variant);
683 Ok(())
684 }
685 fn serialize_newtype_struct<T: ?Sized + Serialize>(self, _name: &'static str, v: &T) -> Result<()> {
686 v.serialize(self)
687 }
688 fn serialize_newtype_variant<T: ?Sized + Serialize>(self, _name: &'static str, _idx: u32, _variant: &'static str, v: &T) -> Result<()> {
689 v.serialize(self)
690 }
691
692 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
693 Err(Error::unsupported("sequence in attribute"))
694 }
695 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
696 Err(Error::unsupported("tuple in attribute"))
697 }
698 fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct> {
699 Err(Error::unsupported("tuple struct in attribute"))
700 }
701 fn serialize_tuple_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeTupleVariant> {
702 Err(Error::unsupported("tuple variant in attribute"))
703 }
704 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
705 Err(Error::unsupported("map in attribute"))
706 }
707 fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
708 Err(Error::unsupported("struct in attribute"))
709 }
710 fn serialize_struct_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeStructVariant> {
711 Err(Error::unsupported("struct variant in attribute"))
712 }
713}
714
715pub struct SeqSerializer<'a> {
717 ser: &'a mut Serializer,
718 element_name: TagName,
719 wrapped: bool,
722}
723
724impl<'a> ser::SerializeSeq for SeqSerializer<'a> {
725 type Ok = ();
726 type Error = Error;
727
728 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
729 where
730 T: Serialize + ?Sized,
731 {
732 self.ser.current_key = Some(self.element_name.clone());
733 value.serialize(&mut *self.ser)
734 }
735
736 fn end(self) -> Result<()> {
737 Ok(())
738 }
739}
740
741impl<'a> ser::SerializeTuple for SeqSerializer<'a> {
742 type Ok = ();
743 type Error = Error;
744
745 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
746 where
747 T: Serialize + ?Sized,
748 {
749 ser::SerializeSeq::serialize_element(self, value)
750 }
751
752 fn end(self) -> Result<()> {
753 ser::SerializeSeq::end(self)
754 }
755}
756
757impl<'a> ser::SerializeTupleStruct for SeqSerializer<'a> {
758 type Ok = ();
759 type Error = Error;
760
761 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
762 where
763 T: Serialize + ?Sized,
764 {
765 self.ser.current_key = Some(self.element_name.clone());
766 value.serialize(&mut *self.ser)
767 }
768
769 fn end(self) -> Result<()> {
770 self.ser.write_end_tag();
771 Ok(())
772 }
773}
774
775impl<'a> ser::SerializeTupleVariant for SeqSerializer<'a> {
776 type Ok = ();
777 type Error = Error;
778
779 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
780 where
781 T: Serialize + ?Sized,
782 {
783 self.ser.current_key = Some(self.element_name.clone());
784 value.serialize(&mut *self.ser)
785 }
786
787 fn end(self) -> Result<()> {
788 self.ser.write_end_tag();
789 if self.wrapped {
790 self.ser.write_end_tag();
791 }
792 Ok(())
793 }
794}
795
796pub struct MapSerializer<'a> {
798 ser: &'a mut Serializer,
799}
800
801impl<'a> ser::SerializeMap for MapSerializer<'a> {
802 type Ok = ();
803 type Error = Error;
804
805 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
806 where
807 T: Serialize + ?Sized,
808 {
809 self.ser.is_key = true;
810 key.serialize(&mut *self.ser)
811 }
812
813 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
814 where
815 T: Serialize + ?Sized,
816 {
817 value.serialize(&mut *self.ser)
818 }
819
820 fn end(self) -> Result<()> {
821 self.ser.write_end_tag();
822 Ok(())
823 }
824}
825
826pub struct StructSerializer<'a> {
833 ser: &'a mut Serializer,
834 elem_name: Option<TagName>,
836 attrs: Vec<(String, String)>,
838 attr_insert_pos: Option<usize>,
842 text_content: Option<String>,
843 wrapped: bool,
846}
847
848impl<'a> ser::SerializeStruct for StructSerializer<'a> {
849 type Ok = ();
850 type Error = Error;
851
852 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
853 where
854 T: Serialize + ?Sized,
855 {
856 if let Some(attr_name) = key.strip_prefix('@') {
858 let mut attr_ser = AttrValueSerializer::new();
860 value.serialize(&mut attr_ser)?;
861 let attr_value = attr_ser.into_string();
862 if let Some(pos) = self.attr_insert_pos {
863 let mut rendered = String::with_capacity(attr_name.len() + attr_value.len() + 4);
866 rendered.push(' ');
867 rendered.push_str(attr_name);
868 rendered.push_str("=\"");
869 rendered.push_str(&escape(&attr_value));
870 rendered.push('"');
871 self.ser.output.insert_str(pos, &rendered);
872 self.attr_insert_pos = Some(pos + rendered.len());
873 } else {
874 self.attrs.push((attr_name.to_string(), attr_value));
875 }
876 return Ok(());
877 }
878
879 if key == "$value" || key == "$text" {
881 let mut buf = self.text_content.take().unwrap_or_default();
884 buf.clear();
885 let mut text_ser = Serializer {
886 output: buf,
887 ..Serializer::new()
888 };
889 value.serialize(&mut text_ser)?;
890 self.text_content = Some(text_ser.output);
891 return Ok(());
892 }
893
894 if let Some(name) = self.elem_name.take() {
896 let rollback_to = self.ser.output.len();
899 self.ser.write_start_tag_with_attrs(name.clone(), &self.attrs);
900 let content_start = self.ser.output.len();
901 self.ser.current_key = Some(TagName::Static(key));
902 value.serialize(&mut *self.ser)?;
903 if self.ser.output.len() == content_start {
904 self.ser.undo_start_tag(rollback_to);
908 self.ser.current_key = None;
909 self.elem_name = Some(name);
910 } else {
911 self.attr_insert_pos = Some(content_start - 1);
913 }
914 } else {
915 self.ser.current_key = Some(TagName::Static(key));
916 value.serialize(&mut *self.ser)?;
917 }
918 Ok(())
919 }
920
921 fn end(self) -> Result<()> {
922 match self.elem_name {
923 Some(name) => {
924 if let Some(text) = self.text_content {
926 self.ser.write_start_tag_with_attrs(name, &self.attrs);
927 self.ser.output.push_str(&text);
928 self.ser.write_end_tag();
929 } else if self.attrs.is_empty() {
930 self.ser.write_empty_element(name.as_str());
932 } else {
933 self.ser.write_empty_element_with_attrs(name.as_str(), &self.attrs);
935 }
936 }
937 None => {
938 if let Some(text) = self.text_content {
941 self.ser.output.push_str(&text);
942 }
943 self.ser.write_end_tag();
944 }
945 }
946 if self.wrapped {
947 self.ser.write_end_tag();
948 }
949 Ok(())
950 }
951}
952
953impl<'a> ser::SerializeStructVariant for StructSerializer<'a> {
954 type Ok = ();
955 type Error = Error;
956
957 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
958 where
959 T: Serialize + ?Sized,
960 {
961 ser::SerializeStruct::serialize_field(self, key, value)
962 }
963
964 fn end(self) -> Result<()> {
965 ser::SerializeStruct::end(self)
966 }
967}
968
969#[cfg(test)]
970mod tests {
971 use super::*;
972 use serde::Serialize;
973
974 #[test]
975 fn test_serialize_simple_struct() {
976 #[derive(Serialize)]
977 struct Person {
978 name: String,
979 age: u32,
980 }
981
982 let person = Person {
983 name: "Alice".to_string(),
984 age: 30,
985 };
986
987 let xml = to_string(&person).unwrap();
988 assert!(xml.contains("<Person>"));
989 assert!(xml.contains("<name>Alice</name>"));
990 assert!(xml.contains("<age>30</age>"));
991 assert!(xml.contains("</Person>"));
992 }
993
994 #[test]
995 fn test_serialize_with_attributes() {
996 #[derive(Serialize)]
997 struct Element {
998 #[serde(rename = "@id")]
999 id: String,
1000 #[serde(rename = "@class")]
1001 class: String,
1002 content: String,
1003 }
1004
1005 let elem = Element {
1006 id: "main".to_string(),
1007 class: "container".to_string(),
1008 content: "Hello".to_string(),
1009 };
1010
1011 let xml = to_string(&elem).unwrap();
1012 assert!(xml.contains(r#"id="main""#));
1013 assert!(xml.contains(r#"class="container""#));
1014 assert!(xml.contains("<content>Hello</content>"));
1015 }
1016
1017 #[test]
1018 fn test_serialize_attributes_only() {
1019 #[derive(Serialize)]
1020 struct EmptyElement {
1021 #[serde(rename = "@id")]
1022 id: String,
1023 #[serde(rename = "@disabled")]
1024 disabled: bool,
1025 }
1026
1027 let elem = EmptyElement {
1028 id: "btn".to_string(),
1029 disabled: true,
1030 };
1031
1032 let xml = to_string(&elem).unwrap();
1033 assert!(xml.contains(r#"id="btn""#));
1034 assert!(xml.contains(r#"disabled="true""#));
1035 assert!(xml.contains("/>") || xml.contains("</EmptyElement>"));
1036 }
1037
1038 #[test]
1039 fn test_serialize_text_content() {
1040 #[derive(Serialize)]
1041 struct TextElement {
1042 #[serde(rename = "@id")]
1043 id: String,
1044 #[serde(rename = "$value")]
1045 text: String,
1046 }
1047
1048 let elem = TextElement {
1049 id: "para".to_string(),
1050 text: "Hello World".to_string(),
1051 };
1052
1053 let xml = to_string(&elem).unwrap();
1054 assert!(xml.contains(r#"id="para""#));
1055 assert!(xml.contains("Hello World"));
1056 }
1057
1058 #[test]
1059 fn test_serialize_nested_struct() {
1060 #[derive(Serialize)]
1061 struct Address {
1062 city: String,
1063 country: String,
1064 }
1065
1066 #[derive(Serialize)]
1067 struct Person {
1068 name: String,
1069 address: Address,
1070 }
1071
1072 let person = Person {
1073 name: "Bob".to_string(),
1074 address: Address {
1075 city: "New York".to_string(),
1076 country: "USA".to_string(),
1077 },
1078 };
1079
1080 let xml = to_string(&person).unwrap();
1081 assert!(xml.contains("<address>"));
1082 assert!(xml.contains("<city>New York</city>"));
1083 assert!(xml.contains("</address>"));
1084 }
1085
1086 #[test]
1087 fn test_serialize_optional() {
1088 #[derive(Serialize)]
1089 struct Config {
1090 name: String,
1091 value: Option<String>,
1092 }
1093
1094 let with_value = Config {
1095 name: "test".to_string(),
1096 value: Some("val".to_string()),
1097 };
1098 let xml = to_string(&with_value).unwrap();
1099 assert!(xml.contains("<value>val</value>"));
1100
1101 let without_value = Config {
1102 name: "test".to_string(),
1103 value: None,
1104 };
1105 let xml = to_string(&without_value).unwrap();
1106 assert!(!xml.contains("<value>"));
1107 }
1108
1109 #[test]
1110 fn test_serialize_vector() {
1111 #[derive(Serialize)]
1112 struct Items {
1113 items: Vec<String>,
1114 }
1115
1116 let items = Items {
1117 items: vec!["one".to_string(), "two".to_string(), "three".to_string()],
1118 };
1119
1120 let xml = to_string(&items).unwrap();
1121 assert!(xml.contains("<items>one</items>"));
1122 assert!(xml.contains("<items>two</items>"));
1123 assert!(xml.contains("<items>three</items>"));
1124 }
1125
1126 #[test]
1127 fn test_serialize_escaped_content() {
1128 #[derive(Serialize)]
1129 struct Data {
1130 content: String,
1131 }
1132
1133 let data = Data {
1134 content: "<hello> & \"world\"".to_string(),
1135 };
1136
1137 let xml = to_string(&data).unwrap();
1138 assert!(xml.contains("<hello>"));
1139 assert!(xml.contains("&"));
1140 assert!(xml.contains("""));
1141 }
1142
1143 #[test]
1144 fn test_serialize_escaped_attribute() {
1145 #[derive(Serialize)]
1146 struct Element {
1147 #[serde(rename = "@title")]
1148 title: String,
1149 }
1150
1151 let elem = Element {
1152 title: "Hello \"World\" & <Friends>".to_string(),
1153 };
1154
1155 let xml = to_string(&elem).unwrap();
1156 assert!(xml.contains("""));
1157 assert!(xml.contains("&"));
1158 assert!(xml.contains("<"));
1159 }
1160
1161 #[test]
1162 fn test_serialize_bool() {
1163 #[derive(Serialize)]
1164 struct Flags {
1165 enabled: bool,
1166 active: bool,
1167 }
1168
1169 let flags = Flags {
1170 enabled: true,
1171 active: false,
1172 };
1173
1174 let xml = to_string(&flags).unwrap();
1175 assert!(xml.contains("<enabled>true</enabled>"));
1176 assert!(xml.contains("<active>false</active>"));
1177 }
1178
1179 #[test]
1180 fn test_serialize_numbers() {
1181 #[derive(Serialize)]
1182 struct Numbers {
1183 i: i32,
1184 u: u64,
1185 f: f64,
1186 }
1187
1188 let nums = Numbers {
1189 i: -42,
1190 u: 100,
1191 f: 1.234,
1192 };
1193
1194 let xml = to_string(&nums).unwrap();
1195 assert!(xml.contains("<i>-42</i>"));
1196 assert!(xml.contains("<u>100</u>"));
1197 assert!(xml.contains("<f>1.234</f>"));
1198 }
1199
1200 #[test]
1201 fn test_serialize_enum() {
1202 #[derive(Serialize)]
1203 enum Status {
1204 Active,
1205 }
1206
1207 #[derive(Serialize)]
1208 struct Item {
1209 status: Status,
1210 }
1211
1212 let item = Item {
1213 status: Status::Active,
1214 };
1215
1216 let xml = to_string(&item).unwrap();
1217 assert!(xml.contains("<status>Active</status>") || xml.contains("<Active/>"));
1218 }
1219
1220 #[test]
1221 fn test_serialize_unit_struct() {
1222 #[derive(Serialize)]
1223 struct Empty;
1224
1225 let xml = to_string(&Empty).unwrap();
1226 assert!(xml.contains("<Empty/>"));
1227 }
1228
1229 #[test]
1230 fn test_serialize_char() {
1231 #[derive(Serialize)]
1232 struct Data {
1233 c: char,
1234 }
1235
1236 let data = Data { c: 'A' };
1237 let xml = to_string(&data).unwrap();
1238 assert!(xml.contains("<c>A</c>"));
1239 }
1240
1241 #[test]
1242 fn test_to_vec() {
1243 #[derive(Serialize)]
1244 struct Data {
1245 value: String,
1246 }
1247
1248 let data = Data {
1249 value: "test".to_string(),
1250 };
1251
1252 let bytes = to_vec(&data).unwrap();
1253 let xml = String::from_utf8(bytes).unwrap();
1254 assert!(xml.contains("<value>test</value>"));
1255 }
1256
1257 #[test]
1258 fn test_to_writer() {
1259 #[derive(Serialize)]
1260 struct Data {
1261 value: String,
1262 }
1263
1264 let data = Data {
1265 value: "test".to_string(),
1266 };
1267
1268 let mut buffer = Vec::new();
1269 to_writer(&mut buffer, &data).unwrap();
1270 let xml = String::from_utf8(buffer).unwrap();
1271 assert!(xml.contains("<value>test</value>"));
1272 }
1273
1274 #[test]
1275 fn test_with_root() {
1276 #[derive(Serialize)]
1277 struct Data {
1278 value: String,
1279 }
1280
1281 let data = Data {
1282 value: "test".to_string(),
1283 };
1284
1285 let xml = to_string_with_root(&data, "root").unwrap();
1286 assert_eq!(xml, "<root><value>test</value></root>");
1288 }
1289
1290 #[test]
1291 fn test_with_root_nested_uses_field_name() {
1292 #[derive(Serialize)]
1293 struct Inner {
1294 value: String,
1295 }
1296
1297 #[derive(Serialize)]
1298 struct Outer {
1299 inner: Inner,
1300 }
1301
1302 let outer = Outer {
1303 inner: Inner {
1304 value: "test".to_string(),
1305 },
1306 };
1307
1308 let xml = to_string_with_root(&outer, "root").unwrap();
1309 assert_eq!(xml, "<root><inner><value>test</value></inner></root>");
1311 }
1312
1313 #[test]
1314 fn test_complex_with_attributes() {
1315 #[derive(Serialize)]
1316 struct Item {
1317 #[serde(rename = "@id")]
1318 id: u32,
1319 #[serde(rename = "@class")]
1320 class: String,
1321 name: String,
1322 value: i32,
1323 }
1324
1325 #[derive(Serialize)]
1326 struct Container {
1327 #[serde(rename = "@version")]
1328 version: String,
1329 item: Vec<Item>,
1330 }
1331
1332 let container = Container {
1333 version: "1.0".to_string(),
1334 item: vec![
1335 Item {
1336 id: 1,
1337 class: "primary".to_string(),
1338 name: "First".to_string(),
1339 value: 100,
1340 },
1341 Item {
1342 id: 2,
1343 class: "secondary".to_string(),
1344 name: "Second".to_string(),
1345 value: 200,
1346 },
1347 ],
1348 };
1349
1350 let xml = to_string(&container).unwrap();
1351 assert!(xml.contains(r#"version="1.0""#));
1352 assert!(xml.contains(r#"id="1""#));
1353 assert!(xml.contains(r#"class="primary""#));
1354 assert!(xml.contains("<name>First</name>"));
1355 }
1356
1357 #[test]
1358 fn test_with_declaration() {
1359 #[derive(Serialize)]
1360 struct Data {
1361 value: String,
1362 }
1363
1364 let data = Data {
1365 value: "test".to_string(),
1366 };
1367
1368 let mut serializer = Serializer::new().with_declaration();
1369 data.serialize(&mut serializer).unwrap();
1370 let xml = serializer.into_string();
1371 assert!(xml.starts_with(r#"<?xml version="1.0" encoding="UTF-8"?>"#));
1372 assert!(xml.contains("<value>test</value>"));
1373 }
1374
1375 #[test]
1376 fn test_no_declaration_by_default() {
1377 #[derive(Serialize)]
1378 struct Data {
1379 value: String,
1380 }
1381
1382 let data = Data {
1383 value: "test".to_string(),
1384 };
1385
1386 let xml = to_string(&data).unwrap();
1387 assert!(!xml.contains("<?xml"));
1388 }
1389
1390 #[test]
1391 fn test_attribute_after_regular_field() {
1392 #[derive(Serialize)]
1393 struct Thing {
1394 name: String,
1395 #[serde(rename = "@id")]
1396 id: String,
1397 }
1398
1399 let thing = Thing {
1400 name: "widget".to_string(),
1401 id: "7".to_string(),
1402 };
1403
1404 let xml = to_string(&thing).unwrap();
1405 assert_eq!(xml, r#"<Thing id="7"><name>widget</name></Thing>"#);
1408 }
1409
1410 #[test]
1411 fn test_serialize_map_numeric_keys() {
1412 use std::collections::BTreeMap;
1413
1414 let mut map = BTreeMap::new();
1415 map.insert(1u32, "one".to_string());
1416 map.insert(2u32, "two".to_string());
1417
1418 let xml = to_string(&map).unwrap();
1419 assert_eq!(xml, "<map><1>one</1><2>two</2></map>");
1420 }
1421
1422 #[test]
1423 fn test_serialize_newtype_variant() {
1424 #[derive(Serialize)]
1425 enum Value {
1426 Count(u32),
1427 }
1428
1429 let xml = to_string(&Value::Count(42)).unwrap();
1430 assert_eq!(xml, "<Count>42</Count>");
1431 }
1432
1433 #[test]
1434 fn test_serialize_tuple_variant() {
1435 #[derive(Serialize)]
1436 enum Value {
1437 Pair(u32, String),
1438 }
1439
1440 let xml = to_string(&Value::Pair(1, "one".to_string())).unwrap();
1441 assert_eq!(xml, "<Pair><item>1</item><item>one</item></Pair>");
1442 }
1443
1444 #[test]
1445 fn test_serialize_struct_variant() {
1446 #[derive(Serialize)]
1447 enum Value {
1448 Point { x: i32, y: i32 },
1449 }
1450
1451 let xml = to_string(&Value::Point { x: 1, y: 2 }).unwrap();
1452 assert_eq!(xml, "<Point><x>1</x><y>2</y></Point>");
1453 }
1454
1455 #[test]
1456 fn test_serialize_newtype_variant_as_field() {
1457 #[derive(Serialize)]
1458 enum Value {
1459 Count(u32),
1460 }
1461
1462 #[derive(Serialize)]
1463 struct Item {
1464 status: Value,
1465 }
1466
1467 let item = Item {
1468 status: Value::Count(42),
1469 };
1470
1471 let xml = to_string(&item).unwrap();
1472 assert_eq!(xml, "<Item><status><Count>42</Count></status></Item>");
1473 }
1474
1475 #[test]
1476 fn test_serialize_tuple_variant_as_field() {
1477 #[derive(Serialize)]
1478 enum Value {
1479 Pair(u32, String),
1480 }
1481
1482 #[derive(Serialize)]
1483 struct Item {
1484 status: Value,
1485 }
1486
1487 let item = Item {
1488 status: Value::Pair(1, "one".to_string()),
1489 };
1490
1491 let xml = to_string(&item).unwrap();
1492 assert_eq!(
1493 xml,
1494 "<Item><status><Pair><item>1</item><item>one</item></Pair></status></Item>"
1495 );
1496 }
1497
1498 #[test]
1499 fn test_serialize_struct_variant_as_field() {
1500 #[derive(Serialize)]
1501 enum Value {
1502 Point { x: i32, y: i32 },
1503 }
1504
1505 #[derive(Serialize)]
1506 struct Item {
1507 status: Value,
1508 }
1509
1510 let item = Item {
1511 status: Value::Point { x: 1, y: 2 },
1512 };
1513
1514 let xml = to_string(&item).unwrap();
1515 assert_eq!(xml, "<Item><status><Point><x>1</x><y>2</y></Point></status></Item>");
1516 }
1517
1518 #[test]
1519 fn test_exact_output_simple_struct() {
1520 #[derive(Serialize)]
1521 struct Person {
1522 name: String,
1523 age: u32,
1524 }
1525
1526 let person = Person {
1527 name: "Alice".to_string(),
1528 age: 30,
1529 };
1530
1531 let xml = to_string(&person).unwrap();
1532 assert_eq!(xml, "<Person><name>Alice</name><age>30</age></Person>");
1533 }
1534
1535 #[test]
1536 fn test_exact_output_attributes() {
1537 #[derive(Serialize)]
1538 struct Item {
1539 #[serde(rename = "@id")]
1540 id: String,
1541 #[serde(rename = "@class")]
1542 class: String,
1543 name: String,
1544 }
1545
1546 let item = Item {
1547 id: "123".to_string(),
1548 class: "product".to_string(),
1549 name: "Widget".to_string(),
1550 };
1551
1552 let xml = to_string(&item).unwrap();
1553 assert_eq!(xml, r#"<Item id="123" class="product"><name>Widget</name></Item>"#);
1554 }
1555
1556 #[test]
1557 fn test_exact_output_text_content() {
1558 #[derive(Serialize)]
1559 struct Link {
1560 #[serde(rename = "@href")]
1561 href: String,
1562 #[serde(rename = "$value")]
1563 text: String,
1564 }
1565
1566 let link = Link {
1567 href: "https://example.com".to_string(),
1568 text: "Click here".to_string(),
1569 };
1570
1571 let xml = to_string(&link).unwrap();
1572 assert_eq!(xml, r#"<Link href="https://example.com">Click here</Link>"#);
1573 }
1574
1575 #[test]
1576 fn test_with_indent() {
1577 #[derive(Serialize)]
1578 struct Address {
1579 city: String,
1580 }
1581
1582 #[derive(Serialize)]
1583 struct Person {
1584 name: String,
1585 address: Address,
1586 }
1587
1588 let person = Person {
1589 name: "Alice".to_string(),
1590 address: Address {
1591 city: "Springfield".to_string(),
1592 },
1593 };
1594
1595 let mut serializer = Serializer::new().with_indent(" ");
1596 person.serialize(&mut serializer).unwrap();
1597 let xml = serializer.into_string();
1598 assert_eq!(
1599 xml,
1600 "<Person>\n <name>Alice</name>\n <address>\n <city>Springfield</city>\n </address>\n</Person>"
1601 );
1602 }
1603
1604 #[test]
1605 fn test_serialize_map_char_keys() {
1606 use std::collections::BTreeMap;
1607
1608 let mut map = BTreeMap::new();
1609 map.insert('a', "1");
1610 map.insert('b', "2");
1611
1612 let xml = to_string(&map).unwrap();
1613 assert_eq!(xml, "<map><a>1</a><b>2</b></map>");
1614 }
1615
1616 #[test]
1617 fn test_serialize_map_negative_int_keys() {
1618 use std::collections::BTreeMap;
1619
1620 let mut map = BTreeMap::new();
1621 map.insert(-1i64, "neg");
1622 map.insert(2i64, "pos");
1623
1624 let xml = to_string(&map).unwrap();
1625 assert_eq!(xml, "<map><-1>neg</-1><2>pos</2></map>");
1626 }
1627
1628 #[test]
1629 fn test_serialize_map_bool_keys() {
1630 use std::collections::BTreeMap;
1631
1632 let mut map = BTreeMap::new();
1633 map.insert(false, "no");
1634 map.insert(true, "yes");
1635
1636 let xml = to_string(&map).unwrap();
1637 assert_eq!(xml, "<map><false>no</false><true>yes</true></map>");
1638 }
1639
1640 #[test]
1641 fn test_none_first_field_then_regular() {
1642 #[derive(Serialize)]
1643 struct S {
1644 a: Option<String>,
1645 b: String,
1646 }
1647
1648 let s = S {
1649 a: None,
1650 b: "x".to_string(),
1651 };
1652
1653 let xml = to_string(&s).unwrap();
1656 assert_eq!(xml, "<S><b>x</b></S>");
1657 }
1658
1659 #[test]
1660 fn test_empty_vec_first_field_then_regular() {
1661 #[derive(Serialize)]
1662 struct S {
1663 a: Vec<String>,
1664 b: String,
1665 }
1666
1667 let s = S {
1668 a: vec![],
1669 b: "x".to_string(),
1670 };
1671
1672 let xml = to_string(&s).unwrap();
1675 assert_eq!(xml, "<S><b>x</b></S>");
1676 }
1677
1678 #[test]
1679 fn test_all_none_fields_empty_element() {
1680 #[derive(Serialize)]
1681 struct S {
1682 a: Option<String>,
1683 b: Option<i32>,
1684 }
1685
1686 let s = S { a: None, b: None };
1687
1688 let xml = to_string(&s).unwrap();
1690 assert_eq!(xml, "<S/>");
1691 }
1692
1693 #[test]
1694 fn test_none_first_field_then_attribute() {
1695 #[derive(Serialize)]
1696 struct S {
1697 a: Option<String>,
1698 #[serde(rename = "@id")]
1699 id: String,
1700 b: String,
1701 }
1702
1703 let s = S {
1704 a: None,
1705 id: "7".to_string(),
1706 b: "x".to_string(),
1707 };
1708
1709 let xml = to_string(&s).unwrap();
1712 assert_eq!(xml, r#"<S id="7"><b>x</b></S>"#);
1713 }
1714
1715 #[test]
1716 fn test_multiple_attributes_after_regular_field() {
1717 #[derive(Serialize)]
1718 struct S {
1719 name: String,
1720 #[serde(rename = "@id")]
1721 id: String,
1722 #[serde(rename = "@cls")]
1723 cls: String,
1724 }
1725
1726 let s = S {
1727 name: "w".to_string(),
1728 id: "7".to_string(),
1729 cls: "a".to_string(),
1730 };
1731
1732 let xml = to_string(&s).unwrap();
1735 assert_eq!(xml, r#"<S id="7" cls="a"><name>w</name></S>"#);
1736 }
1737
1738 #[test]
1739 fn test_attribute_after_nested_child() {
1740 #[derive(Serialize)]
1741 struct Inner {
1742 v: String,
1743 }
1744
1745 #[derive(Serialize)]
1746 struct Outer {
1747 child: Inner,
1748 #[serde(rename = "@id")]
1749 id: String,
1750 }
1751
1752 let outer = Outer {
1753 child: Inner {
1754 v: "x".to_string(),
1755 },
1756 id: "7".to_string(),
1757 };
1758
1759 let xml = to_string(&outer).unwrap();
1762 assert_eq!(xml, r#"<Outer id="7"><child><v>x</v></child></Outer>"#);
1763 }
1764}