1use crate::de::{TEXT_KEY, VALUE_KEY};
4use crate::se::content::ContentSerializer;
5use crate::se::key::QNameSerializer;
6use crate::se::simple_type::{QuoteTarget, SimpleSeq, SimpleTypeSerializer};
7use crate::se::text::TextSerializer;
8use crate::se::{EmptyElementHandling, SeError, WriteResult, XmlName};
9use serde::ser::{
10 Impossible, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
11 SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer,
12};
13use std::fmt::Write;
14
15macro_rules! write_primitive {
17 ($method:ident ( $ty:ty )) => {
18 fn $method(self, value: $ty) -> Result<Self::Ok, Self::Error> {
19 self.ser.write_wrapped(self.key, |ser| ser.$method(value))
20 }
21 };
22}
23
24pub struct ElementSerializer<'w, 'k, W: Write> {
60 pub ser: ContentSerializer<'w, 'k, W>,
62 pub(super) key: XmlName<'k>,
64}
65
66impl<'w, 'k, W: Write> Serializer for ElementSerializer<'w, 'k, W> {
67 type Ok = WriteResult;
68 type Error = SeError;
69
70 type SerializeSeq = Self;
71 type SerializeTuple = Self;
72 type SerializeTupleStruct = Self;
73 type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
74 type SerializeMap = Map<'w, 'k, W>;
75 type SerializeStruct = Struct<'w, 'k, W>;
76 type SerializeStructVariant = Struct<'w, 'k, W>;
77
78 write_primitive!(serialize_bool(bool));
79
80 write_primitive!(serialize_i8(i8));
81 write_primitive!(serialize_i16(i16));
82 write_primitive!(serialize_i32(i32));
83 write_primitive!(serialize_i64(i64));
84
85 write_primitive!(serialize_u8(u8));
86 write_primitive!(serialize_u16(u16));
87 write_primitive!(serialize_u32(u32));
88 write_primitive!(serialize_u64(u64));
89
90 write_primitive!(serialize_i128(i128));
91 write_primitive!(serialize_u128(u128));
92
93 write_primitive!(serialize_f32(f32));
94 write_primitive!(serialize_f64(f64));
95
96 write_primitive!(serialize_char(char));
97 write_primitive!(serialize_bytes(&[u8]));
98
99 fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
100 if value.is_empty() {
101 self.ser.write_empty(self.key)
102 } else {
103 self.ser
104 .write_wrapped(self.key, |ser| ser.serialize_str(value))
105 }
106 }
107
108 fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
122 self.serialize_unit()
123 }
124
125 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
126 value.serialize(self)
127 }
128
129 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
130 self.ser.write_empty(self.key)
131 }
132
133 fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
134 self.ser.write_empty(self.key)
135 }
136
137 fn serialize_unit_variant(
141 self,
142 name: &'static str,
143 variant_index: u32,
144 variant: &'static str,
145 ) -> Result<Self::Ok, Self::Error> {
146 if variant == TEXT_KEY {
147 self.ser.write_empty(self.key)
148 } else {
149 self.ser.write_wrapped(self.key, |ser| {
150 ser.serialize_unit_variant(name, variant_index, variant)
151 })
152 }
153 }
154
155 fn serialize_newtype_struct<T: ?Sized + Serialize>(
156 self,
157 _name: &'static str,
158 value: &T,
159 ) -> Result<Self::Ok, Self::Error> {
160 value.serialize(self)
161 }
162
163 #[inline]
166 fn serialize_newtype_variant<T: ?Sized + Serialize>(
167 self,
168 name: &'static str,
169 _variant_index: u32,
170 variant: &'static str,
171 _value: &T,
172 ) -> Result<Self::Ok, Self::Error> {
173 Err(SeError::Unsupported(
174 format!(
175 "cannot serialize enum newtype variant `{}::{}`",
176 name, variant
177 )
178 .into(),
179 ))
180 }
181
182 #[inline]
183 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
184 Ok(self)
185 }
186
187 #[inline]
188 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
189 self.serialize_seq(Some(len))
190 }
191
192 #[inline]
193 fn serialize_tuple_struct(
194 self,
195 _name: &'static str,
196 len: usize,
197 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
198 self.serialize_tuple(len)
199 }
200
201 #[inline]
204 fn serialize_tuple_variant(
205 self,
206 name: &'static str,
207 _variant_index: u32,
208 variant: &'static str,
209 _len: usize,
210 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
211 Err(SeError::Unsupported(
212 format!(
213 "cannot serialize enum tuple variant `{}::{}`",
214 name, variant
215 )
216 .into(),
217 ))
218 }
219
220 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
221 Ok(Map {
222 ser: self.serialize_struct("", 0)?,
223 key: None,
224 })
225 }
226
227 #[inline]
228 fn serialize_struct(
229 mut self,
230 _name: &'static str,
231 _len: usize,
232 ) -> Result<Self::SerializeStruct, Self::Error> {
233 self.ser.write_indent()?;
234 self.ser.indent.increase();
235
236 self.ser.writer.write_char('<')?;
237 self.ser.writer.write_str(self.key.0)?;
238 Ok(Struct {
239 ser: self,
240 children: String::new(),
241 write_indent: true,
242 })
243 }
244
245 #[inline]
248 fn serialize_struct_variant(
249 self,
250 name: &'static str,
251 _variant_index: u32,
252 variant: &'static str,
253 _len: usize,
254 ) -> Result<Self::SerializeStructVariant, Self::Error> {
255 Err(SeError::Unsupported(
256 format!(
257 "cannot serialize enum struct variant `{}::{}`",
258 name, variant
259 )
260 .into(),
261 ))
262 }
263}
264
265impl<'w, 'k, W: Write> SerializeSeq for ElementSerializer<'w, 'k, W> {
266 type Ok = WriteResult;
267 type Error = SeError;
268
269 fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
270 where
271 T: ?Sized + Serialize,
272 {
273 value.serialize(ElementSerializer {
274 ser: self.ser.new_seq_element_serializer(true),
275 key: self.key,
276 })?;
277 self.ser.write_indent = true;
279 Ok(())
280 }
281
282 #[inline]
283 fn end(self) -> Result<Self::Ok, Self::Error> {
284 Ok(WriteResult::Element)
285 }
286}
287
288impl<'w, 'k, W: Write> SerializeTuple for ElementSerializer<'w, 'k, W> {
289 type Ok = WriteResult;
290 type Error = SeError;
291
292 #[inline]
293 fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
294 where
295 T: ?Sized + Serialize,
296 {
297 SerializeSeq::serialize_element(self, value)
298 }
299
300 #[inline]
301 fn end(self) -> Result<Self::Ok, Self::Error> {
302 SerializeSeq::end(self)
303 }
304}
305
306impl<'w, 'k, W: Write> SerializeTupleStruct for ElementSerializer<'w, 'k, W> {
307 type Ok = WriteResult;
308 type Error = SeError;
309
310 #[inline]
311 fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
312 where
313 T: ?Sized + Serialize,
314 {
315 SerializeSeq::serialize_element(self, value)
316 }
317
318 #[inline]
319 fn end(self) -> Result<Self::Ok, Self::Error> {
320 SerializeSeq::end(self)
321 }
322}
323
324pub enum Tuple<'w, 'k, W: Write> {
330 Element(ElementSerializer<'w, 'k, W>),
332 Text(SimpleSeq<&'w mut W>),
334}
335
336impl<'w, 'k, W: Write> SerializeTupleVariant for Tuple<'w, 'k, W> {
337 type Ok = WriteResult;
338 type Error = SeError;
339
340 #[inline]
341 fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
342 where
343 T: ?Sized + Serialize,
344 {
345 match self {
346 Self::Element(ser) => SerializeTuple::serialize_element(ser, value),
347 Self::Text(ser) => SerializeTuple::serialize_element(ser, value),
348 }
349 }
350
351 #[inline]
352 fn end(self) -> Result<Self::Ok, Self::Error> {
353 match self {
354 Self::Element(ser) => SerializeTuple::end(ser),
355 Self::Text(ser) => SerializeTuple::end(ser).map(|_| WriteResult::SensitiveText),
358 }
359 }
360}
361
362pub struct Struct<'w, 'k, W: Write> {
374 ser: ElementSerializer<'w, 'k, W>,
375 children: String,
380 write_indent: bool,
382}
383
384impl<'w, 'k, W: Write> Struct<'w, 'k, W> {
385 #[inline]
386 fn write_field<T>(&mut self, key: &str, value: &T) -> Result<(), SeError>
387 where
388 T: ?Sized + Serialize,
389 {
390 if let Some(key) = key.strip_prefix('@') {
392 let key = XmlName::try_from(key)?;
393 self.write_attribute(key, value)
394 } else {
395 self.write_element(key, value)
396 }
397 }
398
399 #[inline]
401 fn write_attribute<T>(&mut self, key: XmlName, value: &T) -> Result<(), SeError>
402 where
403 T: ?Sized + Serialize,
404 {
405 self.ser.ser.writer.write_char(' ')?;
407 self.ser.ser.writer.write_str(key.0)?;
408 self.ser.ser.writer.write_char('=')?;
409
410 self.ser.ser.writer.write_char('"')?;
412 value.serialize(SimpleTypeSerializer {
413 writer: &mut self.ser.ser.writer,
414 target: QuoteTarget::DoubleQAttr,
415 level: self.ser.ser.level,
416 })?;
417 self.ser.ser.writer.write_char('"')?;
418
419 Ok(())
420 }
421
422 fn write_element<T>(&mut self, key: &str, value: &T) -> Result<(), SeError>
434 where
435 T: ?Sized + Serialize,
436 {
437 let ser = ContentSerializer {
438 writer: &mut self.children,
439 level: self.ser.ser.level,
440 indent: self.ser.ser.indent.borrow(),
441 write_indent: self.write_indent,
443 text_format: self.ser.ser.text_format,
444 allow_primitive: true,
445 empty_element_handling: self.ser.ser.empty_element_handling,
446 };
447
448 if key == TEXT_KEY {
449 value.serialize(TextSerializer(ser.into_simple_type_serializer()?))?;
450 self.write_indent = false;
452 } else if key == VALUE_KEY {
453 self.write_indent = value.serialize(ser)?.allow_indent();
455 } else {
456 value.serialize(ElementSerializer {
457 key: XmlName::try_from(key)?,
458 ser,
459 })?;
460 self.write_indent = true;
462 }
463 Ok(())
464 }
465}
466
467impl<'w, 'k, W: Write> SerializeStruct for Struct<'w, 'k, W> {
468 type Ok = WriteResult;
469 type Error = SeError;
470
471 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
472 where
473 T: ?Sized + Serialize,
474 {
475 self.write_field(key, value)
476 }
477
478 fn end(mut self) -> Result<Self::Ok, Self::Error> {
479 self.ser.ser.indent.decrease();
480
481 if self.children.is_empty() {
482 match self.ser.ser.empty_element_handling {
483 EmptyElementHandling::SelfClosed => {
484 self.ser.ser.writer.write_str("/>")?;
485 }
486 EmptyElementHandling::SelfClosedWithSpace => {
487 self.ser.ser.writer.write_str(" />")?;
488 }
489 EmptyElementHandling::Expanded => {
490 self.ser.ser.writer.write_str("></")?;
491 self.ser.ser.writer.write_str(self.ser.key.0)?;
492 self.ser.ser.writer.write_char('>')?;
493 }
494 }
495 } else {
496 self.ser.ser.writer.write_char('>')?;
497 self.ser.ser.writer.write_str(&self.children)?;
498
499 if self.write_indent {
500 self.ser.ser.indent.write_indent(&mut self.ser.ser.writer)?;
501 }
502
503 self.ser.ser.writer.write_str("</")?;
504 self.ser.ser.writer.write_str(self.ser.key.0)?;
505 self.ser.ser.writer.write_char('>')?;
506 }
507 Ok(WriteResult::Element)
508 }
509}
510
511impl<'w, 'k, W: Write> SerializeStructVariant for Struct<'w, 'k, W> {
512 type Ok = WriteResult;
513 type Error = SeError;
514
515 #[inline]
516 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
517 where
518 T: ?Sized + Serialize,
519 {
520 SerializeStruct::serialize_field(self, key, value)
521 }
522
523 #[inline]
524 fn end(self) -> Result<Self::Ok, Self::Error> {
525 SerializeStruct::end(self)
526 }
527}
528
529pub struct Map<'w, 'k, W: Write> {
532 ser: Struct<'w, 'k, W>,
533 key: Option<String>,
536}
537
538impl<'w, 'k, W: Write> Map<'w, 'k, W> {
539 fn make_key<T>(&mut self, key: &T) -> Result<String, SeError>
540 where
541 T: ?Sized + Serialize,
542 {
543 key.serialize(QNameSerializer {
544 writer: String::new(),
545 })
546 }
547}
548
549impl<'w, 'k, W: Write> SerializeMap for Map<'w, 'k, W> {
550 type Ok = WriteResult;
551 type Error = SeError;
552
553 fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
554 where
555 T: ?Sized + Serialize,
556 {
557 if self.key.take().is_some() {
558 return Err(SeError::Custom(
559 "calling `serialize_key` twice without `serialize_value`".to_string(),
560 ));
561 }
562 self.key = Some(self.make_key(key)?);
563 Ok(())
564 }
565
566 fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
567 where
568 T: ?Sized + Serialize,
569 {
570 if let Some(key) = self.key.take() {
571 return self.ser.write_field(&key, value);
572 }
573 Err(SeError::Custom(
574 "calling `serialize_value` without call of `serialize_key`".to_string(),
575 ))
576 }
577
578 fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
579 where
580 K: ?Sized + Serialize,
581 V: ?Sized + Serialize,
582 {
583 let key = self.make_key(key)?;
584 self.ser.write_field(&key, value)
585 }
586
587 fn end(mut self) -> Result<Self::Ok, Self::Error> {
588 if let Some(key) = self.key.take() {
589 return Err(SeError::Custom(format!(
590 "calling `end` without call of `serialize_value` for key `{key}`"
591 )));
592 }
593 SerializeStruct::end(self.ser)
594 }
595}
596
597#[cfg(test)]
600mod tests {
601 use super::*;
602 use crate::se::content::tests::*;
603 use crate::se::{Indent, QuoteLevel, TextFormat};
604 use crate::utils::Bytes;
605 use serde::Serialize;
606 use std::collections::BTreeMap;
607
608 #[derive(Debug, Serialize, PartialEq)]
609 struct OptionalElements {
610 a: Option<&'static str>,
611
612 #[serde(skip_serializing_if = "Option::is_none")]
613 b: Option<&'static str>,
614 }
615 #[derive(Debug, Serialize, PartialEq)]
616 struct OptionalAttributes {
617 #[serde(rename = "@a")]
618 a: Option<&'static str>,
619
620 #[serde(rename = "@b")]
621 #[serde(skip_serializing_if = "Option::is_none")]
622 b: Option<&'static str>,
623 }
624
625 mod without_indent {
626 use super::*;
627 use crate::se::content::tests::Struct;
628 use pretty_assertions::assert_eq;
629
630 macro_rules! serialize_as {
632 ($name:ident: $data:expr => $expected:expr) => {
633 #[test]
634 fn $name() {
635 let mut buffer = String::new();
636 let ser = ElementSerializer {
637 ser: ContentSerializer {
638 writer: &mut buffer,
639 level: QuoteLevel::Full,
640 indent: Indent::None,
641 write_indent: false,
642 text_format: TextFormat::Text,
643 allow_primitive: true,
644 empty_element_handling: EmptyElementHandling::SelfClosed,
645 },
646 key: XmlName("root"),
647 };
648
649 let result = $data.serialize(ser).unwrap();
650 assert_eq!(buffer, $expected);
651 assert_eq!(result, WriteResult::Element);
652 }
653 };
654 }
655
656 macro_rules! err {
659 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
660 #[test]
661 fn $name() {
662 let mut buffer = String::new();
663 let ser = ElementSerializer {
664 ser: ContentSerializer {
665 writer: &mut buffer,
666 level: QuoteLevel::Full,
667 indent: Indent::None,
668 write_indent: false,
669 text_format: TextFormat::Text,
670 allow_primitive: true,
671 empty_element_handling: EmptyElementHandling::SelfClosed,
672 },
673 key: XmlName("root"),
674 };
675
676 match $data.serialize(ser).unwrap_err() {
677 SeError::$kind(e) => assert_eq!(e, $reason),
678 e => panic!(
679 "Expected `Err({}({}))`, but got `{:?}`",
680 stringify!($kind),
681 $reason,
682 e
683 ),
684 }
685 }
688 };
689 }
690
691 serialize_as!(false_: false => "<root>false</root>");
692 serialize_as!(true_: true => "<root>true</root>");
693
694 serialize_as!(i8_: -42i8 => "<root>-42</root>");
695 serialize_as!(i16_: -4200i16 => "<root>-4200</root>");
696 serialize_as!(i32_: -42000000i32 => "<root>-42000000</root>");
697 serialize_as!(i64_: -42000000000000i64 => "<root>-42000000000000</root>");
698 serialize_as!(isize_: -42000000isize => "<root>-42000000</root>");
699
700 serialize_as!(u8_: 42u8 => "<root>42</root>");
701 serialize_as!(u16_: 4200u16 => "<root>4200</root>");
702 serialize_as!(u32_: 42000000u32 => "<root>42000000</root>");
703 serialize_as!(u64_: 42000000000000u64 => "<root>42000000000000</root>");
704 serialize_as!(usize_: 42000000usize => "<root>42000000</root>");
705
706 serialize_as!(i128_: -420000000000000000000000000000i128 => "<root>-420000000000000000000000000000</root>");
707 serialize_as!(u128_: 420000000000000000000000000000u128 => "<root>420000000000000000000000000000</root>");
708
709 serialize_as!(f32_: 4.2f32 => "<root>4.2</root>");
710 serialize_as!(f64_: 4.2f64 => "<root>4.2</root>");
711
712 serialize_as!(char_non_escaped: 'h' => "<root>h</root>");
713 serialize_as!(char_lt: '<' => "<root><</root>");
714 serialize_as!(char_gt: '>' => "<root>></root>");
715 serialize_as!(char_amp: '&' => "<root>&</root>");
716 serialize_as!(char_apos: '\'' => "<root>'</root>");
717 serialize_as!(char_quot: '"' => "<root>"</root>");
718
719 serialize_as!(str_non_escaped: "non-escaped string" => "<root>non-escaped string</root>");
720 serialize_as!(str_escaped: "<\"escaped & string'>" => "<root><"escaped & string'></root>");
721
722 err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
723
724 serialize_as!(option_none: Option::<&str>::None => "<root/>");
725 serialize_as!(option_some: Some("non-escaped string") => "<root>non-escaped string</root>");
726 serialize_as!(option_some_empty_str: Some("") => "<root/>");
727
728 serialize_as!(unit: () => "<root/>");
729 serialize_as!(unit_struct: Unit => "<root/>");
730 serialize_as!(unit_struct_escaped: UnitEscaped => "<root/>");
731
732 serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
733 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root><"&'></root>");
734
735 serialize_as!(newtype: Newtype(42) => "<root>42</root>");
736 err!(enum_newtype: Enum::Newtype(42)
737 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype`"));
738
739 serialize_as!(seq: vec![1, 2, 3]
740 => "<root>1</root>\
741 <root>2</root>\
742 <root>3</root>");
743 serialize_as!(seq_empty: Vec::<usize>::new() => "");
744 serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
745 => "<root><"&'></root>\
746 <root>with\t\n\r spaces</root>\
747 <root>3</root>");
748 serialize_as!(tuple_struct: Tuple("first", 42)
749 => "<root>first</root>\
750 <root>42</root>");
751 err!(enum_tuple: Enum::Tuple("first", 42)
752 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple`"));
753
754 serialize_as!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
755 => "<root>\
756 <_1>2</_1>\
757 <_3>4</_3>\
758 </root>");
759 serialize_as!(struct_: Struct { key: "answer", val: (42, 42) }
760 => "<root>\
761 <key>answer</key>\
762 <val>42</val>\
763 <val>42</val>\
764 </root>");
765 err!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
766 => Unsupported("cannot serialize enum struct variant `Enum::Struct`"));
767
768 mod text_field {
771 use super::*;
772
773 mod map {
775 use super::*;
776 use pretty_assertions::assert_eq;
777
778 macro_rules! text {
779 ($name:ident: $data:expr) => {
780 serialize_as!($name:
781 BTreeMap::from([("$text", $data)])
782 => "<root/>");
783 };
784 ($name:ident: $data:expr => $expected:literal) => {
785 serialize_as!($name:
786 BTreeMap::from([("$text", $data)])
787 => concat!("<root>", $expected,"</root>"));
788 };
789 }
790
791 text!(false_: false => "false");
792 text!(true_: true => "true");
793
794 text!(i8_: -42i8 => "-42");
795 text!(i16_: -4200i16 => "-4200");
796 text!(i32_: -42000000i32 => "-42000000");
797 text!(i64_: -42000000000000i64 => "-42000000000000");
798 text!(isize_: -42000000isize => "-42000000");
799
800 text!(u8_: 42u8 => "42");
801 text!(u16_: 4200u16 => "4200");
802 text!(u32_: 42000000u32 => "42000000");
803 text!(u64_: 42000000000000u64 => "42000000000000");
804 text!(usize_: 42000000usize => "42000000");
805
806 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
807 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
808
809 text!(f32_: 4.2f32 => "4.2");
810 text!(f64_: 4.2f64 => "4.2");
811
812 text!(char_non_escaped: 'h' => "h");
813 text!(char_lt: '<' => "<");
814 text!(char_gt: '>' => ">");
815 text!(char_amp: '&' => "&");
816 text!(char_apos: '\'' => "'");
817 text!(char_quot: '"' => """);
818 text!(char_space: ' ' => " ");
819
820 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
821 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
822
823 err!(bytes:
824 Text {
825 before: "answer",
826 content: Bytes(b"<\"escaped & bytes'>"),
827 after: "answer",
828 }
829 => Unsupported("`serialize_bytes` not supported yet"));
830
831 text!(option_none: Option::<&str>::None);
832 text!(option_some: Some("non-escaped string") => "non-escaped string");
833 text!(option_some_empty_str: Some(""));
834
835 text!(unit: ());
836 text!(unit_struct: Unit);
837 text!(unit_struct_escaped: UnitEscaped);
838
839 text!(enum_unit: Enum::Unit => "Unit");
840 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
841
842 text!(newtype: Newtype(42) => "42");
843 err!(enum_newtype:
845 Text {
846 before: "answer",
847 content: Enum::Newtype(42),
848 after: "answer",
849 }
850 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
851
852 text!(seq: vec![1, 2, 3] => "1 2 3");
854 text!(seq_empty: Vec::<usize>::new());
855 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
856 => "<"&'> \
857 with	  spaces \
858 3");
859 text!(tuple_struct: Tuple("first", 42) => "first 42");
860 err!(enum_tuple:
862 Text {
863 before: "answer",
864 content: Enum::Tuple("first", 42),
865 after: "answer",
866 }
867 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
868
869 err!(map:
871 Text {
872 before: "answer",
873 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
874 after: "answer",
875 }
876 => Unsupported("cannot serialize map as text content value"));
877 err!(struct_:
878 Text {
879 before: "answer",
880 content: Struct { key: "answer", val: (42, 42) },
881 after: "answer",
882 }
883 => Unsupported("cannot serialize struct `Struct` as text content value"));
884 err!(enum_struct:
885 Text {
886 before: "answer",
887 content: Enum::Struct { key: "answer", val: (42, 42) },
888 after: "answer",
889 }
890 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
891 }
892
893 mod struct_ {
895 use super::*;
896 use pretty_assertions::assert_eq;
897
898 macro_rules! text {
899 ($name:ident: $data:expr => $expected:literal) => {
900 serialize_as!($name:
901 Text {
902 before: "answer",
903 content: $data,
904 after: "answer",
905 }
906 => concat!(
907 "<root><before>answer</before>",
908 $expected,
909 "<after>answer</after></root>",
910 ));
911 };
912 }
913
914 text!(false_: false => "false");
915 text!(true_: true => "true");
916
917 text!(i8_: -42i8 => "-42");
918 text!(i16_: -4200i16 => "-4200");
919 text!(i32_: -42000000i32 => "-42000000");
920 text!(i64_: -42000000000000i64 => "-42000000000000");
921 text!(isize_: -42000000isize => "-42000000");
922
923 text!(u8_: 42u8 => "42");
924 text!(u16_: 4200u16 => "4200");
925 text!(u32_: 42000000u32 => "42000000");
926 text!(u64_: 42000000000000u64 => "42000000000000");
927 text!(usize_: 42000000usize => "42000000");
928
929 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
930 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
931
932 text!(f32_: 4.2f32 => "4.2");
933 text!(f64_: 4.2f64 => "4.2");
934
935 text!(char_non_escaped: 'h' => "h");
936 text!(char_lt: '<' => "<");
937 text!(char_gt: '>' => ">");
938 text!(char_amp: '&' => "&");
939 text!(char_apos: '\'' => "'");
940 text!(char_quot: '"' => """);
941 text!(char_space: ' ' => " ");
942
943 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
944 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
945
946 err!(bytes:
947 Text {
948 before: "answer",
949 content: Bytes(b"<\"escaped & bytes'>"),
950 after: "answer",
951 }
952 => Unsupported("`serialize_bytes` not supported yet"));
953
954 text!(option_none: Option::<&str>::None => "");
955 text!(option_some: Some("non-escaped string") => "non-escaped string");
956 text!(option_some_empty_str: Some("") => "");
957
958 text!(unit: () => "");
959 text!(unit_struct: Unit => "");
960 text!(unit_struct_escaped: UnitEscaped => "");
961
962 text!(enum_unit: Enum::Unit => "Unit");
963 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
964
965 text!(newtype: Newtype(42) => "42");
966 err!(enum_newtype:
968 Text {
969 before: "answer",
970 content: Enum::Newtype(42),
971 after: "answer",
972 }
973 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
974
975 text!(seq: vec![1, 2, 3] => "1 2 3");
977 text!(seq_empty: Vec::<usize>::new() => "");
978 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
979 => "<"&'> \
980 with	  spaces \
981 3");
982 text!(tuple_struct: Tuple("first", 42) => "first 42");
983 err!(enum_tuple:
985 Text {
986 before: "answer",
987 content: Enum::Tuple("first", 42),
988 after: "answer",
989 }
990 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
991
992 err!(map:
994 Text {
995 before: "answer",
996 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
997 after: "answer",
998 }
999 => Unsupported("cannot serialize map as text content value"));
1000 err!(struct_:
1001 Text {
1002 before: "answer",
1003 content: Struct { key: "answer", val: (42, 42) },
1004 after: "answer",
1005 }
1006 => Unsupported("cannot serialize struct `Struct` as text content value"));
1007 err!(enum_struct:
1008 Text {
1009 before: "answer",
1010 content: Enum::Struct { key: "answer", val: (42, 42) },
1011 after: "answer",
1012 }
1013 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1014 }
1015 }
1016
1017 mod value_field {
1021 use super::*;
1022
1023 mod map {
1025 use super::*;
1026 use pretty_assertions::assert_eq;
1027
1028 macro_rules! value {
1029 ($name:ident: $data:expr) => {
1030 serialize_as!($name:
1031 BTreeMap::from([("$value", $data)])
1032 => "<root/>");
1033 };
1034 ($name:ident: $data:expr => $expected:literal) => {
1035 serialize_as!($name:
1036 BTreeMap::from([("$value", $data)])
1037 => concat!("<root>", $expected,"</root>"));
1038 };
1039 }
1040
1041 value!(false_: false => "false");
1042 value!(true_: true => "true");
1043
1044 value!(i8_: -42i8 => "-42");
1045 value!(i16_: -4200i16 => "-4200");
1046 value!(i32_: -42000000i32 => "-42000000");
1047 value!(i64_: -42000000000000i64 => "-42000000000000");
1048 value!(isize_: -42000000isize => "-42000000");
1049
1050 value!(u8_: 42u8 => "42");
1051 value!(u16_: 4200u16 => "4200");
1052 value!(u32_: 42000000u32 => "42000000");
1053 value!(u64_: 42000000000000u64 => "42000000000000");
1054 value!(usize_: 42000000usize => "42000000");
1055
1056 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1057 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1058
1059 value!(f32_: 4.2f32 => "4.2");
1060 value!(f64_: 4.2f64 => "4.2");
1061
1062 value!(char_non_escaped: 'h' => "h");
1063 value!(char_lt: '<' => "<");
1064 value!(char_gt: '>' => ">");
1065 value!(char_amp: '&' => "&");
1066 value!(char_apos: '\'' => "'");
1067 value!(char_quot: '"' => """);
1068 value!(char_space: ' ' => " ");
1069
1070 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1071 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1072
1073 err!(bytes:
1074 BTreeMap::from([("$value", Bytes(b"<\"escaped & bytes'>"))])
1075 => Unsupported("`serialize_bytes` not supported yet"));
1076
1077 value!(option_none: Option::<&str>::None);
1078 value!(option_some: Some("non-escaped string") => "non-escaped string");
1079 value!(option_some_empty_str: Some(""));
1080
1081 value!(unit: ());
1082 value!(unit_struct: Unit);
1083 value!(unit_struct_escaped: UnitEscaped);
1084
1085 value!(enum_unit: Enum::Unit => "<Unit/>");
1086 err!(enum_unit_escaped:
1087 BTreeMap::from([("$value", Enum::UnitEscaped)])
1088 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1089
1090 value!(newtype: Newtype(42) => "42");
1091 value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1092
1093 err!(seq:
1095 BTreeMap::from([("$value", vec![1, 2, 3])])
1096 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1097 value!(seq_empty: Vec::<usize>::new());
1098 err!(tuple:
1099 BTreeMap::from([("$value", ("<\"&'>", "with\t\n\r spaces", 3usize))])
1100 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1101 err!(tuple_struct:
1102 BTreeMap::from([("$value", Tuple("first", 42))])
1103 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1104 value!(enum_tuple: Enum::Tuple("first", 42)
1105 => "<Tuple>first</Tuple>\
1106 <Tuple>42</Tuple>");
1107
1108 err!(map:
1111 BTreeMap::from([("$value", BTreeMap::from([("_1", 2), ("_3", 4)]))])
1112 => Unsupported("serialization of map types is not supported in `$value` field"));
1113 value!(struct_:
1114 Struct { key: "answer", val: (42, 42) }
1115 => "<Struct>\
1116 <key>answer</key>\
1117 <val>42</val>\
1118 <val>42</val>\
1119 </Struct>");
1120 value!(enum_struct:
1121 Enum::Struct { key: "answer", val: (42, 42) }
1122 => "<Struct>\
1123 <key>answer</key>\
1124 <val>42</val>\
1125 <val>42</val>\
1126 </Struct>");
1127 }
1128
1129 mod struct_ {
1131 use super::*;
1132 use pretty_assertions::assert_eq;
1133
1134 macro_rules! value {
1135 ($name:ident: $data:expr => $expected:literal) => {
1136 serialize_as!($name:
1137 Value {
1138 before: "answer",
1139 content: $data,
1140 after: "answer",
1141 }
1142 => concat!(
1143 "<root><before>answer</before>",
1144 $expected,
1145 "<after>answer</after></root>",
1146 ));
1147 };
1148 }
1149
1150 value!(false_: false => "false");
1151 value!(true_: true => "true");
1152
1153 value!(i8_: -42i8 => "-42");
1154 value!(i16_: -4200i16 => "-4200");
1155 value!(i32_: -42000000i32 => "-42000000");
1156 value!(i64_: -42000000000000i64 => "-42000000000000");
1157 value!(isize_: -42000000isize => "-42000000");
1158
1159 value!(u8_: 42u8 => "42");
1160 value!(u16_: 4200u16 => "4200");
1161 value!(u32_: 42000000u32 => "42000000");
1162 value!(u64_: 42000000000000u64 => "42000000000000");
1163 value!(usize_: 42000000usize => "42000000");
1164
1165 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1166 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1167
1168 value!(f32_: 4.2f32 => "4.2");
1169 value!(f64_: 4.2f64 => "4.2");
1170
1171 value!(char_non_escaped: 'h' => "h");
1172 value!(char_lt: '<' => "<");
1173 value!(char_gt: '>' => ">");
1174 value!(char_amp: '&' => "&");
1175 value!(char_apos: '\'' => "'");
1176 value!(char_quot: '"' => """);
1177 value!(char_space: ' ' => " ");
1178
1179 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1180 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1181
1182 err!(bytes:
1183 Value {
1184 before: "answer",
1185 content: Bytes(b"<\"escaped & bytes'>"),
1186 after: "answer",
1187 }
1188 => Unsupported("`serialize_bytes` not supported yet"));
1189
1190 value!(option_none: Option::<&str>::None => "");
1191 value!(option_some: Some("non-escaped string") => "non-escaped string");
1192 value!(option_some_empty_str: Some("") => "");
1193
1194 value!(unit: () => "");
1195 value!(unit_struct: Unit => "");
1196 value!(unit_struct_escaped: UnitEscaped => "");
1197
1198 value!(enum_unit: Enum::Unit => "<Unit/>");
1199 err!(enum_unit_escaped:
1200 Value {
1201 before: "answer",
1202 content: Enum::UnitEscaped,
1203 after: "answer",
1204 }
1205 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1206
1207 value!(newtype: Newtype(42) => "42");
1208 value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1209
1210 err!(seq:
1212 Value {
1213 before: "answer",
1214 content: vec![1, 2, 3],
1215 after: "answer",
1216 }
1217 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1218 value!(seq_empty: Vec::<usize>::new() => "");
1219 err!(tuple:
1220 Value {
1221 before: "answer",
1222 content: ("<\"&'>", "with\t\n\r spaces", 3usize),
1223 after: "answer",
1224 }
1225 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1226 err!(tuple_struct:
1227 Value {
1228 before: "answer",
1229 content: Tuple("first", 42),
1230 after: "answer",
1231 }
1232 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1233 value!(enum_tuple: Enum::Tuple("first", 42)
1234 => "<Tuple>first</Tuple>\
1235 <Tuple>42</Tuple>");
1236
1237 err!(map:
1240 Value {
1241 before: "answer",
1242 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1243 after: "answer",
1244 }
1245 => Unsupported("serialization of map types is not supported in `$value` field"));
1246 value!(struct_:
1247 Struct { key: "answer", val: (42, 42) }
1248 => "<Struct>\
1249 <key>answer</key>\
1250 <val>42</val>\
1251 <val>42</val>\
1252 </Struct>");
1253 value!(enum_struct:
1254 Enum::Struct { key: "answer", val: (42, 42) }
1255 => "<Struct>\
1256 <key>answer</key>\
1257 <val>42</val>\
1258 <val>42</val>\
1259 </Struct>");
1260 }
1261 }
1262
1263 mod attributes {
1264 use super::*;
1265 use pretty_assertions::assert_eq;
1266
1267 serialize_as!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
1268 => r#"<root key1="1" key2="2"/>"#);
1269 serialize_as!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
1270 => r#"<root key1="1"><key2>2</key2></root>"#);
1271
1272 serialize_as!(struct_: Attributes { key: "answer", val: (42, 42) }
1273 => r#"<root key="answer" val="42 42"/>"#);
1274 serialize_as!(struct_before: AttributesBefore { key: "answer", val: 42 }
1275 => r#"<root key="answer"><val>42</val></root>"#);
1276 serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
1277 => r#"<root val="42"><key>answer</key></root>"#);
1278
1279 err!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
1280 => Unsupported("cannot serialize enum struct variant `Enum::Attributes`"));
1281
1282 mod optional {
1284 use super::*;
1285 use pretty_assertions::assert_eq;
1286
1287 serialize_as!(none:
1288 OptionalAttributes { a: None, b: None }
1289 => r#"<root a=""/>"#);
1290 serialize_as!(some_empty_str:
1291 OptionalAttributes {
1292 a: Some(""),
1293 b: Some(""),
1294 }
1295 => r#"<root a="" b=""/>"#);
1296 serialize_as!(some_non_empty:
1297 OptionalAttributes {
1298 a: Some("1"),
1299 b: Some("2"),
1300 }
1301 => r#"<root a="1" b="2"/>"#);
1302 }
1303 }
1304
1305 mod optional {
1307 use super::*;
1308 use pretty_assertions::assert_eq;
1309
1310 serialize_as!(none:
1311 OptionalElements { a: None, b: None }
1312 => "<root>\
1313 <a/>\
1314 </root>");
1315 serialize_as!(some_empty_str:
1316 OptionalElements {
1317 a: Some(""),
1318 b: Some(""),
1319 }
1320 => "<root>\
1321 <a/>\
1322 <b/>\
1323 </root>");
1324 serialize_as!(some_non_empty:
1325 OptionalElements {
1326 a: Some("1"),
1327 b: Some("2"),
1328 }
1329 => "<root>\
1330 <a>1</a>\
1331 <b>2</b>\
1332 </root>");
1333 }
1334 }
1335
1336 mod with_indent {
1337 use super::*;
1338 use crate::se::content::tests::Struct;
1339 use crate::writer::Indentation;
1340 use pretty_assertions::assert_eq;
1341
1342 macro_rules! serialize_as {
1345 ($name:ident: $data:expr => $expected:expr) => {
1346 #[test]
1347 fn $name() {
1348 let mut buffer = String::new();
1349 let ser = ElementSerializer {
1350 ser: ContentSerializer {
1351 writer: &mut buffer,
1352 level: QuoteLevel::Full,
1353 indent: Indent::Owned(Indentation::new(b' ', 2)),
1354 write_indent: false,
1355 text_format: TextFormat::Text,
1356 allow_primitive: true,
1357 empty_element_handling: EmptyElementHandling::SelfClosed,
1358 },
1359 key: XmlName("root"),
1360 };
1361
1362 let result = $data.serialize(ser).unwrap();
1363 assert_eq!(buffer, $expected);
1364 assert_eq!(result, WriteResult::Element);
1365 }
1366 };
1367 }
1368
1369 macro_rules! err {
1372 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
1373 #[test]
1374 fn $name() {
1375 let mut buffer = String::new();
1376 let ser = ElementSerializer {
1377 ser: ContentSerializer {
1378 writer: &mut buffer,
1379 level: QuoteLevel::Full,
1380 indent: Indent::Owned(Indentation::new(b' ', 2)),
1381 write_indent: false,
1382 text_format: TextFormat::Text,
1383 allow_primitive: true,
1384 empty_element_handling: EmptyElementHandling::SelfClosed,
1385 },
1386 key: XmlName("root"),
1387 };
1388
1389 match $data.serialize(ser).unwrap_err() {
1390 SeError::$kind(e) => assert_eq!(e, $reason),
1391 e => panic!(
1392 "Expected `Err({}({}))`, but got `{:?}`",
1393 stringify!($kind),
1394 $reason,
1395 e
1396 ),
1397 }
1398 }
1401 };
1402 }
1403
1404 serialize_as!(false_: false => "<root>false</root>");
1405 serialize_as!(true_: true => "<root>true</root>");
1406
1407 serialize_as!(i8_: -42i8 => "<root>-42</root>");
1408 serialize_as!(i16_: -4200i16 => "<root>-4200</root>");
1409 serialize_as!(i32_: -42000000i32 => "<root>-42000000</root>");
1410 serialize_as!(i64_: -42000000000000i64 => "<root>-42000000000000</root>");
1411 serialize_as!(isize_: -42000000isize => "<root>-42000000</root>");
1412
1413 serialize_as!(u8_: 42u8 => "<root>42</root>");
1414 serialize_as!(u16_: 4200u16 => "<root>4200</root>");
1415 serialize_as!(u32_: 42000000u32 => "<root>42000000</root>");
1416 serialize_as!(u64_: 42000000000000u64 => "<root>42000000000000</root>");
1417 serialize_as!(usize_: 42000000usize => "<root>42000000</root>");
1418
1419 serialize_as!(i128_: -420000000000000000000000000000i128 => "<root>-420000000000000000000000000000</root>");
1420 serialize_as!(u128_: 420000000000000000000000000000u128 => "<root>420000000000000000000000000000</root>");
1421
1422 serialize_as!(f32_: 4.2f32 => "<root>4.2</root>");
1423 serialize_as!(f64_: 4.2f64 => "<root>4.2</root>");
1424
1425 serialize_as!(char_non_escaped: 'h' => "<root>h</root>");
1426 serialize_as!(char_lt: '<' => "<root><</root>");
1427 serialize_as!(char_gt: '>' => "<root>></root>");
1428 serialize_as!(char_amp: '&' => "<root>&</root>");
1429 serialize_as!(char_apos: '\'' => "<root>'</root>");
1430 serialize_as!(char_quot: '"' => "<root>"</root>");
1431 serialize_as!(char_space: ' ' => "<root> </root>");
1432
1433 serialize_as!(str_non_escaped: "non-escaped string" => "<root>non-escaped string</root>");
1434 serialize_as!(str_escaped: "<\"escaped & string'>" => "<root><"escaped & string'></root>");
1435
1436 err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
1437
1438 serialize_as!(option_none: Option::<&str>::None => "<root/>");
1439 serialize_as!(option_some: Some("non-escaped string") => "<root>non-escaped string</root>");
1440 serialize_as!(option_some_empty: Some("") => "<root/>");
1441
1442 serialize_as!(unit: () => "<root/>");
1443 serialize_as!(unit_struct: Unit => "<root/>");
1444 serialize_as!(unit_struct_escaped: UnitEscaped => "<root/>");
1445
1446 serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
1447 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root><"&'></root>");
1448
1449 serialize_as!(newtype: Newtype(42) => "<root>42</root>");
1450 err!(enum_newtype: Enum::Newtype(42)
1451 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype`"));
1452
1453 serialize_as!(seq: vec![1, 2, 3]
1454 => "<root>1</root>\n\
1455 <root>2</root>\n\
1456 <root>3</root>");
1457 serialize_as!(seq_empty: Vec::<usize>::new() => "");
1458 serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1459 => "<root><"&'></root>\n\
1460 <root>with\t\n\r spaces</root>\n\
1461 <root>3</root>");
1462 serialize_as!(tuple_struct: Tuple("first", 42)
1463 => "<root>first</root>\n\
1464 <root>42</root>");
1465 err!(enum_tuple: Enum::Tuple("first", 42)
1466 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple`"));
1467
1468 serialize_as!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
1469 => "<root>\n \
1470 <_1>2</_1>\n \
1471 <_3>4</_3>\n\
1472 </root>");
1473 serialize_as!(struct_: Struct { key: "answer", val: (42, 42) }
1474 => "<root>\n \
1475 <key>answer</key>\n \
1476 <val>42</val>\n \
1477 <val>42</val>\n\
1478 </root>");
1479 err!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
1480 => Unsupported("cannot serialize enum struct variant `Enum::Struct`"));
1481
1482 mod text_field {
1485 use super::*;
1486
1487 mod map {
1489 use super::*;
1490 use pretty_assertions::assert_eq;
1491
1492 macro_rules! text {
1493 ($name:ident: $data:expr) => {
1494 serialize_as!($name:
1495 BTreeMap::from([("$text", $data)])
1497 => "<root/>");
1498 };
1499 ($name:ident: $data:expr => $expected:literal) => {
1500 serialize_as!($name:
1501 BTreeMap::from([("$text", $data)])
1503 => concat!("<root>", $expected,"</root>"));
1504 };
1505 }
1506
1507 text!(false_: false => "false");
1508 text!(true_: true => "true");
1509
1510 text!(i8_: -42i8 => "-42");
1511 text!(i16_: -4200i16 => "-4200");
1512 text!(i32_: -42000000i32 => "-42000000");
1513 text!(i64_: -42000000000000i64 => "-42000000000000");
1514 text!(isize_: -42000000isize => "-42000000");
1515
1516 text!(u8_: 42u8 => "42");
1517 text!(u16_: 4200u16 => "4200");
1518 text!(u32_: 42000000u32 => "42000000");
1519 text!(u64_: 42000000000000u64 => "42000000000000");
1520 text!(usize_: 42000000usize => "42000000");
1521
1522 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1523 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1524
1525 text!(f32_: 4.2f32 => "4.2");
1526 text!(f64_: 4.2f64 => "4.2");
1527
1528 text!(char_non_escaped: 'h' => "h");
1529 text!(char_lt: '<' => "<");
1530 text!(char_gt: '>' => ">");
1531 text!(char_amp: '&' => "&");
1532 text!(char_apos: '\'' => "'");
1533 text!(char_quot: '"' => """);
1534 text!(char_space: ' ' => " ");
1535
1536 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
1537 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1538
1539 err!(bytes:
1540 Text {
1541 before: "answer",
1542 content: Bytes(b"<\"escaped & bytes'>"),
1543 after: "answer",
1544 }
1545 => Unsupported("`serialize_bytes` not supported yet"));
1546
1547 text!(option_none: Option::<&str>::None);
1548 text!(option_some: Some("non-escaped string") => "non-escaped string");
1549 text!(option_some_empty_str: Some(""));
1550
1551 text!(unit: ());
1552 text!(unit_struct: Unit);
1553 text!(unit_struct_escaped: UnitEscaped);
1554
1555 text!(enum_unit: Enum::Unit => "Unit");
1556 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
1557
1558 text!(newtype: Newtype(42) => "42");
1559 err!(enum_newtype:
1561 Text {
1562 before: "answer",
1563 content: Enum::Newtype(42),
1564 after: "answer",
1565 }
1566 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
1567
1568 text!(seq: vec![1, 2, 3] => "1 2 3");
1570 text!(seq_empty: Vec::<usize>::new());
1571 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1572 => "<"&'> \
1573 with	  spaces \
1574 3");
1575 text!(tuple_struct: Tuple("first", 42) => "first 42");
1576 err!(enum_tuple:
1578 Text {
1579 before: "answer",
1580 content: Enum::Tuple("first", 42),
1581 after: "answer",
1582 }
1583 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
1584
1585 err!(map:
1587 Text {
1588 before: "answer",
1589 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1590 after: "answer",
1591 }
1592 => Unsupported("cannot serialize map as text content value"));
1593 err!(struct_:
1594 Text {
1595 before: "answer",
1596 content: Struct { key: "answer", val: (42, 42) },
1597 after: "answer",
1598 }
1599 => Unsupported("cannot serialize struct `Struct` as text content value"));
1600 err!(enum_struct:
1601 Text {
1602 before: "answer",
1603 content: Enum::Struct { key: "answer", val: (42, 42) },
1604 after: "answer",
1605 }
1606 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1607 }
1608
1609 mod struct_ {
1611 use super::*;
1612 use pretty_assertions::assert_eq;
1613
1614 macro_rules! text {
1615 ($name:ident: $data:expr => $expected:literal) => {
1616 serialize_as!($name:
1617 Text {
1619 before: "answer",
1620 content: $data,
1621 after: "answer",
1622 }
1623 => concat!(
1624 "<root>\n <before>answer</before>",
1625 $expected,
1626 "<after>answer</after>\n</root>",
1627 ));
1628 };
1629 }
1630
1631 text!(false_: false => "false");
1632 text!(true_: true => "true");
1633
1634 text!(i8_: -42i8 => "-42");
1635 text!(i16_: -4200i16 => "-4200");
1636 text!(i32_: -42000000i32 => "-42000000");
1637 text!(i64_: -42000000000000i64 => "-42000000000000");
1638 text!(isize_: -42000000isize => "-42000000");
1639
1640 text!(u8_: 42u8 => "42");
1641 text!(u16_: 4200u16 => "4200");
1642 text!(u32_: 42000000u32 => "42000000");
1643 text!(u64_: 42000000000000u64 => "42000000000000");
1644 text!(usize_: 42000000usize => "42000000");
1645
1646 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1647 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1648
1649 text!(f32_: 4.2f32 => "4.2");
1650 text!(f64_: 4.2f64 => "4.2");
1651
1652 text!(char_non_escaped: 'h' => "h");
1653 text!(char_lt: '<' => "<");
1654 text!(char_gt: '>' => ">");
1655 text!(char_amp: '&' => "&");
1656 text!(char_apos: '\'' => "'");
1657 text!(char_quot: '"' => """);
1658 text!(char_space: ' ' => " ");
1659
1660 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
1661 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1662
1663 err!(bytes:
1664 Text {
1665 before: "answer",
1666 content: Bytes(b"<\"escaped & bytes'>"),
1667 after: "answer",
1668 }
1669 => Unsupported("`serialize_bytes` not supported yet"));
1670
1671 text!(option_none: Option::<&str>::None => "");
1672 text!(option_some: Some("non-escaped string") => "non-escaped string");
1673 text!(option_some_empty_str: Some("") => "");
1674
1675 text!(unit: () => "");
1676 text!(unit_struct: Unit => "");
1677 text!(unit_struct_escaped: UnitEscaped => "");
1678
1679 text!(enum_unit: Enum::Unit => "Unit");
1680 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
1681
1682 text!(newtype: Newtype(42) => "42");
1683 err!(enum_newtype:
1685 Text {
1686 before: "answer",
1687 content: Enum::Newtype(42),
1688 after: "answer",
1689 }
1690 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
1691
1692 text!(seq: vec![1, 2, 3] => "1 2 3");
1694 text!(seq_empty: Vec::<usize>::new() => "");
1695 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1696 => "<"&'> \
1697 with	  spaces \
1698 3");
1699 text!(tuple_struct: Tuple("first", 42) => "first 42");
1700 err!(enum_tuple:
1702 Text {
1703 before: "answer",
1704 content: Enum::Tuple("first", 42),
1705 after: "answer",
1706 }
1707 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
1708
1709 err!(map:
1711 Text {
1712 before: "answer",
1713 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1714 after: "answer",
1715 }
1716 => Unsupported("cannot serialize map as text content value"));
1717 err!(struct_:
1718 Text {
1719 before: "answer",
1720 content: Struct { key: "answer", val: (42, 42) },
1721 after: "answer",
1722 }
1723 => Unsupported("cannot serialize struct `Struct` as text content value"));
1724 err!(enum_struct:
1725 Text {
1726 before: "answer",
1727 content: Enum::Struct { key: "answer", val: (42, 42) },
1728 after: "answer",
1729 }
1730 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1731 }
1732 }
1733
1734 mod value_field {
1738 use super::*;
1739
1740 mod map {
1742 use super::*;
1743 use pretty_assertions::assert_eq;
1744
1745 macro_rules! value {
1746 ($name:ident: $data:expr) => {
1747 serialize_as!($name:
1748 BTreeMap::from([("$value", $data)])
1750 => "<root/>");
1751 };
1752 ($name:ident: $data:expr => $expected:literal) => {
1753 serialize_as!($name:
1754 BTreeMap::from([("$value", $data)])
1756 => concat!("<root>", $expected,"</root>"));
1757 };
1758 }
1759
1760 value!(false_: false => "false");
1761 value!(true_: true => "true");
1762
1763 value!(i8_: -42i8 => "-42");
1764 value!(i16_: -4200i16 => "-4200");
1765 value!(i32_: -42000000i32 => "-42000000");
1766 value!(i64_: -42000000000000i64 => "-42000000000000");
1767 value!(isize_: -42000000isize => "-42000000");
1768
1769 value!(u8_: 42u8 => "42");
1770 value!(u16_: 4200u16 => "4200");
1771 value!(u32_: 42000000u32 => "42000000");
1772 value!(u64_: 42000000000000u64 => "42000000000000");
1773 value!(usize_: 42000000usize => "42000000");
1774
1775 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1776 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1777
1778 value!(f32_: 4.2f32 => "4.2");
1779 value!(f64_: 4.2f64 => "4.2");
1780
1781 value!(char_non_escaped: 'h' => "h");
1782 value!(char_lt: '<' => "<");
1783 value!(char_gt: '>' => ">");
1784 value!(char_amp: '&' => "&");
1785 value!(char_apos: '\'' => "'");
1786 value!(char_quot: '"' => """);
1787 value!(char_space: ' ' => " ");
1788
1789 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1790 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1791
1792 err!(bytes:
1793 BTreeMap::from([("$value", Bytes(b"<\"escaped & bytes'>"))])
1794 => Unsupported("`serialize_bytes` not supported yet"));
1795
1796 value!(option_none: Option::<&str>::None);
1797 value!(option_some: Some("non-escaped string") => "non-escaped string");
1798 value!(option_some_empty_str: Some(""));
1799
1800 value!(unit: ());
1801 value!(unit_struct: Unit);
1802 value!(unit_struct_escaped: UnitEscaped);
1803
1804 value!(enum_unit: Enum::Unit => "\n <Unit/>\n");
1805 err!(enum_unit_escaped:
1806 BTreeMap::from([("$value", Enum::UnitEscaped)])
1807 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1808
1809 value!(newtype: Newtype(42) => "42");
1810 value!(enum_newtype: Enum::Newtype(42) => "\n <Newtype>42</Newtype>\n");
1811
1812 err!(seq:
1813 BTreeMap::from([("$value", vec![1, 2, 3])])
1814 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1815 value!(seq_empty: Vec::<usize>::new());
1816 err!(tuple:
1817 BTreeMap::from([("$value", ("<\"&'>", "with\t\n\r spaces", 3usize))])
1818 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1819 err!(tuple_struct:
1820 BTreeMap::from([("$value", Tuple("first", 42))])
1821 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1822 value!(enum_tuple: Enum::Tuple("first", 42)
1823 => "\n \
1824 <Tuple>first</Tuple>\n \
1825 <Tuple>42</Tuple>\n");
1826
1827 err!(map:
1830 BTreeMap::from([("$value", BTreeMap::from([("_1", 2), ("_3", 4)]))])
1831 => Unsupported("serialization of map types is not supported in `$value` field"));
1832 value!(struct_:
1833 Struct { key: "answer", val: (42, 42) }
1834 => "\n \
1835 <Struct>\n \
1836 <key>answer</key>\n \
1837 <val>42</val>\n \
1838 <val>42</val>\n \
1839 </Struct>\n");
1840 value!(enum_struct:
1841 Enum::Struct { key: "answer", val: (42, 42) }
1842 => "\n \
1843 <Struct>\n \
1844 <key>answer</key>\n \
1845 <val>42</val>\n \
1846 <val>42</val>\n \
1847 </Struct>\n");
1848 }
1849
1850 mod struct_ {
1852 use super::*;
1853 use pretty_assertions::assert_eq;
1854
1855 macro_rules! value {
1856 ($name:ident: $data:expr => $expected:literal) => {
1857 serialize_as!($name:
1858 Value {
1860 before: "answer",
1861 content: $data,
1862 after: "answer",
1863 }
1864 => concat!(
1865 "<root>\n <before>answer</before>",
1866 $expected,
1867 "<after>answer</after>\n</root>",
1868 ));
1869 };
1870 }
1871
1872 value!(false_: false => "false");
1873 value!(true_: true => "true");
1874
1875 value!(i8_: -42i8 => "-42");
1876 value!(i16_: -4200i16 => "-4200");
1877 value!(i32_: -42000000i32 => "-42000000");
1878 value!(i64_: -42000000000000i64 => "-42000000000000");
1879 value!(isize_: -42000000isize => "-42000000");
1880
1881 value!(u8_: 42u8 => "42");
1882 value!(u16_: 4200u16 => "4200");
1883 value!(u32_: 42000000u32 => "42000000");
1884 value!(u64_: 42000000000000u64 => "42000000000000");
1885 value!(usize_: 42000000usize => "42000000");
1886
1887 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1888 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1889
1890 value!(f32_: 4.2f32 => "4.2");
1891 value!(f64_: 4.2f64 => "4.2");
1892
1893 value!(char_non_escaped: 'h' => "h");
1894 value!(char_lt: '<' => "<");
1895 value!(char_gt: '>' => ">");
1896 value!(char_amp: '&' => "&");
1897 value!(char_apos: '\'' => "'");
1898 value!(char_quot: '"' => """);
1899 value!(char_space: ' ' => " ");
1900
1901 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1902 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1903
1904 err!(bytes:
1905 Value {
1906 before: "answer",
1907 content: Bytes(b"<\"escaped & bytes'>"),
1908 after: "answer",
1909 }
1910 => Unsupported("`serialize_bytes` not supported yet"));
1911
1912 value!(option_none: Option::<&str>::None => "");
1913 value!(option_some: Some("non-escaped string") => "non-escaped string");
1914 value!(option_some_empty_str: Some("") => "");
1915
1916 value!(unit: () => "\n ");
1917 value!(unit_struct: Unit => "\n ");
1918 value!(unit_struct_escaped: UnitEscaped => "\n ");
1919
1920 value!(enum_unit: Enum::Unit => "\n <Unit/>\n ");
1921 err!(enum_unit_escaped:
1922 Value {
1923 before: "answer",
1924 content: Enum::UnitEscaped,
1925 after: "answer",
1926 }
1927 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1928
1929 value!(newtype: Newtype(42) => "42");
1930 value!(enum_newtype: Enum::Newtype(42) => "\n <Newtype>42</Newtype>\n ");
1931
1932 err!(seq:
1933 Value {
1934 before: "answer",
1935 content: vec![1, 2, 3],
1936 after: "answer",
1937 }
1938 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1939 value!(seq_empty: Vec::<usize>::new() => "");
1940 err!(tuple:
1941 Value {
1942 before: "answer",
1943 content: ("<\"&'>", "with\t\n\r spaces", 3usize),
1944 after: "answer",
1945 }
1946 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1947 err!(tuple_struct:
1948 Value {
1949 before: "answer",
1950 content: Tuple("first", 42),
1951 after: "answer",
1952 }
1953 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1954 value!(enum_tuple: Enum::Tuple("first", 42)
1955 => "\n \
1956 <Tuple>first</Tuple>\n \
1957 <Tuple>42</Tuple>\n ");
1958
1959 err!(map:
1962 Value {
1963 before: "answer",
1964 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1965 after: "answer",
1966 }
1967 => Unsupported("serialization of map types is not supported in `$value` field"));
1968 value!(struct_:
1969 Value {
1970 before: "answer",
1971 content: Struct { key: "answer", val: (42, 42) },
1972 after: "answer",
1973 }
1974 => "\n \
1975 <Value>\n \
1976 <before>answer</before>\n \
1977 <Struct>\n \
1978 <key>answer</key>\n \
1979 <val>42</val>\n \
1980 <val>42</val>\n \
1981 </Struct>\n \
1982 <after>answer</after>\n \
1983 </Value>\n ");
1984 value!(enum_struct:
1985 Enum::Struct { key: "answer", val: (42, 42) }
1986 => "\n \
1987 <Struct>\n \
1988 <key>answer</key>\n \
1989 <val>42</val>\n \
1990 <val>42</val>\n \
1991 </Struct>\n ");
1992 }
1993 }
1994
1995 mod attributes {
1996 use super::*;
1997 use pretty_assertions::assert_eq;
1998
1999 serialize_as!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
2000 => r#"<root key1="1" key2="2"/>"#);
2001 serialize_as!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
2002 => "<root key1=\"1\">\n \
2003 <key2>2</key2>\n\
2004 </root>");
2005
2006 serialize_as!(struct_: Attributes { key: "answer", val: (42, 42) }
2007 => r#"<root key="answer" val="42 42"/>"#);
2008 serialize_as!(struct_before: AttributesBefore { key: "answer", val: 42 }
2009 => "<root key=\"answer\">\n \
2010 <val>42</val>\n\
2011 </root>");
2012 serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
2013 => "<root val=\"42\">\n \
2014 <key>answer</key>\n\
2015 </root>");
2016
2017 err!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
2018 => Unsupported("cannot serialize enum struct variant `Enum::Attributes`"));
2019
2020 mod optional {
2022 use super::*;
2023 use pretty_assertions::assert_eq;
2024
2025 serialize_as!(none:
2026 OptionalAttributes { a: None, b: None }
2027 => r#"<root a=""/>"#);
2028 serialize_as!(some_empty_str:
2029 OptionalAttributes {
2030 a: Some(""),
2031 b: Some("")
2032 }
2033 => r#"<root a="" b=""/>"#);
2034 serialize_as!(some_non_empty:
2035 OptionalAttributes {
2036 a: Some("a"),
2037 b: Some("b")
2038 }
2039 => r#"<root a="a" b="b"/>"#);
2040 }
2041 }
2042
2043 mod optional {
2045 use super::*;
2046 use pretty_assertions::assert_eq;
2047
2048 serialize_as!(none:
2049 OptionalElements { a: None, b: None }
2050 => "<root>\n \
2051 <a/>\n\
2052 </root>");
2053 serialize_as!(some_empty_str:
2054 OptionalElements {
2055 a: Some(""),
2056 b: Some("")
2057 }
2058 => "<root>\n \
2059 <a/>\n \
2060 <b/>\n\
2061 </root>");
2062 serialize_as!(some_non_empty:
2063 OptionalElements {
2064 a: Some("a"),
2065 b: Some("b")
2066 }
2067 => "<root>\n \
2068 <a>a</a>\n \
2069 <b>b</b>\n\
2070 </root>");
2071 }
2072 }
2073
2074 mod expand_empty_elements {
2075 use super::*;
2076 use pretty_assertions::assert_eq;
2077
2078 macro_rules! serialize_as {
2080 ($name:ident: $data:expr => $expected:expr) => {
2081 #[test]
2082 fn $name() {
2083 let mut buffer = String::new();
2084 let ser = ElementSerializer {
2085 ser: ContentSerializer {
2086 writer: &mut buffer,
2087 level: QuoteLevel::Full,
2088 indent: Indent::None,
2089 write_indent: false,
2090 text_format: TextFormat::Text,
2091 allow_primitive: true,
2092 empty_element_handling: EmptyElementHandling::Expanded,
2093 },
2094 key: XmlName("root"),
2095 };
2096
2097 let result = $data.serialize(ser).unwrap();
2098 assert_eq!(buffer, $expected);
2099 assert_eq!(result, WriteResult::Element);
2100 }
2101 };
2102 }
2103
2104 serialize_as!(option_some_empty: Some("") => "<root></root>");
2105 serialize_as!(option_some_empty_str: Some("") => "<root></root>");
2106
2107 serialize_as!(unit: () => "<root></root>");
2108 serialize_as!(unit_struct: Unit => "<root></root>");
2109 serialize_as!(unit_struct_escaped: UnitEscaped => "<root></root>");
2110
2111 serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
2112 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root><"&'></root>");
2113 }
2114}