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