1use crate::errors::serialize::DeError;
7use crate::escapei::_escape;
8use crate::se::{Indent, QuoteLevel};
9use serde::ser::{
10 Impossible, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
11 SerializeTupleVariant, Serializer,
12};
13use serde::serde_if_integer128;
14use std::borrow::Cow;
15use std::fmt::Write;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum QuoteTarget {
19 Text,
21 DoubleQAttr,
23 SingleQAttr,
25}
26
27fn escape_item(value: &str, target: QuoteTarget, level: QuoteLevel) -> Cow<str> {
30 use QuoteLevel::*;
31 use QuoteTarget::*;
32
33 match (target, level) {
34 (_, Full) => _escape(value, |ch| match ch {
35 b' ' | b'\r' | b'\n' | b'\t' => true,
37 b'&' | b'<' | b'>' | b'\'' | b'\"' => true,
39 _ => false,
40 }),
41 (Text, Partial) => _escape(value, |ch| match ch {
43 b' ' | b'\r' | b'\n' | b'\t' => true,
45 b'&' | b'<' | b'>' => true,
47 _ => false,
48 }),
49 (Text, Minimal) => _escape(value, |ch| match ch {
50 b' ' | b'\r' | b'\n' | b'\t' => true,
52 b'&' | b'<' => true,
54 _ => false,
55 }),
56 (DoubleQAttr, Partial) => _escape(value, |ch| match ch {
58 b' ' | b'\r' | b'\n' | b'\t' => true,
60 b'&' | b'<' | b'>' => true,
62 b'"' => true,
64 _ => false,
65 }),
66 (DoubleQAttr, Minimal) => _escape(value, |ch| match ch {
67 b' ' | b'\r' | b'\n' | b'\t' => true,
69 b'&' | b'<' => true,
71 b'"' => true,
73 _ => false,
74 }),
75 (SingleQAttr, Partial) => _escape(value, |ch| match ch {
77 b' ' | b'\r' | b'\n' | b'\t' => true,
79 b'&' | b'<' | b'>' => true,
81 b'\'' => true,
83 _ => false,
84 }),
85 (SingleQAttr, Minimal) => _escape(value, |ch| match ch {
86 b' ' | b'\r' | b'\n' | b'\t' => true,
88 b'&' | b'<' => true,
90 b'\'' => true,
92 _ => false,
93 }),
94 }
95}
96
97fn escape_list(value: &str, target: QuoteTarget, level: QuoteLevel) -> Cow<str> {
99 use QuoteLevel::*;
100 use QuoteTarget::*;
101
102 match (target, level) {
103 (_, Full) => _escape(value, |ch| match ch {
104 b'&' | b'<' | b'>' | b'\'' | b'\"' => true,
106 _ => false,
107 }),
108 (Text, Partial) => _escape(value, |ch| match ch {
110 b'&' | b'<' | b'>' => true,
112 _ => false,
113 }),
114 (Text, Minimal) => _escape(value, |ch| match ch {
115 b'&' | b'<' => true,
117 _ => false,
118 }),
119 (DoubleQAttr, Partial) => _escape(value, |ch| match ch {
121 b'&' | b'<' | b'>' => true,
123 b'"' => true,
125 _ => false,
126 }),
127 (DoubleQAttr, Minimal) => _escape(value, |ch| match ch {
128 b'&' | b'<' => true,
130 b'"' => true,
132 _ => false,
133 }),
134 (SingleQAttr, Partial) => _escape(value, |ch| match ch {
136 b'&' | b'<' | b'>' => true,
138 b'\'' => true,
140 _ => false,
141 }),
142 (SingleQAttr, Minimal) => _escape(value, |ch| match ch {
143 b'&' | b'<' => true,
145 b'\'' => true,
147 _ => false,
148 }),
149 }
150}
151
152macro_rules! write_atomic {
155 ($method:ident ( $ty:ty )) => {
156 fn $method(mut self, value: $ty) -> Result<Self::Ok, Self::Error> {
157 self.write_str(&value.to_string())?;
158 Ok(true)
159 }
160 };
161}
162
163pub struct AtomicSerializer<'i, W: Write> {
184 pub writer: W,
185 pub target: QuoteTarget,
186 pub level: QuoteLevel,
188 pub(crate) indent: Option<Indent<'i>>,
192}
193
194impl<'i, W: Write> AtomicSerializer<'i, W> {
195 fn write_str(&mut self, value: &str) -> Result<(), DeError> {
196 if let Some(indent) = self.indent.as_mut() {
197 indent.write_indent(&mut self.writer)?;
198 } else {
199 self.writer.write_char(' ')?;
201 }
202 Ok(self.writer.write_str(value)?)
203 }
204}
205
206impl<'i, W: Write> Serializer for AtomicSerializer<'i, W> {
207 type Ok = bool;
208 type Error = DeError;
209
210 type SerializeSeq = Impossible<Self::Ok, Self::Error>;
211 type SerializeTuple = Impossible<Self::Ok, Self::Error>;
212 type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
213 type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
214 type SerializeMap = Impossible<Self::Ok, Self::Error>;
215 type SerializeStruct = Impossible<Self::Ok, Self::Error>;
216 type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
217
218 fn serialize_bool(mut self, value: bool) -> Result<Self::Ok, Self::Error> {
219 self.write_str(if value { "true" } else { "false" })?;
220 Ok(true)
221 }
222
223 write_atomic!(serialize_i8(i8));
224 write_atomic!(serialize_i16(i16));
225 write_atomic!(serialize_i32(i32));
226 write_atomic!(serialize_i64(i64));
227
228 write_atomic!(serialize_u8(u8));
229 write_atomic!(serialize_u16(u16));
230 write_atomic!(serialize_u32(u32));
231 write_atomic!(serialize_u64(u64));
232
233 serde_if_integer128! {
234 write_atomic!(serialize_i128(i128));
235 write_atomic!(serialize_u128(u128));
236 }
237
238 write_atomic!(serialize_f32(f32));
239 write_atomic!(serialize_f64(f64));
240
241 fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
242 self.serialize_str(&value.to_string())
243 }
244
245 fn serialize_str(mut self, value: &str) -> Result<Self::Ok, Self::Error> {
246 if !value.is_empty() {
247 self.write_str(&escape_item(value, self.target, self.level))?;
248 }
249 Ok(!value.is_empty())
250 }
251
252 fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
253 Err(DeError::Unsupported(
255 "`serialize_bytes` not supported yet".into(),
256 ))
257 }
258
259 fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
260 Ok(false)
261 }
262
263 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
264 value.serialize(self)
265 }
266
267 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
270 Err(DeError::Unsupported(
271 "cannot serialize unit type `()` as an `xs:list` item".into(),
272 ))
273 }
274
275 fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
278 Err(DeError::Unsupported(
279 format!(
280 "cannot serialize unit struct `{}` as an `xs:list` item",
281 name
282 )
283 .into(),
284 ))
285 }
286
287 fn serialize_unit_variant(
288 self,
289 _name: &'static str,
290 _variant_index: u32,
291 variant: &'static str,
292 ) -> Result<Self::Ok, Self::Error> {
293 self.serialize_str(variant)
294 }
295
296 fn serialize_newtype_struct<T: ?Sized + Serialize>(
297 self,
298 _name: &'static str,
299 value: &T,
300 ) -> Result<Self::Ok, Self::Error> {
301 value.serialize(self)
302 }
303
304 fn serialize_newtype_variant<T: ?Sized + Serialize>(
307 self,
308 name: &'static str,
309 _variant_index: u32,
310 variant: &'static str,
311 _value: &T,
312 ) -> Result<Self::Ok, DeError> {
313 Err(DeError::Unsupported(
314 format!(
315 "cannot serialize enum newtype variant `{}::{}` as an `xs:list` item",
316 name, variant
317 )
318 .into(),
319 ))
320 }
321
322 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
323 Err(DeError::Unsupported(
324 "cannot serialize sequence as an `xs:list` item".into(),
325 ))
326 }
327
328 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
329 Err(DeError::Unsupported(
330 "cannot serialize tuple as an `xs:list` item".into(),
331 ))
332 }
333
334 fn serialize_tuple_struct(
335 self,
336 name: &'static str,
337 _len: usize,
338 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
339 Err(DeError::Unsupported(
340 format!(
341 "cannot serialize tuple struct `{}` as an `xs:list` item",
342 name
343 )
344 .into(),
345 ))
346 }
347
348 fn serialize_tuple_variant(
349 self,
350 name: &'static str,
351 _variant_index: u32,
352 variant: &'static str,
353 _len: usize,
354 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
355 Err(DeError::Unsupported(
356 format!(
357 "cannot serialize enum tuple variant `{}::{}` as an `xs:list` item",
358 name, variant
359 )
360 .into(),
361 ))
362 }
363
364 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
365 Err(DeError::Unsupported(
366 "cannot serialize map as an `xs:list` item".into(),
367 ))
368 }
369
370 fn serialize_struct(
371 self,
372 name: &'static str,
373 _len: usize,
374 ) -> Result<Self::SerializeStruct, Self::Error> {
375 Err(DeError::Unsupported(
376 format!("cannot serialize struct `{}` as an `xs:list` item", name).into(),
377 ))
378 }
379
380 fn serialize_struct_variant(
381 self,
382 name: &'static str,
383 _variant_index: u32,
384 variant: &'static str,
385 _len: usize,
386 ) -> Result<Self::SerializeStructVariant, Self::Error> {
387 Err(DeError::Unsupported(
388 format!(
389 "cannot serialize enum struct variant `{}::{}` as an `xs:list` item",
390 name, variant
391 )
392 .into(),
393 ))
394 }
395}
396
397pub struct SimpleTypeSerializer<'i, W: Write> {
406 pub writer: W,
408 pub target: QuoteTarget,
410 pub level: QuoteLevel,
412 pub(crate) indent: Indent<'i>,
414}
415
416impl<'i, W: Write> SimpleTypeSerializer<'i, W> {
417 fn write_str(&mut self, value: &str) -> Result<(), DeError> {
418 self.indent.write_indent(&mut self.writer)?;
419 Ok(self.writer.write_str(value)?)
420 }
421}
422
423impl<'i, W: Write> Serializer for SimpleTypeSerializer<'i, W> {
424 type Ok = W;
425 type Error = DeError;
426
427 type SerializeSeq = SimpleSeq<'i, W>;
428 type SerializeTuple = SimpleSeq<'i, W>;
429 type SerializeTupleStruct = SimpleSeq<'i, W>;
430 type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
431 type SerializeMap = Impossible<Self::Ok, Self::Error>;
432 type SerializeStruct = Impossible<Self::Ok, Self::Error>;
433 type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
434
435 write_primitive!();
436
437 fn serialize_str(mut self, value: &str) -> Result<Self::Ok, Self::Error> {
438 if !value.is_empty() {
439 self.write_str(&escape_list(value, self.target, self.level))?;
440 }
441 Ok(self.writer)
442 }
443
444 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
446 Ok(self.writer)
447 }
448
449 fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
451 Ok(self.writer)
452 }
453
454 fn serialize_newtype_variant<T: ?Sized + Serialize>(
457 self,
458 name: &'static str,
459 _variant_index: u32,
460 variant: &'static str,
461 _value: &T,
462 ) -> Result<Self::Ok, DeError> {
463 Err(DeError::Unsupported(
464 format!("cannot serialize enum newtype variant `{}::{}` as an attribute or text content value", name, variant).into(),
465 ))
466 }
467
468 #[inline]
469 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
470 Ok(SimpleSeq {
471 writer: self.writer,
472 target: self.target,
473 level: self.level,
474 indent: self.indent,
475 is_empty: true,
476 })
477 }
478
479 #[inline]
480 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
481 self.serialize_seq(None)
482 }
483
484 #[inline]
485 fn serialize_tuple_struct(
486 self,
487 _name: &'static str,
488 _len: usize,
489 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
490 self.serialize_seq(None)
491 }
492
493 fn serialize_tuple_variant(
494 self,
495 name: &'static str,
496 _variant_index: u32,
497 variant: &'static str,
498 _len: usize,
499 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
500 Err(DeError::Unsupported(
501 format!("cannot serialize enum tuple variant `{}::{}` as an attribute or text content value", name, variant).into(),
502 ))
503 }
504
505 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
506 Err(DeError::Unsupported(
507 "cannot serialize map as an attribute or text content value".into(),
508 ))
509 }
510
511 fn serialize_struct(
512 self,
513 name: &'static str,
514 _len: usize,
515 ) -> Result<Self::SerializeStruct, Self::Error> {
516 Err(DeError::Unsupported(
517 format!(
518 "cannot serialize struct `{}` as an attribute or text content value",
519 name
520 )
521 .into(),
522 ))
523 }
524
525 fn serialize_struct_variant(
526 self,
527 name: &'static str,
528 _variant_index: u32,
529 variant: &'static str,
530 _len: usize,
531 ) -> Result<Self::SerializeStructVariant, Self::Error> {
532 Err(DeError::Unsupported(
533 format!("cannot serialize enum struct variant `{}::{}` as an attribute or text content value", name, variant).into(),
534 ))
535 }
536}
537
538pub struct SimpleSeq<'i, W: Write> {
540 writer: W,
541 target: QuoteTarget,
542 level: QuoteLevel,
543 indent: Indent<'i>,
545 is_empty: bool,
547}
548
549impl<'i, W: Write> SerializeSeq for SimpleSeq<'i, W> {
550 type Ok = W;
551 type Error = DeError;
552
553 fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
554 where
555 T: ?Sized + Serialize,
556 {
557 let indent = if self.is_empty {
559 Some(self.indent.borrow())
560 } else {
561 None
562 };
563 if value.serialize(AtomicSerializer {
564 writer: &mut self.writer,
565 target: self.target,
566 level: self.level,
567 indent,
568 })? {
569 self.is_empty = false;
570 }
571 Ok(())
572 }
573
574 #[inline]
575 fn end(self) -> Result<Self::Ok, Self::Error> {
576 Ok(self.writer)
577 }
578}
579
580impl<'i, W: Write> SerializeTuple for SimpleSeq<'i, W> {
581 type Ok = W;
582 type Error = DeError;
583
584 #[inline]
585 fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
586 where
587 T: ?Sized + Serialize,
588 {
589 SerializeSeq::serialize_element(self, value)
590 }
591
592 #[inline]
593 fn end(self) -> Result<Self::Ok, Self::Error> {
594 SerializeSeq::end(self)
595 }
596}
597
598impl<'i, W: Write> SerializeTupleStruct for SimpleSeq<'i, W> {
599 type Ok = W;
600 type Error = DeError;
601
602 #[inline]
603 fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
604 where
605 T: ?Sized + Serialize,
606 {
607 SerializeSeq::serialize_element(self, value)
608 }
609
610 #[inline]
611 fn end(self) -> Result<Self::Ok, Self::Error> {
612 SerializeSeq::end(self)
613 }
614}
615
616impl<'i, W: Write> SerializeTupleVariant for SimpleSeq<'i, W> {
617 type Ok = W;
618 type Error = DeError;
619
620 #[inline]
621 fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
622 where
623 T: ?Sized + Serialize,
624 {
625 SerializeSeq::serialize_element(self, value)
626 }
627
628 #[inline]
629 fn end(self) -> Result<Self::Ok, Self::Error> {
630 SerializeSeq::end(self)
631 }
632}
633
634#[cfg(test)]
637mod tests {
638 use super::*;
639 use crate::utils::Bytes;
640 use serde::Serialize;
641 use std::collections::BTreeMap;
642
643 #[derive(Debug, Serialize, PartialEq)]
644 struct Unit;
645
646 #[derive(Debug, Serialize, PartialEq)]
647 struct Newtype(usize);
648
649 #[derive(Debug, Serialize, PartialEq)]
650 struct Tuple(&'static str, usize);
651
652 #[derive(Debug, Serialize, PartialEq)]
653 struct Struct {
654 key: &'static str,
655 val: usize,
656 }
657
658 #[derive(Debug, Serialize, PartialEq)]
659 enum Enum {
660 Unit,
661 #[serde(rename = "<\"&'>")]
662 UnitEscaped,
663 Newtype(usize),
664 Tuple(&'static str, usize),
665 Struct {
666 key: &'static str,
667 val: usize,
668 },
669 }
670
671 mod escape_item {
672 use super::*;
673
674 mod full {
675 use super::*;
676 use pretty_assertions::assert_eq;
677
678 #[test]
679 fn text() {
680 assert_eq!(
681 escape_item("text<\"'&> \t\n\rtext", QuoteTarget::Text, QuoteLevel::Full),
682 "text<"'&> 	 text"
683 );
684 }
685
686 #[test]
687 fn double_quote_attr() {
688 assert_eq!(
689 escape_item(
690 "text<\"'&> \t\n\rtext",
691 QuoteTarget::DoubleQAttr,
692 QuoteLevel::Full
693 ),
694 "text<"'&> 	 text"
695 );
696 }
697
698 #[test]
699 fn single_quote_attr() {
700 assert_eq!(
701 escape_item(
702 "text<\"'&> \t\n\rtext",
703 QuoteTarget::SingleQAttr,
704 QuoteLevel::Full
705 ),
706 "text<"'&> 	 text"
707 );
708 }
709 }
710
711 mod partial {
712 use super::*;
713 use pretty_assertions::assert_eq;
714
715 #[test]
716 fn text() {
717 assert_eq!(
718 escape_item(
719 "text<\"'&> \t\n\rtext",
720 QuoteTarget::Text,
721 QuoteLevel::Partial
722 ),
723 "text<\"'&> 	 text"
724 );
725 }
726
727 #[test]
728 fn double_quote_attr() {
729 assert_eq!(
730 escape_item(
731 "text<\"'&> \t\n\rtext",
732 QuoteTarget::DoubleQAttr,
733 QuoteLevel::Partial
734 ),
735 "text<"'&> 	 text"
736 );
737 }
738
739 #[test]
740 fn single_quote_attr() {
741 assert_eq!(
742 escape_item(
743 "text<\"'&> \t\n\rtext",
744 QuoteTarget::SingleQAttr,
745 QuoteLevel::Partial
746 ),
747 "text<\"'&> 	 text"
748 );
749 }
750 }
751
752 mod minimal {
753 use super::*;
754 use pretty_assertions::assert_eq;
755
756 #[test]
757 fn text() {
758 assert_eq!(
759 escape_item(
760 "text<\"'&> \t\n\rtext",
761 QuoteTarget::Text,
762 QuoteLevel::Minimal
763 ),
764 "text<\"'&> 	 text"
765 );
766 }
767
768 #[test]
769 fn double_quote_attr() {
770 assert_eq!(
771 escape_item(
772 "text<\"'&> \t\n\rtext",
773 QuoteTarget::DoubleQAttr,
774 QuoteLevel::Minimal
775 ),
776 "text<"'&> 	 text"
777 );
778 }
779
780 #[test]
781 fn single_quote_attr() {
782 assert_eq!(
783 escape_item(
784 "text<\"'&> \t\n\rtext",
785 QuoteTarget::SingleQAttr,
786 QuoteLevel::Minimal
787 ),
788 "text<\"'&> 	 text"
789 );
790 }
791 }
792 }
793
794 mod escape_list {
795 use super::*;
796
797 mod full {
798 use super::*;
799 use pretty_assertions::assert_eq;
800
801 #[test]
802 fn text() {
803 assert_eq!(
804 escape_list("text<\"'&> \t\n\rtext", QuoteTarget::Text, QuoteLevel::Full),
805 "text<"'&> \t\n\rtext"
806 );
807 }
808
809 #[test]
810 fn double_quote_attr() {
811 assert_eq!(
812 escape_list(
813 "text<\"'&> \t\n\rtext",
814 QuoteTarget::DoubleQAttr,
815 QuoteLevel::Full
816 ),
817 "text<"'&> \t\n\rtext"
818 );
819 }
820
821 #[test]
822 fn single_quote_attr() {
823 assert_eq!(
824 escape_list(
825 "text<\"'&> \t\n\rtext",
826 QuoteTarget::SingleQAttr,
827 QuoteLevel::Full
828 ),
829 "text<"'&> \t\n\rtext"
830 );
831 }
832 }
833
834 mod partial {
835 use super::*;
836 use pretty_assertions::assert_eq;
837
838 #[test]
839 fn text() {
840 assert_eq!(
841 escape_list(
842 "text<\"'&> \t\n\rtext",
843 QuoteTarget::Text,
844 QuoteLevel::Partial
845 ),
846 "text<\"'&> \t\n\rtext"
847 );
848 }
849
850 #[test]
851 fn double_quote_attr() {
852 assert_eq!(
853 escape_list(
854 "text<\"'&> \t\n\rtext",
855 QuoteTarget::DoubleQAttr,
856 QuoteLevel::Partial
857 ),
858 "text<"'&> \t\n\rtext"
859 );
860 }
861
862 #[test]
863 fn single_quote_attr() {
864 assert_eq!(
865 escape_list(
866 "text<\"'&> \t\n\rtext",
867 QuoteTarget::SingleQAttr,
868 QuoteLevel::Partial
869 ),
870 "text<\"'&> \t\n\rtext"
871 );
872 }
873 }
874
875 mod minimal {
876 use super::*;
877 use pretty_assertions::assert_eq;
878
879 #[test]
880 fn text() {
881 assert_eq!(
882 escape_list(
883 "text<\"'&> \t\n\rtext",
884 QuoteTarget::Text,
885 QuoteLevel::Minimal
886 ),
887 "text<\"'&> \t\n\rtext"
888 );
889 }
890
891 #[test]
892 fn double_quote_attr() {
893 assert_eq!(
894 escape_list(
895 "text<\"'&> \t\n\rtext",
896 QuoteTarget::DoubleQAttr,
897 QuoteLevel::Minimal
898 ),
899 "text<"'&> \t\n\rtext"
900 );
901 }
902
903 #[test]
904 fn single_quote_attr() {
905 assert_eq!(
906 escape_list(
907 "text<\"'&> \t\n\rtext",
908 QuoteTarget::SingleQAttr,
909 QuoteLevel::Minimal
910 ),
911 "text<\"'&> \t\n\rtext"
912 );
913 }
914 }
915 }
916
917 mod atomic {
919 use super::*;
920 use pretty_assertions::assert_eq;
921
922 macro_rules! serialize_as {
924 ($name:ident: $data:expr => $expected:literal) => {
925 #[test]
926 fn $name() {
927 let mut buffer = String::new();
928 let ser = AtomicSerializer {
929 writer: &mut buffer,
930 target: QuoteTarget::Text,
931 level: QuoteLevel::Full,
932 indent: Some(Indent::None),
933 };
934
935 let has_written = $data.serialize(ser).unwrap();
936 assert_eq!(buffer, $expected);
937 assert_eq!(has_written, !buffer.is_empty());
938 }
939 };
940 }
941
942 macro_rules! err {
945 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
946 #[test]
947 fn $name() {
948 let mut buffer = String::new();
949 let ser = AtomicSerializer {
950 writer: &mut buffer,
951 target: QuoteTarget::Text,
952 level: QuoteLevel::Full,
953 indent: Some(Indent::None),
954 };
955
956 match $data.serialize(ser).unwrap_err() {
957 DeError::$kind(e) => assert_eq!(e, $reason),
958 e => panic!(
959 "Expected `{}({})`, found `{:?}`",
960 stringify!($kind),
961 $reason,
962 e
963 ),
964 }
965 assert_eq!(buffer, "");
966 }
967 };
968 }
969
970 serialize_as!(false_: false => "false");
971 serialize_as!(true_: true => "true");
972
973 serialize_as!(i8_: -42i8 => "-42");
974 serialize_as!(i16_: -4200i16 => "-4200");
975 serialize_as!(i32_: -42000000i32 => "-42000000");
976 serialize_as!(i64_: -42000000000000i64 => "-42000000000000");
977 serialize_as!(isize_: -42000000000000isize => "-42000000000000");
978
979 serialize_as!(u8_: 42u8 => "42");
980 serialize_as!(u16_: 4200u16 => "4200");
981 serialize_as!(u32_: 42000000u32 => "42000000");
982 serialize_as!(u64_: 42000000000000u64 => "42000000000000");
983 serialize_as!(usize_: 42000000000000usize => "42000000000000");
984
985 serde_if_integer128! {
986 serialize_as!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
987 serialize_as!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
988 }
989
990 serialize_as!(f32_: 4.2f32 => "4.2");
991 serialize_as!(f64_: 4.2f64 => "4.2");
992
993 serialize_as!(char_non_escaped: 'h' => "h");
994 serialize_as!(char_lt: '<' => "<");
995 serialize_as!(char_gt: '>' => ">");
996 serialize_as!(char_amp: '&' => "&");
997 serialize_as!(char_apos: '\'' => "'");
998 serialize_as!(char_quot: '"' => """);
999
1000 serialize_as!(str_non_escaped: "non-escaped-string" => "non-escaped-string");
1001 serialize_as!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1002
1003 err!(bytes: Bytes(b"<\"escaped & bytes'>")
1004 => Unsupported("`serialize_bytes` not supported yet"));
1005
1006 serialize_as!(option_none: Option::<&str>::None => "");
1007 serialize_as!(option_some: Some("non-escaped-string") => "non-escaped-string");
1008
1009 err!(unit: ()
1010 => Unsupported("cannot serialize unit type `()` as an `xs:list` item"));
1011 err!(unit_struct: Unit
1012 => Unsupported("cannot serialize unit struct `Unit` as an `xs:list` item"));
1013
1014 serialize_as!(enum_unit: Enum::Unit => "Unit");
1015 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
1016
1017 serialize_as!(newtype: Newtype(42) => "42");
1018 err!(enum_newtype: Enum::Newtype(42)
1019 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as an `xs:list` item"));
1020
1021 err!(seq: vec![1, 2, 3]
1022 => Unsupported("cannot serialize sequence as an `xs:list` item"));
1023 err!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1024 => Unsupported("cannot serialize tuple as an `xs:list` item"));
1025 err!(tuple_struct: Tuple("first", 42)
1026 => Unsupported("cannot serialize tuple struct `Tuple` as an `xs:list` item"));
1027 err!(enum_tuple: Enum::Tuple("first", 42)
1028 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as an `xs:list` item"));
1029
1030 err!(map: BTreeMap::from([(1, 2), (3, 4)])
1031 => Unsupported("cannot serialize map as an `xs:list` item"));
1032 err!(struct_: Struct { key: "answer", val: 42 }
1033 => Unsupported("cannot serialize struct `Struct` as an `xs:list` item"));
1034 err!(enum_struct: Enum::Struct { key: "answer", val: 42 }
1035 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as an `xs:list` item"));
1036 }
1037
1038 mod simple_type {
1039 use super::*;
1040 use pretty_assertions::assert_eq;
1041
1042 macro_rules! serialize_as {
1044 ($name:ident: $data:expr => $expected:literal) => {
1045 #[test]
1046 fn $name() {
1047 let ser = SimpleTypeSerializer {
1048 writer: String::new(),
1049 target: QuoteTarget::Text,
1050 level: QuoteLevel::Full,
1051 indent: Indent::None,
1052 };
1053
1054 let buffer = $data.serialize(ser).unwrap();
1055 assert_eq!(buffer, $expected);
1056 }
1057 };
1058 }
1059
1060 macro_rules! err {
1063 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
1064 #[test]
1065 fn $name() {
1066 let mut buffer = String::new();
1067 let ser = SimpleTypeSerializer {
1068 writer: &mut buffer,
1069 target: QuoteTarget::Text,
1070 level: QuoteLevel::Full,
1071 indent: Indent::None,
1072 };
1073
1074 match $data.serialize(ser).unwrap_err() {
1075 DeError::$kind(e) => assert_eq!(e, $reason),
1076 e => panic!(
1077 "Expected `{}({})`, found `{:?}`",
1078 stringify!($kind),
1079 $reason,
1080 e
1081 ),
1082 }
1083 assert_eq!(buffer, "");
1084 }
1085 };
1086 }
1087
1088 serialize_as!(false_: false => "false");
1089 serialize_as!(true_: true => "true");
1090
1091 serialize_as!(i8_: -42i8 => "-42");
1092 serialize_as!(i16_: -4200i16 => "-4200");
1093 serialize_as!(i32_: -42000000i32 => "-42000000");
1094 serialize_as!(i64_: -42000000000000i64 => "-42000000000000");
1095 serialize_as!(isize_: -42000000000000isize => "-42000000000000");
1096
1097 serialize_as!(u8_: 42u8 => "42");
1098 serialize_as!(u16_: 4200u16 => "4200");
1099 serialize_as!(u32_: 42000000u32 => "42000000");
1100 serialize_as!(u64_: 42000000000000u64 => "42000000000000");
1101 serialize_as!(usize_: 42000000000000usize => "42000000000000");
1102
1103 serde_if_integer128! {
1104 serialize_as!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1105 serialize_as!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
1106 }
1107
1108 serialize_as!(f32_: 4.2f32 => "4.2");
1109 serialize_as!(f64_: 4.2f64 => "4.2");
1110
1111 serialize_as!(char_non_escaped: 'h' => "h");
1112 serialize_as!(char_lt: '<' => "<");
1113 serialize_as!(char_gt: '>' => ">");
1114 serialize_as!(char_amp: '&' => "&");
1115 serialize_as!(char_apos: '\'' => "'");
1116 serialize_as!(char_quot: '"' => """);
1117
1118 serialize_as!(str_non_escaped: "non-escaped string" => "non-escaped string");
1119 serialize_as!(str_escaped: "<\"escaped & string'>" => "<"escaped & string'>");
1120
1121 err!(bytes: Bytes(b"<\"escaped & bytes'>")
1122 => Unsupported("`serialize_bytes` not supported yet"));
1123
1124 serialize_as!(option_none: Option::<&str>::None => "");
1125 serialize_as!(option_some: Some("non-escaped string") => "non-escaped string");
1126
1127 serialize_as!(unit: () => "");
1128 serialize_as!(unit_struct: Unit => "");
1129
1130 serialize_as!(enum_unit: Enum::Unit => "Unit");
1131 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<"&'>");
1132
1133 serialize_as!(newtype: Newtype(42) => "42");
1134 err!(enum_newtype: Enum::Newtype(42)
1135 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as an attribute or text content value"));
1136
1137 serialize_as!(seq: vec![1, 2, 3] => "1 2 3");
1138 serialize_as!(seq_empty: Vec::<usize>::new() => "");
1139 serialize_as!(seq_with_1_empty_str: vec![""] => "");
1140 serialize_as!(seq_with_2_empty_strs: vec!["", ""] => "");
1141 serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1142 => "<"&'> with	  spaces 3");
1143 serialize_as!(tuple_struct: Tuple("first", 42) => "first 42");
1144 err!(enum_tuple: Enum::Tuple("first", 42)
1145 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as an attribute or text content value"));
1146
1147 err!(map: BTreeMap::from([(1, 2), (3, 4)])
1148 => Unsupported("cannot serialize map as an attribute or text content value"));
1149 err!(struct_: Struct { key: "answer", val: 42 }
1150 => Unsupported("cannot serialize struct `Struct` as an attribute or text content value"));
1151 err!(enum_struct: Enum::Struct { key: "answer", val: 42 }
1152 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as an attribute or text content value"));
1153 }
1154
1155 mod simple_seq {
1156 use super::*;
1157 use crate::writer::Indentation;
1158 use pretty_assertions::assert_eq;
1159
1160 #[test]
1161 fn empty_seq() {
1162 let mut buffer = String::new();
1163 let mut indent = Indentation::new(b'*', 2);
1164 indent.grow();
1165 let ser = SimpleSeq {
1166 writer: &mut buffer,
1167 target: QuoteTarget::Text,
1168 level: QuoteLevel::Full,
1169 indent: Indent::Owned(indent),
1170 is_empty: true,
1171 };
1172
1173 SerializeSeq::end(ser).unwrap();
1174 assert_eq!(buffer, "");
1175 }
1176
1177 #[test]
1178 fn all_items_empty() {
1179 let mut buffer = String::new();
1180 let mut indent = Indentation::new(b'*', 2);
1181 indent.grow();
1182 let mut ser = SimpleSeq {
1183 writer: &mut buffer,
1184 target: QuoteTarget::Text,
1185 level: QuoteLevel::Full,
1186 indent: Indent::Owned(indent),
1187 is_empty: true,
1188 };
1189
1190 SerializeSeq::serialize_element(&mut ser, "").unwrap();
1191 SerializeSeq::serialize_element(&mut ser, "").unwrap();
1192 SerializeSeq::serialize_element(&mut ser, "").unwrap();
1193 SerializeSeq::end(ser).unwrap();
1194 assert_eq!(buffer, "");
1195 }
1196
1197 #[test]
1198 fn some_items_empty1() {
1199 let mut buffer = String::new();
1200 let mut indent = Indentation::new(b'*', 2);
1201 indent.grow();
1202 let mut ser = SimpleSeq {
1203 writer: &mut buffer,
1204 target: QuoteTarget::Text,
1205 level: QuoteLevel::Full,
1206 indent: Indent::Owned(indent),
1207 is_empty: true,
1208 };
1209
1210 SerializeSeq::serialize_element(&mut ser, "").unwrap();
1211 SerializeSeq::serialize_element(&mut ser, &1).unwrap();
1212 SerializeSeq::serialize_element(&mut ser, "").unwrap();
1213 SerializeSeq::end(ser).unwrap();
1214 assert_eq!(buffer, "\n**1");
1215 }
1216
1217 #[test]
1218 fn some_items_empty2() {
1219 let mut buffer = String::new();
1220 let mut indent = Indentation::new(b'*', 2);
1221 indent.grow();
1222 let mut ser = SimpleSeq {
1223 writer: &mut buffer,
1224 target: QuoteTarget::Text,
1225 level: QuoteLevel::Full,
1226 indent: Indent::Owned(indent),
1227 is_empty: true,
1228 };
1229
1230 SerializeSeq::serialize_element(&mut ser, &1).unwrap();
1231 SerializeSeq::serialize_element(&mut ser, "").unwrap();
1232 SerializeSeq::serialize_element(&mut ser, &2).unwrap();
1233 SerializeSeq::end(ser).unwrap();
1234 assert_eq!(buffer, "\n**1 2");
1235 }
1236
1237 #[test]
1238 fn items() {
1239 let mut buffer = String::new();
1240 let mut indent = Indentation::new(b'*', 2);
1241 indent.grow();
1242 let mut ser = SimpleSeq {
1243 writer: &mut buffer,
1244 target: QuoteTarget::Text,
1245 level: QuoteLevel::Full,
1246 indent: Indent::Owned(indent),
1247 is_empty: true,
1248 };
1249
1250 SerializeSeq::serialize_element(&mut ser, &1).unwrap();
1251 SerializeSeq::serialize_element(&mut ser, &2).unwrap();
1252 SerializeSeq::serialize_element(&mut ser, &3).unwrap();
1253 SerializeSeq::end(ser).unwrap();
1254 assert_eq!(buffer, "\n**1 2 3");
1255 }
1256 }
1257}