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 self.ser.ser.writer.write_str("/>")?;
471 } else {
472 self.ser.ser.writer.write_char('>')?;
473 self.ser.ser.writer.write_str(&self.children)?;
474
475 self.ser.ser.indent.write_indent(&mut self.ser.ser.writer)?;
476
477 self.ser.ser.writer.write_str("</")?;
478 self.ser.ser.writer.write_str(self.ser.key.0)?;
479 self.ser.ser.writer.write_char('>')?;
480 }
481 Ok(())
482 }
483}
484
485impl<'w, 'k, W: Write> SerializeStructVariant for Struct<'w, 'k, W> {
486 type Ok = ();
487 type Error = DeError;
488
489 #[inline]
490 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
491 where
492 T: ?Sized + Serialize,
493 {
494 SerializeStruct::serialize_field(self, key, value)
495 }
496
497 #[inline]
498 fn end(self) -> Result<Self::Ok, Self::Error> {
499 SerializeStruct::end(self)
500 }
501}
502
503pub struct Map<'w, 'k, W: Write> {
506 ser: Struct<'w, 'k, W>,
507 key: Option<String>,
510}
511
512impl<'w, 'k, W: Write> Map<'w, 'k, W> {
513 fn make_key<T>(&mut self, key: &T) -> Result<String, DeError>
514 where
515 T: ?Sized + Serialize,
516 {
517 key.serialize(QNameSerializer {
518 writer: String::new(),
519 })
520 }
521}
522
523impl<'w, 'k, W: Write> SerializeMap for Map<'w, 'k, W> {
524 type Ok = ();
525 type Error = DeError;
526
527 fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
528 where
529 T: ?Sized + Serialize,
530 {
531 if let Some(_) = self.key.take() {
532 return Err(DeError::Custom(
533 "calling `serialize_key` twice without `serialize_value`".to_string(),
534 ));
535 }
536 self.key = Some(self.make_key(key)?);
537 Ok(())
538 }
539
540 fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
541 where
542 T: ?Sized + Serialize,
543 {
544 if let Some(key) = self.key.take() {
545 return self.ser.write_field(&key, value);
546 }
547 Err(DeError::Custom(
548 "calling `serialize_value` without call of `serialize_key`".to_string(),
549 ))
550 }
551
552 fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
553 where
554 K: ?Sized + Serialize,
555 V: ?Sized + Serialize,
556 {
557 let key = self.make_key(key)?;
558 self.ser.write_field(&key, value)
559 }
560
561 fn end(mut self) -> Result<Self::Ok, Self::Error> {
562 if let Some(key) = self.key.take() {
563 return Err(DeError::Custom(format!(
564 "calling `end` without call of `serialize_value` for key `{key}`"
565 )));
566 }
567 SerializeStruct::end(self.ser)
568 }
569}
570
571#[cfg(test)]
574mod tests {
575 use super::*;
576 use crate::se::content::tests::*;
577 use crate::se::{Indent, QuoteLevel};
578 use crate::utils::Bytes;
579 use serde::Serialize;
580 use std::collections::BTreeMap;
581
582 #[derive(Debug, Serialize, PartialEq)]
583 struct OptionalElements {
584 a: Option<&'static str>,
585
586 #[serde(skip_serializing_if = "Option::is_none")]
587 b: Option<&'static str>,
588 }
589 #[derive(Debug, Serialize, PartialEq)]
590 struct OptionalAttributes {
591 #[serde(rename = "@a")]
592 a: Option<&'static str>,
593
594 #[serde(rename = "@b")]
595 #[serde(skip_serializing_if = "Option::is_none")]
596 b: Option<&'static str>,
597 }
598
599 mod without_indent {
600 use super::*;
601 use crate::se::content::tests::Struct;
602 use pretty_assertions::assert_eq;
603
604 macro_rules! serialize_as {
606 ($name:ident: $data:expr => $expected:expr) => {
607 #[test]
608 fn $name() {
609 let mut buffer = String::new();
610 let ser = ElementSerializer {
611 ser: ContentSerializer {
612 writer: &mut buffer,
613 level: QuoteLevel::Full,
614 indent: Indent::None,
615 write_indent: false,
616 expand_empty_elements: false,
617 },
618 key: XmlName("root"),
619 };
620
621 $data.serialize(ser).unwrap();
622 assert_eq!(buffer, $expected);
623 }
624 };
625 }
626
627 macro_rules! err {
630 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
631 #[test]
632 fn $name() {
633 let mut buffer = String::new();
634 let ser = ElementSerializer {
635 ser: ContentSerializer {
636 writer: &mut buffer,
637 level: QuoteLevel::Full,
638 indent: Indent::None,
639 write_indent: false,
640 expand_empty_elements: false,
641 },
642 key: XmlName("root"),
643 };
644
645 match $data.serialize(ser).unwrap_err() {
646 DeError::$kind(e) => assert_eq!(e, $reason),
647 e => panic!(
648 "Expected `{}({})`, found `{:?}`",
649 stringify!($kind),
650 $reason,
651 e
652 ),
653 }
654 }
657 };
658 }
659
660 serialize_as!(false_: false => "<root>false</root>");
661 serialize_as!(true_: true => "<root>true</root>");
662
663 serialize_as!(i8_: -42i8 => "<root>-42</root>");
664 serialize_as!(i16_: -4200i16 => "<root>-4200</root>");
665 serialize_as!(i32_: -42000000i32 => "<root>-42000000</root>");
666 serialize_as!(i64_: -42000000000000i64 => "<root>-42000000000000</root>");
667 serialize_as!(isize_: -42000000000000isize => "<root>-42000000000000</root>");
668
669 serialize_as!(u8_: 42u8 => "<root>42</root>");
670 serialize_as!(u16_: 4200u16 => "<root>4200</root>");
671 serialize_as!(u32_: 42000000u32 => "<root>42000000</root>");
672 serialize_as!(u64_: 42000000000000u64 => "<root>42000000000000</root>");
673 serialize_as!(usize_: 42000000000000usize => "<root>42000000000000</root>");
674
675 serde_if_integer128! {
676 serialize_as!(i128_: -420000000000000000000000000000i128 => "<root>-420000000000000000000000000000</root>");
677 serialize_as!(u128_: 420000000000000000000000000000u128 => "<root>420000000000000000000000000000</root>");
678 }
679
680 serialize_as!(f32_: 4.2f32 => "<root>4.2</root>");
681 serialize_as!(f64_: 4.2f64 => "<root>4.2</root>");
682
683 serialize_as!(char_non_escaped: 'h' => "<root>h</root>");
684 serialize_as!(char_lt: '<' => "<root><</root>");
685 serialize_as!(char_gt: '>' => "<root>></root>");
686 serialize_as!(char_amp: '&' => "<root>&</root>");
687 serialize_as!(char_apos: '\'' => "<root>'</root>");
688 serialize_as!(char_quot: '"' => "<root>"</root>");
689
690 serialize_as!(str_non_escaped: "non-escaped string" => "<root>non-escaped string</root>");
691 serialize_as!(str_escaped: "<\"escaped & string'>" => "<root><"escaped & string'></root>");
692
693 err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
694
695 serialize_as!(option_none: Option::<&str>::None => "<root/>");
696 serialize_as!(option_some: Some("non-escaped string") => "<root>non-escaped string</root>");
697 serialize_as!(option_some_empty_str: Some("") => "<root/>");
698
699 serialize_as!(unit: () => "<root/>");
700 serialize_as!(unit_struct: Unit => "<root/>");
701 serialize_as!(unit_struct_escaped: UnitEscaped => "<root/>");
702
703 serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
704 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root><"&'></root>");
705
706 serialize_as!(newtype: Newtype(42) => "<root>42</root>");
707 err!(enum_newtype: Enum::Newtype(42)
708 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype`"));
709
710 serialize_as!(seq: vec![1, 2, 3]
711 => "<root>1</root>\
712 <root>2</root>\
713 <root>3</root>");
714 serialize_as!(seq_empty: Vec::<usize>::new() => "");
715 serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
716 => "<root><"&'></root>\
717 <root>with\t\n\r spaces</root>\
718 <root>3</root>");
719 serialize_as!(tuple_struct: Tuple("first", 42)
720 => "<root>first</root>\
721 <root>42</root>");
722 err!(enum_tuple: Enum::Tuple("first", 42)
723 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple`"));
724
725 serialize_as!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
726 => "<root>\
727 <_1>2</_1>\
728 <_3>4</_3>\
729 </root>");
730 serialize_as!(struct_: Struct { key: "answer", val: (42, 42) }
731 => "<root>\
732 <key>answer</key>\
733 <val>42</val>\
734 <val>42</val>\
735 </root>");
736 err!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
737 => Unsupported("cannot serialize enum struct variant `Enum::Struct`"));
738
739 mod text_field {
742 use super::*;
743
744 mod map {
746 use super::*;
747 use pretty_assertions::assert_eq;
748
749 macro_rules! text {
750 ($name:ident: $data:expr) => {
751 serialize_as!($name:
752 BTreeMap::from([("$text", $data)])
753 => "<root/>");
754 };
755 ($name:ident: $data:expr => $expected:literal) => {
756 serialize_as!($name:
757 BTreeMap::from([("$text", $data)])
758 => concat!("<root>", $expected,"</root>"));
759 };
760 }
761
762 text!(false_: false => "false");
763 text!(true_: true => "true");
764
765 text!(i8_: -42i8 => "-42");
766 text!(i16_: -4200i16 => "-4200");
767 text!(i32_: -42000000i32 => "-42000000");
768 text!(i64_: -42000000000000i64 => "-42000000000000");
769 text!(isize_: -42000000000000isize => "-42000000000000");
770
771 text!(u8_: 42u8 => "42");
772 text!(u16_: 4200u16 => "4200");
773 text!(u32_: 42000000u32 => "42000000");
774 text!(u64_: 42000000000000u64 => "42000000000000");
775 text!(usize_: 42000000000000usize => "42000000000000");
776
777 serde_if_integer128! {
778 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
779 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
780 }
781
782 text!(f32_: 4.2f32 => "4.2");
783 text!(f64_: 4.2f64 => "4.2");
784
785 text!(char_non_escaped: 'h' => "h");
786 text!(char_lt: '<' => "<");
787 text!(char_gt: '>' => ">");
788 text!(char_amp: '&' => "&");
789 text!(char_apos: '\'' => "'");
790 text!(char_quot: '"' => """);
791 text!(char_space: ' ' => " ");
794
795 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
796 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
797
798 err!(bytes:
799 Text {
800 before: "answer",
801 content: Bytes(b"<\"escaped & bytes'>"),
802 after: "answer",
803 }
804 => Unsupported("`serialize_bytes` not supported yet"));
805
806 text!(option_none: Option::<&str>::None);
807 text!(option_some: Some("non-escaped string") => "non-escaped string");
808 text!(option_some_empty_str: Some(""));
809
810 text!(unit: ());
811 text!(unit_struct: Unit);
812 text!(unit_struct_escaped: UnitEscaped);
813
814 text!(enum_unit: Enum::Unit => "Unit");
815 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
816
817 text!(newtype: Newtype(42) => "42");
818 err!(enum_newtype:
820 Text {
821 before: "answer",
822 content: Enum::Newtype(42),
823 after: "answer",
824 }
825 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
826
827 text!(seq: vec![1, 2, 3] => "1 2 3");
829 text!(seq_empty: Vec::<usize>::new());
830 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
831 => "<"&'> \
832 with	  spaces \
833 3");
834 text!(tuple_struct: Tuple("first", 42) => "first 42");
835 err!(enum_tuple:
837 Text {
838 before: "answer",
839 content: Enum::Tuple("first", 42),
840 after: "answer",
841 }
842 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
843
844 err!(map:
846 Text {
847 before: "answer",
848 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
849 after: "answer",
850 }
851 => Unsupported("cannot serialize map as text content value"));
852 err!(struct_:
853 Text {
854 before: "answer",
855 content: Struct { key: "answer", val: (42, 42) },
856 after: "answer",
857 }
858 => Unsupported("cannot serialize struct `Struct` as text content value"));
859 err!(enum_struct:
860 Text {
861 before: "answer",
862 content: Enum::Struct { key: "answer", val: (42, 42) },
863 after: "answer",
864 }
865 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
866 }
867
868 mod struct_ {
870 use super::*;
871 use pretty_assertions::assert_eq;
872
873 macro_rules! text {
874 ($name:ident: $data:expr => $expected:literal) => {
875 serialize_as!($name:
876 Text {
877 before: "answer",
878 content: $data,
879 after: "answer",
880 }
881 => concat!(
882 "<root><before>answer</before>",
883 $expected,
884 "<after>answer</after></root>",
885 ));
886 };
887 }
888
889 text!(false_: false => "false");
890 text!(true_: true => "true");
891
892 text!(i8_: -42i8 => "-42");
893 text!(i16_: -4200i16 => "-4200");
894 text!(i32_: -42000000i32 => "-42000000");
895 text!(i64_: -42000000000000i64 => "-42000000000000");
896 text!(isize_: -42000000000000isize => "-42000000000000");
897
898 text!(u8_: 42u8 => "42");
899 text!(u16_: 4200u16 => "4200");
900 text!(u32_: 42000000u32 => "42000000");
901 text!(u64_: 42000000000000u64 => "42000000000000");
902 text!(usize_: 42000000000000usize => "42000000000000");
903
904 serde_if_integer128! {
905 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
906 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
907 }
908
909 text!(f32_: 4.2f32 => "4.2");
910 text!(f64_: 4.2f64 => "4.2");
911
912 text!(char_non_escaped: 'h' => "h");
913 text!(char_lt: '<' => "<");
914 text!(char_gt: '>' => ">");
915 text!(char_amp: '&' => "&");
916 text!(char_apos: '\'' => "'");
917 text!(char_quot: '"' => """);
918 text!(char_space: ' ' => " ");
921
922 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
923 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
924
925 err!(bytes:
926 Text {
927 before: "answer",
928 content: Bytes(b"<\"escaped & bytes'>"),
929 after: "answer",
930 }
931 => Unsupported("`serialize_bytes` not supported yet"));
932
933 text!(option_none: Option::<&str>::None => "");
934 text!(option_some: Some("non-escaped string") => "non-escaped string");
935 text!(option_some_empty_str: Some("") => "");
936
937 text!(unit: () => "");
938 text!(unit_struct: Unit => "");
939 text!(unit_struct_escaped: UnitEscaped => "");
940
941 text!(enum_unit: Enum::Unit => "Unit");
942 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
943
944 text!(newtype: Newtype(42) => "42");
945 err!(enum_newtype:
947 Text {
948 before: "answer",
949 content: Enum::Newtype(42),
950 after: "answer",
951 }
952 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
953
954 text!(seq: vec![1, 2, 3] => "1 2 3");
956 text!(seq_empty: Vec::<usize>::new() => "");
957 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
958 => "<"&'> \
959 with	  spaces \
960 3");
961 text!(tuple_struct: Tuple("first", 42) => "first 42");
962 err!(enum_tuple:
964 Text {
965 before: "answer",
966 content: Enum::Tuple("first", 42),
967 after: "answer",
968 }
969 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
970
971 err!(map:
973 Text {
974 before: "answer",
975 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
976 after: "answer",
977 }
978 => Unsupported("cannot serialize map as text content value"));
979 err!(struct_:
980 Text {
981 before: "answer",
982 content: Struct { key: "answer", val: (42, 42) },
983 after: "answer",
984 }
985 => Unsupported("cannot serialize struct `Struct` as text content value"));
986 err!(enum_struct:
987 Text {
988 before: "answer",
989 content: Enum::Struct { key: "answer", val: (42, 42) },
990 after: "answer",
991 }
992 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
993 }
994 }
995
996 mod value_field {
1000 use super::*;
1001
1002 mod map {
1004 use super::*;
1005 use pretty_assertions::assert_eq;
1006
1007 macro_rules! value {
1008 ($name:ident: $data:expr) => {
1009 serialize_as!($name:
1010 BTreeMap::from([("$value", $data)])
1011 => "<root/>");
1012 };
1013 ($name:ident: $data:expr => $expected:literal) => {
1014 serialize_as!($name:
1015 BTreeMap::from([("$value", $data)])
1016 => concat!("<root>", $expected,"</root>"));
1017 };
1018 }
1019
1020 value!(false_: false => "false");
1021 value!(true_: true => "true");
1022
1023 value!(i8_: -42i8 => "-42");
1024 value!(i16_: -4200i16 => "-4200");
1025 value!(i32_: -42000000i32 => "-42000000");
1026 value!(i64_: -42000000000000i64 => "-42000000000000");
1027 value!(isize_: -42000000000000isize => "-42000000000000");
1028
1029 value!(u8_: 42u8 => "42");
1030 value!(u16_: 4200u16 => "4200");
1031 value!(u32_: 42000000u32 => "42000000");
1032 value!(u64_: 42000000000000u64 => "42000000000000");
1033 value!(usize_: 42000000000000usize => "42000000000000");
1034
1035 serde_if_integer128! {
1036 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1037 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1038 }
1039
1040 value!(f32_: 4.2f32 => "4.2");
1041 value!(f64_: 4.2f64 => "4.2");
1042
1043 value!(char_non_escaped: 'h' => "h");
1044 value!(char_lt: '<' => "<");
1045 value!(char_gt: '>' => ">");
1046 value!(char_amp: '&' => "&");
1047 value!(char_apos: '\'' => "'");
1048 value!(char_quot: '"' => """);
1049 value!(char_space: ' ' => " ");
1052
1053 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1054 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1055
1056 err!(bytes:
1057 BTreeMap::from([("$value", Bytes(b"<\"escaped & bytes'>"))])
1058 => Unsupported("`serialize_bytes` not supported yet"));
1059
1060 value!(option_none: Option::<&str>::None);
1061 value!(option_some: Some("non-escaped string") => "non-escaped string");
1062 value!(option_some_empty_str: Some(""));
1063
1064 value!(unit: ());
1065 value!(unit_struct: Unit);
1066 value!(unit_struct_escaped: UnitEscaped);
1067
1068 value!(enum_unit: Enum::Unit => "<Unit/>");
1069 err!(enum_unit_escaped:
1070 BTreeMap::from([("$value", Enum::UnitEscaped)])
1071 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1072
1073 value!(newtype: Newtype(42) => "42");
1074 value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1075
1076 value!(seq: vec![1, 2, 3] => "123");
1078 value!(seq_empty: Vec::<usize>::new());
1079 value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1080 => "<"&'>\
1081 with\t\n\r spaces\
1082 3");
1083 value!(tuple_struct: Tuple("first", 42) => "first42");
1084 value!(enum_tuple: Enum::Tuple("first", 42)
1085 => "<Tuple>first</Tuple>\
1086 <Tuple>42</Tuple>");
1087
1088 err!(map:
1091 BTreeMap::from([("$value", BTreeMap::from([("_1", 2), ("_3", 4)]))])
1092 => Unsupported("serialization of map types is not supported in `$value` field"));
1093 err!(struct_:
1094 BTreeMap::from([("$value", Struct { key: "answer", val: (42, 42) })])
1095 => Unsupported("serialization of struct `Struct` is not supported in `$value` field"));
1096 value!(enum_struct:
1097 Enum::Struct { key: "answer", val: (42, 42) }
1098 => "<Struct>\
1099 <key>answer</key>\
1100 <val>42</val>\
1101 <val>42</val>\
1102 </Struct>");
1103 }
1104
1105 mod struct_ {
1107 use super::*;
1108 use pretty_assertions::assert_eq;
1109
1110 macro_rules! value {
1111 ($name:ident: $data:expr => $expected:literal) => {
1112 serialize_as!($name:
1113 Value {
1114 before: "answer",
1115 content: $data,
1116 after: "answer",
1117 }
1118 => concat!(
1119 "<root><before>answer</before>",
1120 $expected,
1121 "<after>answer</after></root>",
1122 ));
1123 };
1124 }
1125
1126 value!(false_: false => "false");
1127 value!(true_: true => "true");
1128
1129 value!(i8_: -42i8 => "-42");
1130 value!(i16_: -4200i16 => "-4200");
1131 value!(i32_: -42000000i32 => "-42000000");
1132 value!(i64_: -42000000000000i64 => "-42000000000000");
1133 value!(isize_: -42000000000000isize => "-42000000000000");
1134
1135 value!(u8_: 42u8 => "42");
1136 value!(u16_: 4200u16 => "4200");
1137 value!(u32_: 42000000u32 => "42000000");
1138 value!(u64_: 42000000000000u64 => "42000000000000");
1139 value!(usize_: 42000000000000usize => "42000000000000");
1140
1141 serde_if_integer128! {
1142 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1143 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1144 }
1145
1146 value!(f32_: 4.2f32 => "4.2");
1147 value!(f64_: 4.2f64 => "4.2");
1148
1149 value!(char_non_escaped: 'h' => "h");
1150 value!(char_lt: '<' => "<");
1151 value!(char_gt: '>' => ">");
1152 value!(char_amp: '&' => "&");
1153 value!(char_apos: '\'' => "'");
1154 value!(char_quot: '"' => """);
1155 value!(char_space: ' ' => " ");
1158
1159 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1160 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1161
1162 err!(bytes:
1163 Value {
1164 before: "answer",
1165 content: Bytes(b"<\"escaped & bytes'>"),
1166 after: "answer",
1167 }
1168 => Unsupported("`serialize_bytes` not supported yet"));
1169
1170 value!(option_none: Option::<&str>::None => "");
1171 value!(option_some: Some("non-escaped string") => "non-escaped string");
1172 value!(option_some_empty_str: Some("") => "");
1173
1174 value!(unit: () => "");
1175 value!(unit_struct: Unit => "");
1176 value!(unit_struct_escaped: UnitEscaped => "");
1177
1178 value!(enum_unit: Enum::Unit => "<Unit/>");
1179 err!(enum_unit_escaped:
1180 Value {
1181 before: "answer",
1182 content: Enum::UnitEscaped,
1183 after: "answer",
1184 }
1185 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1186
1187 value!(newtype: Newtype(42) => "42");
1188 value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1189
1190 value!(seq: vec![1, 2, 3] => "123");
1192 value!(seq_empty: Vec::<usize>::new() => "");
1193 value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1194 => "<"&'>\
1195 with\t\n\r spaces\
1196 3");
1197 value!(tuple_struct: Tuple("first", 42) => "first42");
1198 value!(enum_tuple: Enum::Tuple("first", 42)
1199 => "<Tuple>first</Tuple>\
1200 <Tuple>42</Tuple>");
1201
1202 err!(map:
1205 Value {
1206 before: "answer",
1207 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1208 after: "answer",
1209 }
1210 => Unsupported("serialization of map types is not supported in `$value` field"));
1211 err!(struct_:
1212 Value {
1213 before: "answer",
1214 content: Struct { key: "answer", val: (42, 42) },
1215 after: "answer",
1216 }
1217 => Unsupported("serialization of struct `Struct` is not supported in `$value` field"));
1218 value!(enum_struct:
1219 Enum::Struct { key: "answer", val: (42, 42) }
1220 => "<Struct>\
1221 <key>answer</key>\
1222 <val>42</val>\
1223 <val>42</val>\
1224 </Struct>");
1225 }
1226 }
1227
1228 mod attributes {
1229 use super::*;
1230 use pretty_assertions::assert_eq;
1231
1232 serialize_as!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
1233 => r#"<root key1="1" key2="2"/>"#);
1234 serialize_as!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
1235 => r#"<root key1="1"><key2>2</key2></root>"#);
1236
1237 serialize_as!(struct_: Attributes { key: "answer", val: (42, 42) }
1238 => r#"<root key="answer" val="42 42"/>"#);
1239 serialize_as!(struct_before: AttributesBefore { key: "answer", val: 42 }
1240 => r#"<root key="answer"><val>42</val></root>"#);
1241 serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
1242 => r#"<root val="42"><key>answer</key></root>"#);
1243
1244 err!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
1245 => Unsupported("cannot serialize enum struct variant `Enum::Attributes`"));
1246
1247 mod optional {
1249 use super::*;
1250 use pretty_assertions::assert_eq;
1251
1252 serialize_as!(none:
1253 OptionalAttributes { a: None, b: None }
1254 => r#"<root a=""/>"#);
1255 serialize_as!(some_empty_str:
1256 OptionalAttributes {
1257 a: Some(""),
1258 b: Some(""),
1259 }
1260 => r#"<root a="" b=""/>"#);
1261 serialize_as!(some_non_empty:
1262 OptionalAttributes {
1263 a: Some("1"),
1264 b: Some("2"),
1265 }
1266 => r#"<root a="1" b="2"/>"#);
1267 }
1268 }
1269
1270 mod optional {
1272 use super::*;
1273 use pretty_assertions::assert_eq;
1274
1275 serialize_as!(none:
1276 OptionalElements { a: None, b: None }
1277 => "<root>\
1278 <a/>\
1279 </root>");
1280 serialize_as!(some_empty_str:
1281 OptionalElements {
1282 a: Some(""),
1283 b: Some(""),
1284 }
1285 => "<root>\
1286 <a/>\
1287 <b/>\
1288 </root>");
1289 serialize_as!(some_non_empty:
1290 OptionalElements {
1291 a: Some("1"),
1292 b: Some("2"),
1293 }
1294 => "<root>\
1295 <a>1</a>\
1296 <b>2</b>\
1297 </root>");
1298 }
1299 }
1300
1301 mod with_indent {
1302 use super::*;
1303 use crate::se::content::tests::Struct;
1304 use crate::writer::Indentation;
1305 use pretty_assertions::assert_eq;
1306
1307 macro_rules! serialize_as {
1309 ($name:ident: $data:expr => $expected:expr) => {
1310 #[test]
1311 fn $name() {
1312 let mut buffer = String::new();
1313 let ser = ElementSerializer {
1314 ser: ContentSerializer {
1315 writer: &mut buffer,
1316 level: QuoteLevel::Full,
1317 indent: Indent::Owned(Indentation::new(b' ', 2)),
1318 write_indent: false,
1319 expand_empty_elements: false,
1320 },
1321 key: XmlName("root"),
1322 };
1323
1324 $data.serialize(ser).unwrap();
1325 assert_eq!(buffer, $expected);
1326 }
1327 };
1328 }
1329
1330 macro_rules! err {
1333 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
1334 #[test]
1335 fn $name() {
1336 let mut buffer = String::new();
1337 let ser = ElementSerializer {
1338 ser: ContentSerializer {
1339 writer: &mut buffer,
1340 level: QuoteLevel::Full,
1341 indent: Indent::Owned(Indentation::new(b' ', 2)),
1342 write_indent: false,
1343 expand_empty_elements: false,
1344 },
1345 key: XmlName("root"),
1346 };
1347
1348 match $data.serialize(ser).unwrap_err() {
1349 DeError::$kind(e) => assert_eq!(e, $reason),
1350 e => panic!(
1351 "Expected `{}({})`, found `{:?}`",
1352 stringify!($kind),
1353 $reason,
1354 e
1355 ),
1356 }
1357 }
1360 };
1361 }
1362
1363 serialize_as!(false_: false => "<root>false</root>");
1364 serialize_as!(true_: true => "<root>true</root>");
1365
1366 serialize_as!(i8_: -42i8 => "<root>-42</root>");
1367 serialize_as!(i16_: -4200i16 => "<root>-4200</root>");
1368 serialize_as!(i32_: -42000000i32 => "<root>-42000000</root>");
1369 serialize_as!(i64_: -42000000000000i64 => "<root>-42000000000000</root>");
1370 serialize_as!(isize_: -42000000000000isize => "<root>-42000000000000</root>");
1371
1372 serialize_as!(u8_: 42u8 => "<root>42</root>");
1373 serialize_as!(u16_: 4200u16 => "<root>4200</root>");
1374 serialize_as!(u32_: 42000000u32 => "<root>42000000</root>");
1375 serialize_as!(u64_: 42000000000000u64 => "<root>42000000000000</root>");
1376 serialize_as!(usize_: 42000000000000usize => "<root>42000000000000</root>");
1377
1378 serde_if_integer128! {
1379 serialize_as!(i128_: -420000000000000000000000000000i128 => "<root>-420000000000000000000000000000</root>");
1380 serialize_as!(u128_: 420000000000000000000000000000u128 => "<root>420000000000000000000000000000</root>");
1381 }
1382
1383 serialize_as!(f32_: 4.2f32 => "<root>4.2</root>");
1384 serialize_as!(f64_: 4.2f64 => "<root>4.2</root>");
1385
1386 serialize_as!(char_non_escaped: 'h' => "<root>h</root>");
1387 serialize_as!(char_lt: '<' => "<root><</root>");
1388 serialize_as!(char_gt: '>' => "<root>></root>");
1389 serialize_as!(char_amp: '&' => "<root>&</root>");
1390 serialize_as!(char_apos: '\'' => "<root>'</root>");
1391 serialize_as!(char_quot: '"' => "<root>"</root>");
1392 serialize_as!(char_space: ' ' => "<root> </root>");
1395
1396 serialize_as!(str_non_escaped: "non-escaped string" => "<root>non-escaped string</root>");
1397 serialize_as!(str_escaped: "<\"escaped & string'>" => "<root><"escaped & string'></root>");
1398
1399 err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
1400
1401 serialize_as!(option_none: Option::<&str>::None => "<root/>");
1402 serialize_as!(option_some: Some("non-escaped string") => "<root>non-escaped string</root>");
1403 serialize_as!(option_some_empty: Some("") => "<root/>");
1404
1405 serialize_as!(unit: () => "<root/>");
1406 serialize_as!(unit_struct: Unit => "<root/>");
1407 serialize_as!(unit_struct_escaped: UnitEscaped => "<root/>");
1408
1409 serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
1410 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root><"&'></root>");
1411
1412 serialize_as!(newtype: Newtype(42) => "<root>42</root>");
1413 err!(enum_newtype: Enum::Newtype(42)
1414 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype`"));
1415
1416 serialize_as!(seq: vec![1, 2, 3]
1417 => "<root>1</root>\n\
1418 <root>2</root>\n\
1419 <root>3</root>");
1420 serialize_as!(seq_empty: Vec::<usize>::new() => "");
1421 serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1422 => "<root><"&'></root>\n\
1423 <root>with\t\n\r spaces</root>\n\
1424 <root>3</root>");
1425 serialize_as!(tuple_struct: Tuple("first", 42)
1426 => "<root>first</root>\n\
1427 <root>42</root>");
1428 err!(enum_tuple: Enum::Tuple("first", 42)
1429 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple`"));
1430
1431 serialize_as!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
1432 => "<root>\n \
1433 <_1>2</_1>\n \
1434 <_3>4</_3>\n\
1435 </root>");
1436 serialize_as!(struct_: Struct { key: "answer", val: (42, 42) }
1437 => "<root>\n \
1438 <key>answer</key>\n \
1439 <val>42</val>\n \
1440 <val>42</val>\n\
1441 </root>");
1442 err!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
1443 => Unsupported("cannot serialize enum struct variant `Enum::Struct`"));
1444
1445 mod text_field {
1448 use super::*;
1449
1450 mod map {
1452 use super::*;
1453 use pretty_assertions::assert_eq;
1454
1455 macro_rules! text {
1456 ($name:ident: $data:expr) => {
1457 serialize_as!($name:
1458 BTreeMap::from([("$text", $data)])
1459 => "<root/>");
1460 };
1461 ($name:ident: $data:expr => $expected:literal) => {
1462 serialize_as!($name:
1463 BTreeMap::from([("$text", $data)])
1464 => concat!("<root>\n ", $expected,"\n</root>"));
1465 };
1466 }
1467
1468 text!(false_: false => "false");
1469 text!(true_: true => "true");
1470
1471 text!(i8_: -42i8 => "-42");
1472 text!(i16_: -4200i16 => "-4200");
1473 text!(i32_: -42000000i32 => "-42000000");
1474 text!(i64_: -42000000000000i64 => "-42000000000000");
1475 text!(isize_: -42000000000000isize => "-42000000000000");
1476
1477 text!(u8_: 42u8 => "42");
1478 text!(u16_: 4200u16 => "4200");
1479 text!(u32_: 42000000u32 => "42000000");
1480 text!(u64_: 42000000000000u64 => "42000000000000");
1481 text!(usize_: 42000000000000usize => "42000000000000");
1482
1483 serde_if_integer128! {
1484 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1485 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1486 }
1487
1488 text!(f32_: 4.2f32 => "4.2");
1489 text!(f64_: 4.2f64 => "4.2");
1490
1491 text!(char_non_escaped: 'h' => "h");
1492 text!(char_lt: '<' => "<");
1493 text!(char_gt: '>' => ">");
1494 text!(char_amp: '&' => "&");
1495 text!(char_apos: '\'' => "'");
1496 text!(char_quot: '"' => """);
1497 text!(char_space: ' ' => " ");
1500
1501 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
1502 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1503
1504 err!(bytes:
1505 Text {
1506 before: "answer",
1507 content: Bytes(b"<\"escaped & bytes'>"),
1508 after: "answer",
1509 }
1510 => Unsupported("`serialize_bytes` not supported yet"));
1511
1512 text!(option_none: Option::<&str>::None);
1513 text!(option_some: Some("non-escaped string") => "non-escaped string");
1514 text!(option_some_empty_str: Some(""));
1515
1516 text!(unit: ());
1517 text!(unit_struct: Unit);
1518 text!(unit_struct_escaped: UnitEscaped);
1519
1520 text!(enum_unit: Enum::Unit => "Unit");
1521 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
1522
1523 text!(newtype: Newtype(42) => "42");
1524 err!(enum_newtype:
1526 Text {
1527 before: "answer",
1528 content: Enum::Newtype(42),
1529 after: "answer",
1530 }
1531 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
1532
1533 text!(seq: vec![1, 2, 3] => "1 2 3");
1535 text!(seq_empty: Vec::<usize>::new());
1536 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1537 => "<"&'> \
1538 with	  spaces \
1539 3");
1540 text!(tuple_struct: Tuple("first", 42) => "first 42");
1541 err!(enum_tuple:
1543 Text {
1544 before: "answer",
1545 content: Enum::Tuple("first", 42),
1546 after: "answer",
1547 }
1548 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
1549
1550 err!(map:
1552 Text {
1553 before: "answer",
1554 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1555 after: "answer",
1556 }
1557 => Unsupported("cannot serialize map as text content value"));
1558 err!(struct_:
1559 Text {
1560 before: "answer",
1561 content: Struct { key: "answer", val: (42, 42) },
1562 after: "answer",
1563 }
1564 => Unsupported("cannot serialize struct `Struct` as text content value"));
1565 err!(enum_struct:
1566 Text {
1567 before: "answer",
1568 content: Enum::Struct { key: "answer", val: (42, 42) },
1569 after: "answer",
1570 }
1571 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1572 }
1573
1574 mod struct_ {
1576 use super::*;
1577 use pretty_assertions::assert_eq;
1578
1579 macro_rules! text {
1580 ($name:ident: $data:expr) => {
1581 serialize_as!($name:
1582 Text {
1583 before: "answer",
1584 content: $data,
1585 after: "answer",
1586 }
1587 => "<root>\n \
1588 <before>answer</before>\n \
1589 <after>answer</after>\n\
1590 </root>");
1591 };
1592 ($name:ident: $data:expr => $expected:literal) => {
1593 serialize_as!($name:
1594 Text {
1595 before: "answer",
1596 content: $data,
1597 after: "answer",
1598 }
1599 => concat!(
1600 "<root>\n <before>answer</before>\n ",
1601 $expected,
1602 "\n <after>answer</after>\n</root>",
1603 ));
1604 };
1605 }
1606
1607 text!(false_: false => "false");
1608 text!(true_: true => "true");
1609
1610 text!(i8_: -42i8 => "-42");
1611 text!(i16_: -4200i16 => "-4200");
1612 text!(i32_: -42000000i32 => "-42000000");
1613 text!(i64_: -42000000000000i64 => "-42000000000000");
1614 text!(isize_: -42000000000000isize => "-42000000000000");
1615
1616 text!(u8_: 42u8 => "42");
1617 text!(u16_: 4200u16 => "4200");
1618 text!(u32_: 42000000u32 => "42000000");
1619 text!(u64_: 42000000000000u64 => "42000000000000");
1620 text!(usize_: 42000000000000usize => "42000000000000");
1621
1622 serde_if_integer128! {
1623 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1624 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1625 }
1626
1627 text!(f32_: 4.2f32 => "4.2");
1628 text!(f64_: 4.2f64 => "4.2");
1629
1630 text!(char_non_escaped: 'h' => "h");
1631 text!(char_lt: '<' => "<");
1632 text!(char_gt: '>' => ">");
1633 text!(char_amp: '&' => "&");
1634 text!(char_apos: '\'' => "'");
1635 text!(char_quot: '"' => """);
1636 text!(char_space: ' ' => " ");
1639
1640 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
1641 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1642
1643 err!(bytes:
1644 Text {
1645 before: "answer",
1646 content: Bytes(b"<\"escaped & bytes'>"),
1647 after: "answer",
1648 }
1649 => Unsupported("`serialize_bytes` not supported yet"));
1650
1651 text!(option_none: Option::<&str>::None);
1652 text!(option_some: Some("non-escaped string") => "non-escaped string");
1653 text!(option_some_empty_str: Some(""));
1654
1655 text!(unit: ());
1656 text!(unit_struct: Unit);
1657 text!(unit_struct_escaped: UnitEscaped);
1658
1659 text!(enum_unit: Enum::Unit => "Unit");
1660 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
1661
1662 text!(newtype: Newtype(42) => "42");
1663 err!(enum_newtype:
1665 Text {
1666 before: "answer",
1667 content: Enum::Newtype(42),
1668 after: "answer",
1669 }
1670 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
1671
1672 text!(seq: vec![1, 2, 3] => "1 2 3");
1674 text!(seq_empty: Vec::<usize>::new());
1675 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1676 => "<"&'> \
1677 with	  spaces \
1678 3");
1679 text!(tuple_struct: Tuple("first", 42) => "first 42");
1680 err!(enum_tuple:
1682 Text {
1683 before: "answer",
1684 content: Enum::Tuple("first", 42),
1685 after: "answer",
1686 }
1687 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
1688
1689 err!(map:
1691 Text {
1692 before: "answer",
1693 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1694 after: "answer",
1695 }
1696 => Unsupported("cannot serialize map as text content value"));
1697 err!(struct_:
1698 Text {
1699 before: "answer",
1700 content: Struct { key: "answer", val: (42, 42) },
1701 after: "answer",
1702 }
1703 => Unsupported("cannot serialize struct `Struct` as text content value"));
1704 err!(enum_struct:
1705 Text {
1706 before: "answer",
1707 content: Enum::Struct { key: "answer", val: (42, 42) },
1708 after: "answer",
1709 }
1710 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1711 }
1712 }
1713
1714 mod value_field {
1718 use super::*;
1719
1720 mod map {
1722 use super::*;
1723 use pretty_assertions::assert_eq;
1724
1725 macro_rules! value {
1726 ($name:ident: $data:expr) => {
1727 serialize_as!($name:
1728 BTreeMap::from([("$value", $data)])
1729 => "<root/>");
1730 };
1731 ($name:ident: $data:expr => $expected:literal) => {
1732 serialize_as!($name:
1733 BTreeMap::from([("$value", $data)])
1734 => concat!("<root>\n ", $expected,"\n</root>"));
1735 };
1736 }
1737
1738 value!(false_: false => "false");
1739 value!(true_: true => "true");
1740
1741 value!(i8_: -42i8 => "-42");
1742 value!(i16_: -4200i16 => "-4200");
1743 value!(i32_: -42000000i32 => "-42000000");
1744 value!(i64_: -42000000000000i64 => "-42000000000000");
1745 value!(isize_: -42000000000000isize => "-42000000000000");
1746
1747 value!(u8_: 42u8 => "42");
1748 value!(u16_: 4200u16 => "4200");
1749 value!(u32_: 42000000u32 => "42000000");
1750 value!(u64_: 42000000000000u64 => "42000000000000");
1751 value!(usize_: 42000000000000usize => "42000000000000");
1752
1753 serde_if_integer128! {
1754 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1755 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1756 }
1757
1758 value!(f32_: 4.2f32 => "4.2");
1759 value!(f64_: 4.2f64 => "4.2");
1760
1761 value!(char_non_escaped: 'h' => "h");
1762 value!(char_lt: '<' => "<");
1763 value!(char_gt: '>' => ">");
1764 value!(char_amp: '&' => "&");
1765 value!(char_apos: '\'' => "'");
1766 value!(char_quot: '"' => """);
1767 value!(char_space: ' ' => " ");
1770
1771 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1772 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1773
1774 err!(bytes:
1775 BTreeMap::from([("$value", Bytes(b"<\"escaped & bytes'>"))])
1776 => Unsupported("`serialize_bytes` not supported yet"));
1777
1778 value!(option_none: Option::<&str>::None);
1779 value!(option_some: Some("non-escaped string") => "non-escaped string");
1780 value!(option_some_empty_str: Some(""));
1781
1782 value!(unit: ());
1783 value!(unit_struct: Unit);
1784 value!(unit_struct_escaped: UnitEscaped);
1785
1786 value!(enum_unit: Enum::Unit => "<Unit/>");
1787 err!(enum_unit_escaped:
1788 BTreeMap::from([("$value", Enum::UnitEscaped)])
1789 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1790
1791 value!(newtype: Newtype(42) => "42");
1792 value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1793
1794 value!(seq: vec![1, 2, 3] => "1\n 2\n 3");
1795 value!(seq_empty: Vec::<usize>::new());
1796 value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1797 => "<"&'>\n \
1798 with\t\n\r spaces\n \
1799 3");
1800 value!(tuple_struct: Tuple("first", 42) => "first\n 42");
1801 value!(enum_tuple: Enum::Tuple("first", 42)
1802 => "<Tuple>first</Tuple>\n \
1803 <Tuple>42</Tuple>");
1804
1805 err!(map:
1808 BTreeMap::from([("$value", BTreeMap::from([("_1", 2), ("_3", 4)]))])
1809 => Unsupported("serialization of map types is not supported in `$value` field"));
1810 err!(struct_:
1811 BTreeMap::from([("$value", Struct { key: "answer", val: (42, 42) })])
1812 => Unsupported("serialization of struct `Struct` is not supported in `$value` field"));
1813 value!(enum_struct:
1814 Enum::Struct { key: "answer", val: (42, 42) }
1815 => "<Struct>\n \
1816 <key>answer</key>\n \
1817 <val>42</val>\n \
1818 <val>42</val>\n \
1819 </Struct>");
1820 }
1821
1822 mod struct_ {
1824 use super::*;
1825 use pretty_assertions::assert_eq;
1826
1827 macro_rules! value {
1828 ($name:ident: $data:expr) => {
1829 serialize_as!($name:
1830 Value {
1831 before: "answer",
1832 content: $data,
1833 after: "answer",
1834 }
1835 => "<root>\n \
1836 <before>answer</before>\n \
1837 <after>answer</after>\n\
1838 </root>");
1839 };
1840 ($name:ident: $data:expr => $expected:literal) => {
1841 serialize_as!($name:
1842 Value {
1843 before: "answer",
1844 content: $data,
1845 after: "answer",
1846 }
1847 => concat!(
1848 "<root>\n <before>answer</before>\n ",
1849 $expected,
1850 "\n <after>answer</after>\n</root>",
1851 ));
1852 };
1853 }
1854
1855 value!(false_: false => "false");
1856 value!(true_: true => "true");
1857
1858 value!(i8_: -42i8 => "-42");
1859 value!(i16_: -4200i16 => "-4200");
1860 value!(i32_: -42000000i32 => "-42000000");
1861 value!(i64_: -42000000000000i64 => "-42000000000000");
1862 value!(isize_: -42000000000000isize => "-42000000000000");
1863
1864 value!(u8_: 42u8 => "42");
1865 value!(u16_: 4200u16 => "4200");
1866 value!(u32_: 42000000u32 => "42000000");
1867 value!(u64_: 42000000000000u64 => "42000000000000");
1868 value!(usize_: 42000000000000usize => "42000000000000");
1869
1870 serde_if_integer128! {
1871 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1872 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1873 }
1874
1875 value!(f32_: 4.2f32 => "4.2");
1876 value!(f64_: 4.2f64 => "4.2");
1877
1878 value!(char_non_escaped: 'h' => "h");
1879 value!(char_lt: '<' => "<");
1880 value!(char_gt: '>' => ">");
1881 value!(char_amp: '&' => "&");
1882 value!(char_apos: '\'' => "'");
1883 value!(char_quot: '"' => """);
1884 value!(char_space: ' ' => " ");
1887
1888 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1889 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1890
1891 err!(bytes:
1892 Value {
1893 before: "answer",
1894 content: Bytes(b"<\"escaped & bytes'>"),
1895 after: "answer",
1896 }
1897 => Unsupported("`serialize_bytes` not supported yet"));
1898
1899 value!(option_none: Option::<&str>::None);
1900 value!(option_some: Some("non-escaped string") => "non-escaped string");
1901 value!(option_some_empty_str: Some(""));
1902
1903 value!(unit: ());
1904 value!(unit_struct: Unit);
1905 value!(unit_struct_escaped: UnitEscaped);
1906
1907 value!(enum_unit: Enum::Unit => "<Unit/>");
1908 err!(enum_unit_escaped:
1909 Value {
1910 before: "answer",
1911 content: Enum::UnitEscaped,
1912 after: "answer",
1913 }
1914 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1915
1916 value!(newtype: Newtype(42) => "42");
1917 value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1918
1919 value!(seq: vec![1, 2, 3] => "1\n 2\n 3");
1921 value!(seq_empty: Vec::<usize>::new());
1922 value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1923 => "<"&'>\n \
1924 with\t\n\r spaces\n \
1925 3");
1926 value!(tuple_struct: Tuple("first", 42) => "first\n 42");
1927 value!(enum_tuple: Enum::Tuple("first", 42)
1928 => "<Tuple>first</Tuple>\n \
1929 <Tuple>42</Tuple>");
1930
1931 err!(map:
1934 Value {
1935 before: "answer",
1936 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1937 after: "answer",
1938 }
1939 => Unsupported("serialization of map types is not supported in `$value` field"));
1940 err!(struct_:
1941 Value {
1942 before: "answer",
1943 content: Struct { key: "answer", val: (42, 42) },
1944 after: "answer",
1945 }
1946 => Unsupported("serialization of struct `Struct` is not supported in `$value` field"));
1947 value!(enum_struct:
1948 Enum::Struct { key: "answer", val: (42, 42) }
1949 => "<Struct>\n \
1950 <key>answer</key>\n \
1951 <val>42</val>\n \
1952 <val>42</val>\n \
1953 </Struct>");
1954 }
1955 }
1956
1957 mod attributes {
1958 use super::*;
1959 use pretty_assertions::assert_eq;
1960
1961 serialize_as!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
1962 => r#"<root key1="1" key2="2"/>"#);
1963 serialize_as!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
1964 => "<root key1=\"1\">\n \
1965 <key2>2</key2>\n\
1966 </root>");
1967
1968 serialize_as!(struct_: Attributes { key: "answer", val: (42, 42) }
1969 => r#"<root key="answer" val="42 42"/>"#);
1970 serialize_as!(struct_before: AttributesBefore { key: "answer", val: 42 }
1971 => "<root key=\"answer\">\n \
1972 <val>42</val>\n\
1973 </root>");
1974 serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
1975 => "<root val=\"42\">\n \
1976 <key>answer</key>\n\
1977 </root>");
1978
1979 err!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
1980 => Unsupported("cannot serialize enum struct variant `Enum::Attributes`"));
1981
1982 mod optional {
1984 use super::*;
1985 use pretty_assertions::assert_eq;
1986
1987 serialize_as!(none:
1988 OptionalAttributes { a: None, b: None }
1989 => r#"<root a=""/>"#);
1990 serialize_as!(some_empty_str:
1991 OptionalAttributes {
1992 a: Some(""),
1993 b: Some("")
1994 }
1995 => r#"<root a="" b=""/>"#);
1996 serialize_as!(some_non_empty:
1997 OptionalAttributes {
1998 a: Some("a"),
1999 b: Some("b")
2000 }
2001 => r#"<root a="a" b="b"/>"#);
2002 }
2003 }
2004
2005 mod optional {
2007 use super::*;
2008 use pretty_assertions::assert_eq;
2009
2010 serialize_as!(none:
2011 OptionalElements { a: None, b: None }
2012 => "<root>\n \
2013 <a/>\n\
2014 </root>");
2015 serialize_as!(some_empty_str:
2016 OptionalElements {
2017 a: Some(""),
2018 b: Some("")
2019 }
2020 => "<root>\n \
2021 <a/>\n \
2022 <b/>\n\
2023 </root>");
2024 serialize_as!(some_non_empty:
2025 OptionalElements {
2026 a: Some("a"),
2027 b: Some("b")
2028 }
2029 => "<root>\n \
2030 <a>a</a>\n \
2031 <b>b</b>\n\
2032 </root>");
2033 }
2034 }
2035
2036 mod expand_empty_elements {
2037 use super::*;
2038 use pretty_assertions::assert_eq;
2039
2040 macro_rules! serialize_as {
2042 ($name:ident: $data:expr => $expected:expr) => {
2043 #[test]
2044 fn $name() {
2045 let mut buffer = String::new();
2046 let ser = ElementSerializer {
2047 ser: ContentSerializer {
2048 writer: &mut buffer,
2049 level: QuoteLevel::Full,
2050 indent: Indent::None,
2051 write_indent: false,
2052 expand_empty_elements: true,
2053 },
2054 key: XmlName("root"),
2055 };
2056
2057 $data.serialize(ser).unwrap();
2058 assert_eq!(buffer, $expected);
2059 }
2060 };
2061 }
2062
2063 serialize_as!(option_some_empty: Some("") => "<root></root>");
2064 serialize_as!(option_some_empty_str: Some("") => "<root></root>");
2065
2066 serialize_as!(unit: () => "<root></root>");
2067 serialize_as!(unit_struct: Unit => "<root></root>");
2068 serialize_as!(unit_struct_escaped: UnitEscaped => "<root></root>");
2069
2070 serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
2071 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root><"&'></root>");
2072 }
2073}