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