1use crate::de::TEXT_KEY;
4use crate::se::element::{ElementSerializer, Struct, Tuple};
5use crate::se::simple_type::{QuoteTarget, SimpleTypeSerializer};
6use crate::se::{
7 EmptyElementHandling, Indent, QuoteLevel, SeError, TextFormat, WriteResult, XmlName,
8};
9use serde::ser::{
10 Impossible, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct, Serializer,
11};
12use std::fmt::Write;
13
14macro_rules! write_primitive {
15 ($method:ident ( $ty:ty )) => {
16 #[inline]
17 fn $method(self, value: $ty) -> Result<Self::Ok, Self::Error> {
18 self.into_simple_type_serializer()?.$method(value)?;
19 Ok(WriteResult::Text)
20 }
21 };
22}
23
24pub struct ContentSerializer<'w, 'i, W: Write> {
64 pub writer: &'w mut W,
65 pub level: QuoteLevel,
67 pub(super) indent: Indent<'i>,
72 pub write_indent: bool,
75 pub text_format: TextFormat,
77 pub allow_primitive: bool,
85 pub empty_element_handling: EmptyElementHandling,
87}
88
89impl<'w, 'i, W: Write> ContentSerializer<'w, 'i, W> {
90 #[inline]
92 pub fn into_simple_type_serializer_impl(self) -> SimpleTypeSerializer<&'w mut W> {
93 SimpleTypeSerializer {
94 writer: self.writer,
95 target: match self.text_format {
96 TextFormat::Text => QuoteTarget::Text,
97 TextFormat::CData => QuoteTarget::CData,
98 },
99 level: self.level,
100 }
101 }
102
103 #[inline]
106 pub fn into_simple_type_serializer(self) -> Result<SimpleTypeSerializer<&'w mut W>, SeError> {
107 if self.allow_primitive {
108 Ok(self.into_simple_type_serializer_impl())
109 } else {
110 Err(SeError::Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back".into()))
111 }
112 }
113
114 #[inline]
117 pub fn new_seq_element_serializer(
118 &mut self,
119 allow_primitive: bool,
120 ) -> ContentSerializer<'_, '_, W> {
121 ContentSerializer {
122 writer: self.writer,
123 level: self.level,
124 indent: self.indent.borrow(),
125 write_indent: self.write_indent,
126 text_format: self.text_format,
127 allow_primitive,
128 empty_element_handling: self.empty_element_handling,
129 }
130 }
131
132 #[inline]
134 pub(super) fn write_empty(mut self, name: XmlName) -> Result<WriteResult, SeError> {
135 self.write_indent()?;
136
137 match self.empty_element_handling {
138 EmptyElementHandling::SelfClosed => {
139 self.writer.write_char('<')?;
140 self.writer.write_str(name.0)?;
141 self.writer.write_str("/>")?;
142 }
143 EmptyElementHandling::SelfClosedWithSpace => {
144 self.writer.write_char('<')?;
145 self.writer.write_str(name.0)?;
146 self.writer.write_str(" />")?;
147 }
148 EmptyElementHandling::Expanded => {
149 self.writer.write_char('<')?;
150 self.writer.write_str(name.0)?;
151 self.writer.write_str("></")?;
152 self.writer.write_str(name.0)?;
153 self.writer.write_char('>')?;
154 }
155 }
156
157 Ok(WriteResult::Element)
158 }
159
160 pub(super) fn write_wrapped<S>(
162 mut self,
163 name: XmlName,
164 serialize: S,
165 ) -> Result<WriteResult, SeError>
166 where
167 S: for<'a> FnOnce(SimpleTypeSerializer<&'a mut W>) -> Result<&'a mut W, SeError>,
168 {
169 self.write_indent()?;
170 self.writer.write_char('<')?;
171 self.writer.write_str(name.0)?;
172 self.writer.write_char('>')?;
173
174 let writer = serialize(self.into_simple_type_serializer_impl())?;
175
176 writer.write_str("</")?;
177 writer.write_str(name.0)?;
178 writer.write_char('>')?;
179 Ok(WriteResult::Element)
180 }
181
182 pub(super) fn write_indent(&mut self) -> Result<(), SeError> {
183 if self.write_indent {
184 self.indent.write_indent(&mut self.writer)?;
185 self.write_indent = false;
186 }
187 Ok(())
188 }
189}
190
191impl<'w, 'i, W: Write> Serializer for ContentSerializer<'w, 'i, W> {
192 type Ok = WriteResult;
193 type Error = SeError;
194
195 type SerializeSeq = Seq<'w, 'i, W>;
196 type SerializeTuple = Seq<'w, 'i, W>;
197 type SerializeTupleStruct = Seq<'w, 'i, W>;
198 type SerializeTupleVariant = Tuple<'w, 'i, W>;
199 type SerializeMap = Impossible<Self::Ok, Self::Error>;
200 type SerializeStruct = Struct<'w, 'i, W>;
201 type SerializeStructVariant = Struct<'w, 'i, W>;
202
203 write_primitive!(serialize_bool(bool));
204
205 write_primitive!(serialize_i8(i8));
206 write_primitive!(serialize_i16(i16));
207 write_primitive!(serialize_i32(i32));
208 write_primitive!(serialize_i64(i64));
209
210 write_primitive!(serialize_u8(u8));
211 write_primitive!(serialize_u16(u16));
212 write_primitive!(serialize_u32(u32));
213 write_primitive!(serialize_u64(u64));
214
215 write_primitive!(serialize_i128(i128));
216 write_primitive!(serialize_u128(u128));
217
218 write_primitive!(serialize_f32(f32));
219 write_primitive!(serialize_f64(f64));
220
221 write_primitive!(serialize_bytes(&[u8]));
222
223 #[inline]
224 fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
225 self.into_simple_type_serializer()?.serialize_char(value)?;
226 Ok(WriteResult::SensitiveText)
227 }
228
229 #[inline]
230 fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
231 if !value.is_empty() {
232 self.into_simple_type_serializer()?.serialize_str(value)?;
233 }
234 Ok(WriteResult::SensitiveText)
235 }
236
237 #[inline]
239 fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
240 Ok(WriteResult::SensitiveNothing)
244 }
245
246 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
247 value.serialize(self)
248 }
249
250 #[inline]
252 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
253 Ok(WriteResult::Nothing)
254 }
255
256 #[inline]
258 fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
259 Ok(WriteResult::Nothing)
260 }
261
262 fn serialize_unit_variant(
265 self,
266 _name: &'static str,
267 _variant_index: u32,
268 variant: &'static str,
269 ) -> Result<Self::Ok, Self::Error> {
270 if variant == TEXT_KEY {
271 Ok(WriteResult::Nothing)
272 } else {
273 let name = XmlName::try_from(variant)?;
274 self.write_empty(name)
275 }
276 }
277
278 fn serialize_newtype_struct<T: ?Sized + Serialize>(
279 self,
280 _name: &'static str,
281 value: &T,
282 ) -> Result<Self::Ok, Self::Error> {
283 value.serialize(self)
284 }
285
286 fn serialize_newtype_variant<T: ?Sized + Serialize>(
290 self,
291 _name: &'static str,
292 _variant_index: u32,
293 variant: &'static str,
294 value: &T,
295 ) -> Result<Self::Ok, Self::Error> {
296 if variant == TEXT_KEY {
297 value.serialize(self.into_simple_type_serializer()?)?;
298 Ok(WriteResult::SensitiveText)
299 } else {
300 value.serialize(ElementSerializer {
301 key: XmlName::try_from(variant)?,
302 ser: self,
303 })?;
304 Ok(WriteResult::Element)
305 }
306 }
307
308 #[inline]
309 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
310 Ok(Seq {
311 ser: self,
312 last: WriteResult::SensitiveNothing,
315 })
316 }
317
318 #[inline]
319 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
320 self.serialize_seq(Some(len))
321 }
322
323 #[inline]
324 fn serialize_tuple_struct(
325 self,
326 _name: &'static str,
327 len: usize,
328 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
329 self.serialize_tuple(len)
330 }
331
332 #[inline]
341 fn serialize_tuple_variant(
342 self,
343 name: &'static str,
344 _variant_index: u32,
345 variant: &'static str,
346 len: usize,
347 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
348 if variant == TEXT_KEY {
349 self.into_simple_type_serializer()?
350 .serialize_tuple_struct(name, len)
351 .map(Tuple::Text)
352 } else {
353 let ser = ElementSerializer {
354 key: XmlName::try_from(variant)?,
355 ser: self,
356 };
357 ser.serialize_tuple_struct(name, len).map(Tuple::Element)
358 }
359 }
360
361 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
362 Err(SeError::Unsupported(
363 "serialization of map types is not supported in `$value` field".into(),
364 ))
365 }
366
367 #[inline]
368 fn serialize_struct(
369 self,
370 name: &'static str,
371 len: usize,
372 ) -> Result<Self::SerializeStruct, Self::Error> {
373 ElementSerializer {
374 ser: self,
375 key: XmlName::try_from(name)?,
376 }
377 .serialize_struct(name, len)
378 }
379
380 #[inline]
391 fn serialize_struct_variant(
392 self,
393 name: &'static str,
394 _variant_index: u32,
395 variant: &'static str,
396 len: usize,
397 ) -> Result<Self::SerializeStructVariant, Self::Error> {
398 if variant == TEXT_KEY {
399 Err(SeError::Unsupported(
400 format!("cannot serialize `$text` struct variant of `{}` enum", name).into(),
401 ))
402 } else {
403 let ser = ElementSerializer {
404 key: XmlName::try_from(variant)?,
405 ser: self,
406 };
407 ser.serialize_struct(name, len)
408 }
409 }
410}
411
412pub struct Seq<'w, 'k, W: Write> {
417 ser: ContentSerializer<'w, 'k, W>,
418 last: WriteResult,
420}
421
422impl<'w, 'i, W: Write> SerializeSeq for Seq<'w, 'i, W> {
423 type Ok = WriteResult;
424 type Error = SeError;
425
426 fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
427 where
428 T: ?Sized + Serialize,
429 {
430 self.last = value.serialize(self.ser.new_seq_element_serializer(self.last.is_text()))?;
431 self.ser.write_indent = self.last.allow_indent();
433 Ok(())
434 }
435
436 #[inline]
437 fn end(self) -> Result<Self::Ok, Self::Error> {
438 Ok(self.last)
439 }
440}
441
442impl<'w, 'i, W: Write> SerializeTuple for Seq<'w, 'i, W> {
443 type Ok = WriteResult;
444 type Error = SeError;
445
446 #[inline]
447 fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
448 where
449 T: ?Sized + Serialize,
450 {
451 SerializeSeq::serialize_element(self, value)
452 }
453
454 #[inline]
455 fn end(self) -> Result<Self::Ok, Self::Error> {
456 SerializeSeq::end(self)
457 }
458}
459
460impl<'w, 'i, W: Write> SerializeTupleStruct for Seq<'w, 'i, W> {
461 type Ok = WriteResult;
462 type Error = SeError;
463
464 #[inline]
465 fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
466 where
467 T: ?Sized + Serialize,
468 {
469 SerializeSeq::serialize_element(self, value)
470 }
471
472 #[inline]
473 fn end(self) -> Result<Self::Ok, Self::Error> {
474 SerializeSeq::end(self)
475 }
476}
477
478#[cfg(test)]
482pub(super) mod tests {
483 use super::*;
484 use crate::utils::Bytes;
485 use serde::Serialize;
486 use std::collections::BTreeMap;
487 use WriteResult::*;
488
489 #[derive(Debug, Serialize, PartialEq)]
490 pub struct Unit;
491
492 #[derive(Debug, Serialize, PartialEq)]
493 #[serde(rename = "<\"&'>")]
494 pub struct UnitEscaped;
495
496 #[derive(Debug, Serialize, PartialEq)]
497 pub struct Newtype(pub usize);
498
499 #[derive(Debug, Serialize, PartialEq)]
500 pub struct Tuple(pub &'static str, pub usize);
501
502 #[derive(Debug, Serialize, PartialEq)]
503 pub struct Struct {
504 pub key: &'static str,
505 pub val: (usize, usize),
506 }
507
508 #[derive(Debug, Serialize, PartialEq)]
510 pub struct Text<T> {
511 pub before: &'static str,
512 #[serde(rename = "$text")]
513 pub content: T,
514 pub after: &'static str,
515 }
516
517 #[derive(Debug, Serialize, PartialEq)]
519 pub struct Value<T> {
520 pub before: &'static str,
521 #[serde(rename = "$value")]
522 pub content: T,
523 pub after: &'static str,
524 }
525
526 #[derive(Debug, Serialize, PartialEq)]
528 pub struct Attributes {
529 #[serde(rename = "@key")]
530 pub key: &'static str,
531 #[serde(rename = "@val")]
532 pub val: (usize, usize),
533 }
534 #[derive(Debug, Serialize, PartialEq)]
535 pub struct AttributesBefore {
536 #[serde(rename = "@key")]
537 pub key: &'static str,
538 pub val: usize,
539 }
540 #[derive(Debug, Serialize, PartialEq)]
541 pub struct AttributesAfter {
542 pub key: &'static str,
543 #[serde(rename = "@val")]
544 pub val: usize,
545 }
546
547 #[derive(Debug, Serialize, PartialEq)]
548 pub enum Enum {
549 Unit,
550 #[serde(rename = "<\"&'>")]
553 UnitEscaped,
554 Newtype(usize),
555 Tuple(&'static str, usize),
556 Struct {
557 key: &'static str,
558 val: (usize, usize),
560 },
561 Attributes {
562 #[serde(rename = "@key")]
563 key: &'static str,
564 #[serde(rename = "@val")]
565 val: (usize, usize),
566 },
567 AttributesBefore {
568 #[serde(rename = "@key")]
569 key: &'static str,
570 val: usize,
571 },
572 AttributesAfter {
573 key: &'static str,
574 #[serde(rename = "@val")]
575 val: usize,
576 },
577 }
578
579 #[derive(Debug, Serialize, PartialEq)]
580 pub enum SpecialEnum<T> {
581 Text {
583 before: &'static str,
584 #[serde(rename = "$text")]
585 content: T,
586 after: &'static str,
587 },
588 Value {
590 before: &'static str,
591 #[serde(rename = "$value")]
592 content: T,
593 after: &'static str,
594 },
595 }
596
597 mod without_indent {
598 use super::Struct;
599 use super::*;
600 use pretty_assertions::assert_eq;
601
602 macro_rules! serialize_as {
604 ($name:ident: $data:expr => $expected:expr) => {
605 serialize_as!($name: $data => $expected, WriteResult::Element);
606 };
607 ($name:ident: $data:expr => $expected:expr, $result:expr) => {
608 #[test]
609 fn $name() {
610 let mut buffer = String::new();
611 let ser = ContentSerializer {
612 writer: &mut buffer,
613 level: QuoteLevel::Full,
614 indent: Indent::None,
615 write_indent: false,
616 text_format: TextFormat::Text,
617 allow_primitive: true,
618 empty_element_handling: EmptyElementHandling::SelfClosed,
619 };
620
621 let result = $data.serialize(ser).unwrap();
622 assert_eq!(buffer, $expected);
623 assert_eq!(result, $result);
624 }
625 };
626 }
627
628 macro_rules! err {
631 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
632 #[test]
633 fn $name() {
634 let mut buffer = String::new();
635 let ser = ContentSerializer {
636 writer: &mut buffer,
637 level: QuoteLevel::Full,
638 indent: Indent::None,
639 write_indent: false,
640 text_format: TextFormat::Text,
641 allow_primitive: true,
642 empty_element_handling: EmptyElementHandling::SelfClosed,
643 };
644
645 match $data.serialize(ser).unwrap_err() {
646 SeError::$kind(e) => assert_eq!(e, $reason),
647 e => panic!(
648 "Expected `Err({}({}))`, but got `{:?}`",
649 stringify!($kind),
650 $reason,
651 e
652 ),
653 }
654 }
657 };
658 }
659
660 serialize_as!(false_: false => "false", Text);
662 serialize_as!(true_: true => "true", Text);
663
664 serialize_as!(i8_: -42i8 => "-42", Text);
665 serialize_as!(i16_: -4200i16 => "-4200", Text);
666 serialize_as!(i32_: -42000000i32 => "-42000000", Text);
667 serialize_as!(i64_: -42000000000000i64 => "-42000000000000", Text);
668 serialize_as!(isize_: -42000000isize => "-42000000", Text);
669
670 serialize_as!(u8_: 42u8 => "42", Text);
671 serialize_as!(u16_: 4200u16 => "4200", Text);
672 serialize_as!(u32_: 42000000u32 => "42000000", Text);
673 serialize_as!(u64_: 42000000000000u64 => "42000000000000", Text);
674 serialize_as!(usize_: 42000000usize => "42000000", Text);
675
676 serialize_as!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000", Text);
677 serialize_as!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000", Text);
678
679 serialize_as!(f32_: 4.2f32 => "4.2", Text);
680 serialize_as!(f64_: 4.2f64 => "4.2", Text);
681
682 serialize_as!(char_non_escaped: 'h' => "h", SensitiveText);
683 serialize_as!(char_lt: '<' => "<", SensitiveText);
684 serialize_as!(char_gt: '>' => ">", SensitiveText);
685 serialize_as!(char_amp: '&' => "&", SensitiveText);
686 serialize_as!(char_apos: '\'' => "'", SensitiveText);
687 serialize_as!(char_quot: '"' => """, SensitiveText);
688 serialize_as!(char_space: ' ' => " ", SensitiveText);
689
690 serialize_as!(str_non_escaped: "non-escaped string" => "non-escaped string", SensitiveText);
691 serialize_as!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>", SensitiveText);
692
693 err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
694
695 serialize_as!(option_none: Option::<Enum>::None => "", SensitiveNothing);
696 serialize_as!(option_some: Some("non-escaped string") => "non-escaped string", SensitiveText);
697 serialize_as!(option_some_empty_str: Some("") => "", SensitiveText);
698
699 serialize_as!(unit: () => "", Nothing);
700 serialize_as!(unit_struct: Unit => "", Nothing);
701 serialize_as!(unit_struct_escaped: UnitEscaped => "", Nothing);
702
703 serialize_as!(enum_unit: Enum::Unit => "<Unit/>");
705 err!(enum_unit_escaped: Enum::UnitEscaped
706 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
707
708 serialize_as!(newtype: Newtype(42) => "42", Text);
710 serialize_as!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
711
712 err!(seq: vec![1, 2, 3]
714 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
715 serialize_as!(seq_empty: Vec::<usize>::new() => "", SensitiveNothing);
716 err!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize)
717 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
718 err!(tuple_struct: Tuple("first", 42)
719 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
720 serialize_as!(enum_tuple: Enum::Tuple("first", 42)
721 => "<Tuple>first</Tuple>\
722 <Tuple>42</Tuple>");
723
724 err!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
727 => Unsupported("serialization of map types is not supported in `$value` field"));
728 serialize_as!(struct_: Struct { key: "answer", val: (42, 42) }
729 => "<Struct>\
730 <key>answer</key>\
731 <val>42</val>\
732 <val>42</val>\
733 </Struct>");
734
735 serialize_as!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
736 => "<Struct>\
737 <key>answer</key>\
738 <val>42</val>\
739 <val>42</val>\
740 </Struct>");
741
742 mod text_field {
744 use super::*;
745 use pretty_assertions::assert_eq;
746
747 err!(map: BTreeMap::from([("$text", 2), ("_3", 4)])
748 => Unsupported("serialization of map types is not supported in `$value` field"));
749 serialize_as!(struct_:
750 Text {
751 before: "answer",
752 content: (42, 42),
753 after: "answer",
754 }
755 => "<Text>\
756 <before>answer</before>\
757 42 42\
758 <after>answer</after>\
759 </Text>");
760 serialize_as!(enum_struct:
761 SpecialEnum::Text {
762 before: "answer",
763 content: (42, 42),
764 after: "answer",
765 }
766 => "<Text>\
767 <before>answer</before>\
768 42 42\
769 <after>answer</after>\
770 </Text>");
771 }
772
773 mod enum_with_text_field {
775 use super::*;
776 use pretty_assertions::assert_eq;
777
778 macro_rules! text {
779 ($name:ident: $data:expr => $expected:literal) => {
780 serialize_as!($name:
781 SpecialEnum::Text {
782 before: "answer",
783 content: $data,
784 after: "answer",
785 }
786 => concat!(
787 "<Text><before>answer</before>",
788 $expected,
789 "<after>answer</after></Text>",
790 ));
791 };
792 }
793
794 text!(false_: false => "false");
795 text!(true_: true => "true");
796
797 text!(i8_: -42i8 => "-42");
798 text!(i16_: -4200i16 => "-4200");
799 text!(i32_: -42000000i32 => "-42000000");
800 text!(i64_: -42000000000000i64 => "-42000000000000");
801 text!(isize_: -42000000isize => "-42000000");
802
803 text!(u8_: 42u8 => "42");
804 text!(u16_: 4200u16 => "4200");
805 text!(u32_: 42000000u32 => "42000000");
806 text!(u64_: 42000000000000u64 => "42000000000000");
807 text!(usize_: 42000000usize => "42000000");
808
809 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
810 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
811
812 text!(f32_: 4.2f32 => "4.2");
813 text!(f64_: 4.2f64 => "4.2");
814
815 text!(char_non_escaped: 'h' => "h");
816 text!(char_lt: '<' => "<");
817 text!(char_gt: '>' => ">");
818 text!(char_amp: '&' => "&");
819 text!(char_apos: '\'' => "'");
820 text!(char_quot: '"' => """);
821 text!(char_space: ' ' => " ");
822
823 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
824 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
825
826 err!(bytes:
827 SpecialEnum::Text {
828 before: "answer",
829 content: Bytes(b"<\"escaped & bytes'>"),
830 after: "answer",
831 }
832 => Unsupported("`serialize_bytes` not supported yet"));
833
834 text!(option_none: Option::<&str>::None => "");
835 text!(option_some: Some("non-escaped string") => "non-escaped string");
836 text!(option_some_empty_str: Some("") => "");
837
838 text!(unit: () => "");
839 text!(unit_struct: Unit => "");
840 text!(unit_struct_escaped: UnitEscaped => "");
841
842 text!(enum_unit: Enum::Unit => "Unit");
843 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
844
845 text!(newtype: Newtype(42) => "42");
846 err!(enum_newtype:
848 SpecialEnum::Text {
849 before: "answer",
850 content: Enum::Newtype(42),
851 after: "answer",
852 }
853 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
854
855 text!(seq: vec![1, 2, 3] => "1 2 3");
857 text!(seq_empty: Vec::<usize>::new() => "");
858 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
859 => "<"&'> \
860 with	  spaces \
861 3");
862 text!(tuple_struct: Tuple("first", 42) => "first 42");
863 err!(enum_tuple:
865 SpecialEnum::Text {
866 before: "answer",
867 content: Enum::Tuple("first", 42),
868 after: "answer",
869 }
870 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
871
872 err!(map:
874 SpecialEnum::Text {
875 before: "answer",
876 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
877 after: "answer",
878 }
879 => Unsupported("cannot serialize map as text content value"));
880 err!(struct_:
881 SpecialEnum::Text {
882 before: "answer",
883 content: Struct { key: "answer", val: (42, 42) },
884 after: "answer",
885 }
886 => Unsupported("cannot serialize struct `Struct` as text content value"));
887 err!(enum_struct:
888 SpecialEnum::Text {
889 before: "answer",
890 content: Enum::Struct { key: "answer", val: (42, 42) },
891 after: "answer",
892 }
893 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
894 }
895
896 mod enum_with_value_field {
898 use super::*;
899 use pretty_assertions::assert_eq;
900
901 macro_rules! value {
902 ($name:ident: $data:expr => $expected:literal) => {
903 serialize_as!($name:
904 SpecialEnum::Value {
905 before: "answer",
906 content: $data,
907 after: "answer",
908 }
909 => concat!(
910 "<Value><before>answer</before>",
911 $expected,
912 "<after>answer</after></Value>",
913 ));
914 };
915 }
916
917 value!(false_: false => "false");
918 value!(true_: true => "true");
919
920 value!(i8_: -42i8 => "-42");
921 value!(i16_: -4200i16 => "-4200");
922 value!(i32_: -42000000i32 => "-42000000");
923 value!(i64_: -42000000000000i64 => "-42000000000000");
924 value!(isize_: -42000000isize => "-42000000");
925
926 value!(u8_: 42u8 => "42");
927 value!(u16_: 4200u16 => "4200");
928 value!(u32_: 42000000u32 => "42000000");
929 value!(u64_: 42000000000000u64 => "42000000000000");
930 value!(usize_: 42000000usize => "42000000");
931
932 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
933 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
934
935 value!(f32_: 4.2f32 => "4.2");
936 value!(f64_: 4.2f64 => "4.2");
937
938 value!(char_non_escaped: 'h' => "h");
939 value!(char_lt: '<' => "<");
940 value!(char_gt: '>' => ">");
941 value!(char_amp: '&' => "&");
942 value!(char_apos: '\'' => "'");
943 value!(char_quot: '"' => """);
944 value!(char_space: ' ' => " ");
945
946 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
947 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
948
949 err!(bytes:
950 SpecialEnum::Value {
951 before: "answer",
952 content: Bytes(b"<\"escaped & bytes'>"),
953 after: "answer",
954 }
955 => Unsupported("`serialize_bytes` not supported yet"));
956
957 value!(option_none: Option::<&str>::None => "");
958 value!(option_some: Some("non-escaped string") => "non-escaped string");
959 value!(option_some_empty_str: Some("") => "");
960
961 value!(unit: () => "");
962 value!(unit_struct: Unit => "");
963 value!(unit_struct_escaped: UnitEscaped => "");
964
965 value!(enum_unit: Enum::Unit => "<Unit/>");
966 err!(enum_unit_escaped:
967 SpecialEnum::Value {
968 before: "answer",
969 content: Enum::UnitEscaped,
970 after: "answer",
971 }
972 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
973
974 value!(newtype: Newtype(42) => "42");
975 value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
976
977 err!(seq:
979 SpecialEnum::Value {
980 before: "answer",
981 content: vec![1, 2, 3],
982 after: "answer",
983 }
984 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
985 value!(seq_empty: Vec::<usize>::new() => "");
986 err!(tuple:
987 SpecialEnum::Value {
988 before: "answer",
989 content: ("<\"&'>", "with\t\n\r spaces", 3usize),
990 after: "answer",
991 }
992 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
993 err!(tuple_struct:
994 SpecialEnum::Value {
995 before: "answer",
996 content: Tuple("first", 42),
997 after: "answer",
998 }
999 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1000 value!(enum_tuple: Enum::Tuple("first", 42)
1001 => "<Tuple>first</Tuple>\
1002 <Tuple>42</Tuple>");
1003
1004 err!(map:
1007 SpecialEnum::Value {
1008 before: "answer",
1009 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1010 after: "answer",
1011 }
1012 => Unsupported("serialization of map types is not supported in `$value` field"));
1013 value!(struct_:
1014 SpecialEnum::Value {
1015 before: "answer",
1016 content: Struct { key: "answer", val: (42, 42) },
1017 after: "answer",
1018 }
1019 => "<Value>\
1020 <before>answer</before>\
1021 <Struct>\
1022 <key>answer</key>\
1023 <val>42</val>\
1024 <val>42</val>\
1025 </Struct>\
1026 <after>answer</after>\
1027 </Value>");
1028 value!(enum_struct:
1029 Enum::Struct { key: "answer", val: (42, 42) }
1030 => "<Struct>\
1031 <key>answer</key>\
1032 <val>42</val>\
1033 <val>42</val>\
1034 </Struct>");
1035 }
1036
1037 mod attributes {
1038 use super::*;
1039 use pretty_assertions::assert_eq;
1040
1041 err!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
1042 => Unsupported("serialization of map types is not supported in `$value` field"));
1043 err!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
1044 => Unsupported("serialization of map types is not supported in `$value` field"));
1045
1046 serialize_as!(struct_: Attributes { key: "answer", val: (42, 42) }
1047 => r#"<Attributes key="answer" val="42 42"/>"#);
1048 serialize_as!(struct_before: AttributesBefore { key: "answer", val: 42 }
1049 => r#"<AttributesBefore key="answer"><val>42</val></AttributesBefore>"#);
1050 serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
1051 => r#"<AttributesAfter val="42"><key>answer</key></AttributesAfter>"#);
1052
1053 serialize_as!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
1054 => r#"<Attributes key="answer" val="42 42"/>"#);
1055 serialize_as!(enum_before: Enum::AttributesBefore { key: "answer", val: 42 }
1056 => r#"<AttributesBefore key="answer"><val>42</val></AttributesBefore>"#);
1057 serialize_as!(enum_after: Enum::AttributesAfter { key: "answer", val: 42 }
1058 => r#"<AttributesAfter val="42"><key>answer</key></AttributesAfter>"#);
1059 }
1060 }
1061
1062 mod with_indent {
1063 use super::Struct;
1064 use super::*;
1065 use crate::writer::Indentation;
1066 use pretty_assertions::assert_eq;
1067
1068 macro_rules! serialize_as {
1070 ($name:ident: $data:expr => $expected:expr) => {
1071 serialize_as!($name: $data => $expected, WriteResult::Element);
1072 };
1073 ($name:ident: $data:expr => $expected:expr, $result:expr) => {
1074 #[test]
1075 fn $name() {
1076 let mut buffer = String::new();
1077 let ser = ContentSerializer {
1078 writer: &mut buffer,
1079 level: QuoteLevel::Full,
1080 indent: Indent::Owned(Indentation::new(b' ', 2)),
1081 write_indent: false,
1082 text_format: TextFormat::Text,
1083 allow_primitive: true,
1084 empty_element_handling: EmptyElementHandling::SelfClosed,
1085 };
1086
1087 let result = $data.serialize(ser).unwrap();
1088 assert_eq!(buffer, $expected);
1089 assert_eq!(result, $result);
1090 }
1091 };
1092 }
1093
1094 macro_rules! err {
1097 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
1098 #[test]
1099 fn $name() {
1100 let mut buffer = String::new();
1101 let ser = ContentSerializer {
1102 writer: &mut buffer,
1103 level: QuoteLevel::Full,
1104 indent: Indent::Owned(Indentation::new(b' ', 2)),
1105 write_indent: false,
1106 text_format: TextFormat::Text,
1107 allow_primitive: true,
1108 empty_element_handling: EmptyElementHandling::SelfClosed,
1109 };
1110
1111 match $data.serialize(ser).unwrap_err() {
1112 SeError::$kind(e) => assert_eq!(e, $reason),
1113 e => panic!(
1114 "Expected `Err({}({}))`, but got `{:?}`",
1115 stringify!($kind),
1116 $reason,
1117 e
1118 ),
1119 }
1120 }
1123 };
1124 }
1125
1126 serialize_as!(false_: false => "false", Text);
1127 serialize_as!(true_: true => "true", Text);
1128
1129 serialize_as!(i8_: -42i8 => "-42", Text);
1130 serialize_as!(i16_: -4200i16 => "-4200", Text);
1131 serialize_as!(i32_: -42000000i32 => "-42000000", Text);
1132 serialize_as!(i64_: -42000000000000i64 => "-42000000000000", Text);
1133 serialize_as!(isize_: -42000000isize => "-42000000", Text);
1134
1135 serialize_as!(u8_: 42u8 => "42", Text);
1136 serialize_as!(u16_: 4200u16 => "4200", Text);
1137 serialize_as!(u32_: 42000000u32 => "42000000", Text);
1138 serialize_as!(u64_: 42000000000000u64 => "42000000000000", Text);
1139 serialize_as!(usize_: 42000000usize => "42000000", Text);
1140
1141 serialize_as!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000", Text);
1142 serialize_as!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000", Text);
1143
1144 serialize_as!(f32_: 4.2f32 => "4.2", Text);
1145 serialize_as!(f64_: 4.2f64 => "4.2", Text);
1146
1147 serialize_as!(char_non_escaped: 'h' => "h", SensitiveText);
1148 serialize_as!(char_lt: '<' => "<", SensitiveText);
1149 serialize_as!(char_gt: '>' => ">", SensitiveText);
1150 serialize_as!(char_amp: '&' => "&", SensitiveText);
1151 serialize_as!(char_apos: '\'' => "'", SensitiveText);
1152 serialize_as!(char_quot: '"' => """, SensitiveText);
1153 serialize_as!(char_space: ' ' => " ", SensitiveText);
1154
1155 serialize_as!(str_non_escaped: "non-escaped string" => "non-escaped string", SensitiveText);
1156 serialize_as!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>", SensitiveText);
1157
1158 err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
1159
1160 serialize_as!(option_none: Option::<Enum>::None => "", SensitiveNothing);
1161 serialize_as!(option_some: Some(Enum::Unit) => "<Unit/>");
1162
1163 serialize_as!(unit: () => "", Nothing);
1164 serialize_as!(unit_struct: Unit => "", Nothing);
1165 serialize_as!(unit_struct_escaped: UnitEscaped => "", Nothing);
1166
1167 serialize_as!(enum_unit: Enum::Unit => "<Unit/>");
1169 err!(enum_unit_escaped: Enum::UnitEscaped
1170 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1171
1172 serialize_as!(newtype: Newtype(42) => "42", Text);
1174 serialize_as!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1175
1176 err!(seq: vec![1, 2, 3]
1177 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1178 serialize_as!(seq_empty: Vec::<usize>::new() => "", SensitiveNothing);
1179 err!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize)
1180 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1181 err!(tuple_struct: Tuple("first", 42)
1182 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1183 serialize_as!(enum_tuple: Enum::Tuple("first", 42)
1184 => "<Tuple>first</Tuple>\n\
1185 <Tuple>42</Tuple>");
1186
1187 err!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
1190 => Unsupported("serialization of map types is not supported in `$value` field"));
1191 serialize_as!(struct_: Struct { key: "answer", val: (42, 42) }
1192 => "<Struct>\n \
1193 <key>answer</key>\n \
1194 <val>42</val>\n \
1195 <val>42</val>\n\
1196 </Struct>");
1197 serialize_as!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
1198 => "<Struct>\n \
1199 <key>answer</key>\n \
1200 <val>42</val>\n \
1201 <val>42</val>\n\
1202 </Struct>");
1203
1204 mod text_field {
1206 use super::*;
1207 use pretty_assertions::assert_eq;
1208
1209 err!(map: BTreeMap::from([("$text", 2), ("_3", 4)])
1210 => Unsupported("serialization of map types is not supported in `$value` field"));
1211 serialize_as!(struct_:
1212 Text {
1213 before: "answer",
1214 content: (42, 42),
1215 after: "answer",
1216 }
1217 => "<Text>\n \
1218 <before>answer</before>42 42<after>answer</after>\n\
1219 </Text>");
1220 serialize_as!(enum_struct:
1221 SpecialEnum::Text {
1222 before: "answer",
1223 content: (42, 42),
1224 after: "answer",
1225 }
1226 => "<Text>\n \
1227 <before>answer</before>42 42<after>answer</after>\n\
1228 </Text>");
1229 }
1230
1231 mod enum_with_text_field {
1233 use super::*;
1234 use pretty_assertions::assert_eq;
1235
1236 macro_rules! text {
1237 ($name:ident: $data:expr => $expected:literal) => {
1238 serialize_as!($name:
1239 SpecialEnum::Text {
1240 before: "answer",
1241 content: $data,
1242 after: "answer",
1243 }
1244 => concat!(
1245 "<Text>\n <before>answer</before>",
1246 $expected,
1247 "<after>answer</after>\n</Text>",
1248 ));
1249 };
1250 }
1251
1252 text!(false_: false => "false");
1253 text!(true_: true => "true");
1254
1255 text!(i8_: -42i8 => "-42");
1256 text!(i16_: -4200i16 => "-4200");
1257 text!(i32_: -42000000i32 => "-42000000");
1258 text!(i64_: -42000000000000i64 => "-42000000000000");
1259 text!(isize_: -42000000isize => "-42000000");
1260
1261 text!(u8_: 42u8 => "42");
1262 text!(u16_: 4200u16 => "4200");
1263 text!(u32_: 42000000u32 => "42000000");
1264 text!(u64_: 42000000000000u64 => "42000000000000");
1265 text!(usize_: 42000000usize => "42000000");
1266
1267 text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1268 text!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1269
1270 text!(f32_: 4.2f32 => "4.2");
1271 text!(f64_: 4.2f64 => "4.2");
1272
1273 text!(char_non_escaped: 'h' => "h");
1274 text!(char_lt: '<' => "<");
1275 text!(char_gt: '>' => ">");
1276 text!(char_amp: '&' => "&");
1277 text!(char_apos: '\'' => "'");
1278 text!(char_quot: '"' => """);
1279 text!(char_space: ' ' => " ");
1280
1281 text!(str_non_escaped: "non-escaped string" => "non-escaped string");
1282 text!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1283
1284 err!(bytes:
1285 SpecialEnum::Text {
1286 before: "answer",
1287 content: Bytes(b"<\"escaped & bytes'>"),
1288 after: "answer",
1289 }
1290 => Unsupported("`serialize_bytes` not supported yet"));
1291
1292 text!(option_none: Option::<&str>::None => "");
1293 text!(option_some: Some("non-escaped string") => "non-escaped string");
1294 text!(option_some_empty_str: Some("") => "");
1295
1296 text!(unit: () => "");
1297 text!(unit_struct: Unit => "");
1298 text!(unit_struct_escaped: UnitEscaped => "");
1299
1300 text!(enum_unit: Enum::Unit => "Unit");
1301 text!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
1302
1303 text!(newtype: Newtype(42) => "42");
1304 err!(enum_newtype:
1306 SpecialEnum::Text {
1307 before: "answer",
1308 content: Enum::Newtype(42),
1309 after: "answer",
1310 }
1311 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
1312
1313 text!(seq: vec![1, 2, 3] => "1 2 3");
1315 text!(seq_empty: Vec::<usize>::new() => "");
1316 text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1317 => "<"&'> \
1318 with	  spaces \
1319 3");
1320 text!(tuple_struct: Tuple("first", 42) => "first 42");
1321 err!(enum_tuple:
1323 SpecialEnum::Text {
1324 before: "answer",
1325 content: Enum::Tuple("first", 42),
1326 after: "answer",
1327 }
1328 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
1329
1330 err!(map:
1332 SpecialEnum::Text {
1333 before: "answer",
1334 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1335 after: "answer",
1336 }
1337 => Unsupported("cannot serialize map as text content value"));
1338 err!(struct_:
1339 SpecialEnum::Text {
1340 before: "answer",
1341 content: Struct { key: "answer", val: (42, 42) },
1342 after: "answer",
1343 }
1344 => Unsupported("cannot serialize struct `Struct` as text content value"));
1345 err!(enum_struct:
1346 SpecialEnum::Text {
1347 before: "answer",
1348 content: Enum::Struct { key: "answer", val: (42, 42) },
1349 after: "answer",
1350 }
1351 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1352 }
1353
1354 mod enum_with_value_field {
1356 use super::*;
1357 use pretty_assertions::assert_eq;
1358
1359 macro_rules! value {
1360 ($name:ident: $data:expr => $expected:literal) => {
1361 serialize_as!($name:
1362 SpecialEnum::Value {
1363 before: "answer",
1364 content: $data,
1365 after: "answer",
1366 }
1367 => concat!(
1368 "<Value>\n <before>answer</before>",
1369 $expected,
1370 "<after>answer</after>\n</Value>",
1371 ));
1372 };
1373 }
1374
1375 value!(false_: false => "false");
1376 value!(true_: true => "true");
1377
1378 value!(i8_: -42i8 => "-42");
1379 value!(i16_: -4200i16 => "-4200");
1380 value!(i32_: -42000000i32 => "-42000000");
1381 value!(i64_: -42000000000000i64 => "-42000000000000");
1382 value!(isize_: -42000000isize => "-42000000");
1383
1384 value!(u8_: 42u8 => "42");
1385 value!(u16_: 4200u16 => "4200");
1386 value!(u32_: 42000000u32 => "42000000");
1387 value!(u64_: 42000000000000u64 => "42000000000000");
1388 value!(usize_: 42000000usize => "42000000");
1389
1390 value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1391 value!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1392
1393 value!(f32_: 4.2f32 => "4.2");
1394 value!(f64_: 4.2f64 => "4.2");
1395
1396 value!(char_non_escaped: 'h' => "h");
1397 value!(char_lt: '<' => "<");
1398 value!(char_gt: '>' => ">");
1399 value!(char_amp: '&' => "&");
1400 value!(char_apos: '\'' => "'");
1401 value!(char_quot: '"' => """);
1402 value!(char_space: ' ' => " ");
1403
1404 value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1405 value!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1406
1407 err!(bytes:
1408 SpecialEnum::Value {
1409 before: "answer",
1410 content: Bytes(b"<\"escaped & bytes'>"),
1411 after: "answer",
1412 }
1413 => Unsupported("`serialize_bytes` not supported yet"));
1414
1415 value!(option_none: Option::<&str>::None => "");
1416 value!(option_some: Some("non-escaped string") => "non-escaped string");
1417 value!(option_some_empty_str: Some("") => "");
1418
1419 value!(unit: () => "\n ");
1420 value!(unit_struct: Unit => "\n ");
1421 value!(unit_struct_escaped: UnitEscaped => "\n ");
1422
1423 value!(enum_unit: Enum::Unit => "\n <Unit/>\n ");
1424 err!(enum_unit_escaped:
1425 SpecialEnum::Value {
1426 before: "answer",
1427 content: Enum::UnitEscaped,
1428 after: "answer",
1429 }
1430 => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1431
1432 value!(newtype: Newtype(42) => "42");
1433 value!(enum_newtype: Enum::Newtype(42) => "\n <Newtype>42</Newtype>\n ");
1434
1435 err!(seq:
1437 SpecialEnum::Value {
1438 before: "answer",
1439 content: vec![1, 2, 3],
1440 after: "answer",
1441 }
1442 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1443 value!(seq_empty: Vec::<usize>::new() => "");
1444 err!(tuple:
1445 SpecialEnum::Value {
1446 before: "answer",
1447 content: ("<\"&'>", "with\t\n\r spaces", 3usize),
1448 after: "answer",
1449 }
1450 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1451 err!(tuple_struct:
1452 SpecialEnum::Value {
1453 before: "answer",
1454 content: Tuple("first", 42),
1455 after: "answer",
1456 }
1457 => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1458 value!(enum_tuple: Enum::Tuple("first", 42)
1459 => "\n \
1460 <Tuple>first</Tuple>\n \
1461 <Tuple>42</Tuple>\n ");
1462
1463 err!(map:
1466 SpecialEnum::Value {
1467 before: "answer",
1468 content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1469 after: "answer",
1470 }
1471 => Unsupported("serialization of map types is not supported in `$value` field"));
1472 value!(struct_:
1473 SpecialEnum::Value {
1474 before: "answer",
1475 content: Struct { key: "answer", val: (42, 42) },
1476 after: "answer",
1477 }
1478 => "\n \
1479 <Value>\n \
1480 <before>answer</before>\n \
1481 <Struct>\n \
1482 <key>answer</key>\n \
1483 <val>42</val>\n \
1484 <val>42</val>\n \
1485 </Struct>\n \
1486 <after>answer</after>\n \
1487 </Value>\n ");
1488 value!(enum_struct:
1489 Enum::Struct { key: "answer", val: (42, 42) }
1490 => "\n \
1491 <Struct>\n \
1492 <key>answer</key>\n \
1493 <val>42</val>\n \
1494 <val>42</val>\n \
1495 </Struct>\n ");
1496 }
1497
1498 mod attributes {
1499 use super::*;
1500 use pretty_assertions::assert_eq;
1501
1502 err!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
1503 => Unsupported("serialization of map types is not supported in `$value` field"));
1504 err!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
1505 => Unsupported("serialization of map types is not supported in `$value` field"));
1506
1507 serialize_as!(struct_: Attributes { key: "answer", val: (42, 42) }
1508 => r#"<Attributes key="answer" val="42 42"/>"#);
1509 serialize_as!(struct_before: AttributesBefore { key: "answer", val: 42 }
1510 => "<AttributesBefore key=\"answer\">\n \
1511 <val>42</val>\n\
1512 </AttributesBefore>");
1513 serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
1514 => "<AttributesAfter val=\"42\">\n \
1515 <key>answer</key>\n\
1516 </AttributesAfter>");
1517
1518 serialize_as!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
1519 => r#"<Attributes key="answer" val="42 42"/>"#);
1520 serialize_as!(enum_before: Enum::AttributesBefore { key: "answer", val: 42 }
1521 => "<AttributesBefore key=\"answer\">\n \
1522 <val>42</val>\n\
1523 </AttributesBefore>");
1524 serialize_as!(enum_after: Enum::AttributesAfter { key: "answer", val: 42 }
1525 => "<AttributesAfter val=\"42\">\n \
1526 <key>answer</key>\n\
1527 </AttributesAfter>");
1528 }
1529 }
1530}