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