1use std::borrow::Cow;
2use std::fmt::Write as _;
3
4use deser_core::__format::{Float, format_finite};
5use deser_core::ext::Number;
6use deser_core::hints::Layout;
7use deser_core::ser::{self, Describe, PausableSink, SerializeDriver, Written};
8use deser_core::{Atom, BytesFormat, Error, ErrorKind, Event, Serialize, State};
9
10use crate::Names;
11use crate::de::XML_NAMESPACE;
12use crate::mixed::KeepsWhitespace;
13use crate::root::{Declarations, RootData};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
19#[non_exhaustive]
20pub enum Indent {
21 #[default]
23 None,
24 Spaces(usize),
27 Tab,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct SerializerConfig {
81 names: Names,
82 root: Option<&'static str>,
83 declaration: bool,
84 bytes: BytesFormat,
85 indent: Indent,
86}
87
88impl Default for SerializerConfig {
89 fn default() -> SerializerConfig {
90 SerializerConfig::new()
91 }
92}
93
94impl SerializerConfig {
95 pub const fn new() -> SerializerConfig {
97 SerializerConfig {
98 names: Names::new(),
99 root: None,
100 declaration: false,
101 bytes: BytesFormat::BASE64,
102 indent: Indent::None,
103 }
104 }
105
106 pub const fn root(mut self, name: &'static str) -> SerializerConfig {
114 self.root = Some(name);
115 self
116 }
117
118 pub const fn attribute_prefix(mut self, prefix: &'static str) -> SerializerConfig {
120 self.names.attribute_prefix = prefix;
121 self
122 }
123
124 pub const fn text_key(mut self, key: &'static str) -> SerializerConfig {
126 self.names.text_key = key;
127 self
128 }
129
130 pub const fn namespaces(
178 mut self,
179 namespaces: &'static [(&'static str, &'static str)],
180 ) -> SerializerConfig {
181 self.names.namespaces = namespaces;
182 self
183 }
184
185 pub const fn declaration(mut self, yes: bool) -> SerializerConfig {
187 self.declaration = yes;
188 self
189 }
190
191 pub const fn indent(mut self, indent: Indent) -> SerializerConfig {
237 self.indent = indent;
238 self
239 }
240
241 pub const fn pretty(self, indent: Indent) -> SerializerConfig {
259 self.indent(indent)
260 }
261
262 pub const fn bytes(mut self, format: BytesFormat) -> SerializerConfig {
264 self.bytes = format;
265 self
266 }
267
268 pub fn to_string(&self, value: &dyn Serialize) -> Result<String, Error> {
270 self.to_string_with(value, |_| {})
271 }
272
273 pub fn to_string_with<F>(&self, value: &dyn Serialize, setup: F) -> Result<String, Error>
278 where
279 F: FnOnce(&mut SerializeDriver<'_>),
280 {
281 let mut driver = SerializeDriver::new(value);
282 setup(&mut driver);
283 self.serialize_driver(&mut driver)
284 }
285
286 fn serialize_driver(&self, driver: &mut SerializeDriver<'_>) -> Result<String, Error> {
288 let mut writer = Writer::new(self);
289 driver.drive_described(|event, value, state| writer.event(event, value, state))?;
290 writer.finish()?;
291 Ok(writer.out)
292 }
293
294 pub(crate) fn serialize_part(
304 &self,
305 value: &mut Option<Box<Writer>>,
306 driver: &mut SerializeDriver<'_>,
307 out: &mut String,
308 limit: usize,
309 ) -> Result<bool, Error> {
310 if value.is_none() && limit == usize::MAX {
312 let document = self.serialize_driver(driver)?;
313 if out.is_empty() {
314 *out = document;
315 } else {
316 out.push_str(&document);
317 }
318 return Ok(true);
319 }
320 let mut writer = value.take().unwrap_or_else(|| Box::new(Writer::new(self)));
321 let done = if limit == usize::MAX {
323 driver.drive_described(|event, value, state| writer.event(event, value, state))?;
324 true
325 } else {
326 writer.limit = limit;
327 driver.drive_until(&mut *writer)?
328 };
329 if let Some(err) = writer.error.take() {
330 return Err(err);
331 }
332 if done {
333 writer.finish()?;
334 out.push_str(&writer.out);
335 return Ok(true);
336 }
337 writer.pass_on(out);
338 *value = Some(writer);
339 Ok(false)
340 }
341}
342
343pub struct Serializer {
378 config: SerializerConfig,
379 out: String,
380 written: bool,
381 document: Option<Box<Writer>>,
383 in_progress: bool,
385}
386
387impl Default for Serializer {
388 fn default() -> Serializer {
389 Serializer::new()
390 }
391}
392
393impl Clone for Serializer {
394 fn clone(&self) -> Serializer {
400 Serializer {
401 config: self.config.clone(),
402 out: self.out.clone(),
403 written: self.written,
404 document: None,
405 in_progress: self.in_progress,
406 }
407 }
408}
409
410impl std::fmt::Debug for Serializer {
411 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
412 f.debug_struct("Serializer")
413 .field("config", &self.config)
414 .field("output", &self.out)
415 .field("written", &self.written)
416 .field("in_progress", &self.in_progress)
417 .finish()
418 }
419}
420
421impl Serializer {
422 pub fn new() -> Serializer {
424 Serializer::with_config(&SerializerConfig::new())
425 }
426
427 pub fn with_config(config: &SerializerConfig) -> Serializer {
429 Serializer {
430 config: config.clone(),
431 out: String::new(),
432 written: false,
433 document: None,
434 in_progress: false,
435 }
436 }
437
438 pub fn config(&self) -> &SerializerConfig {
440 &self.config
441 }
442
443 pub fn written(&self) -> bool {
445 self.written
446 }
447
448 pub fn serialize(&mut self, value: &dyn Serialize) -> Result<(), Error> {
452 ser::Serializer::serialize(self, value)
453 }
454
455 pub fn serialize_with<F>(&mut self, value: &dyn Serialize, setup: F) -> Result<(), Error>
460 where
461 F: FnOnce(&mut SerializeDriver<'_>),
462 {
463 ser::Serializer::serialize_with(self, value, setup)
464 }
465
466 pub fn as_str(&self) -> &str {
468 &self.out
469 }
470
471 pub fn finish(self) -> String {
473 self.out
474 }
475}
476
477impl ser::Serializer for Serializer {
478 fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
479 if self.in_progress {
481 return Err(Error::in_progress());
482 }
483 ser::StreamSerializer::drive_partial(self, driver, usize::MAX).map(|_| ())
484 }
485}
486
487impl ser::StreamSerializer for Serializer {
488 fn output(&self) -> &[u8] {
489 self.out.as_bytes()
490 }
491
492 fn clear_output(&mut self) {
493 self.out.clear();
494 }
495
496 fn supports_partial(&self) -> bool {
497 true
498 }
499
500 fn drive_partial(
501 &mut self,
502 driver: &mut SerializeDriver<'_>,
503 limit: usize,
504 ) -> Result<Written, Error> {
505 if self.document.is_none() {
506 if self.in_progress {
507 return Err(Error::in_progress());
508 }
509 if self.written {
510 return Err(Error::new(
511 ErrorKind::Unexpected,
512 "an XML document holds a single root element",
513 ));
514 }
515 }
516 if !self
519 .config
520 .serialize_part(&mut self.document, driver, &mut self.out, limit)?
521 {
522 self.in_progress = true;
523 return Ok(Written::Partial);
524 }
525 self.in_progress = false;
526 self.written = true;
527 Ok(Written::Done)
528 }
529
530 fn in_progress(&self) -> bool {
531 self.in_progress
532 }
533}
534
535#[cfg(feature = "io")]
536impl SerializerConfig {
537 pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
562 deser_core::io::Writer::new(writer, Serializer::with_config(self))
563 }
564
565 pub fn to_writer<W: std::io::Write>(
569 &self,
570 writer: W,
571 value: &dyn Serialize,
572 ) -> Result<(), Error> {
573 self.writer(writer).write(value)
574 }
575}
576
577#[cfg(feature = "io")]
595pub fn to_writer<W: std::io::Write>(writer: W, value: &dyn Serialize) -> Result<(), Error> {
596 SerializerConfig::new().to_writer(writer, value)
597}
598
599pub fn to_string(value: &dyn Serialize) -> Result<String, Error> {
603 SerializerConfig::new().to_string(value)
604}
605
606enum Frame {
608 Element(Element),
609 Items {
611 name: String,
612 compact: bool,
614 started: bool,
616 },
617}
618
619#[derive(Clone, Copy, PartialEq, Eq)]
621enum Lines {
622 Pending,
624 Indented,
626 Inline,
628}
629
630struct Element {
632 name: String,
634 attrs_at: usize,
636 content: bool,
638 late: String,
641 attrs: Attrs,
643 fields: Option<(&'static [&'static str], usize)>,
646 bindings: usize,
648 lines: Lines,
650 expanded: bool,
652}
653
654enum Attrs {
659 Unknown,
661 Until(usize),
664 Done,
666}
667
668enum Key {
670 Attribute {
672 name: String,
673 last: bool,
674 },
675 Text,
676 Element(String),
677}
678
679pub(crate) struct Writer {
681 config: SerializerConfig,
682 out: String,
685 base: usize,
686 limit: usize,
689 error: Option<Error>,
691 stack: Vec<Frame>,
692 key: Option<Key>,
694 root_bindings: Vec<(String, String)>,
697 root_declared: bool,
700 root_declarations: Option<usize>,
702 local_bindings: Vec<(String, String)>,
704 depth: usize,
706}
707
708#[derive(Default)]
710struct TypeName(Option<String>);
711
712impl Describe for TypeName {
713 fn structure(&mut self, name: &str) {
714 self.0.get_or_insert_with(|| name.to_string());
715 }
716
717 fn newtype(&mut self, name: &str) {
718 self.0.get_or_insert_with(|| name.to_string());
719 }
720
721 fn tuple_struct(&mut self, name: &str) {
722 self.0.get_or_insert_with(|| name.to_string());
723 }
724
725 fn unit_struct(&mut self, name: &str) {
726 self.0.get_or_insert_with(|| name.to_string());
727 }
728}
729
730#[derive(Default)]
736struct Fields {
737 names: Option<&'static [&'static str]>,
738 variant: bool,
739}
740
741impl Describe for Fields {
742 fn structure(&mut self, _name: &str) {
743 self.names = None;
744 }
745
746 fn fields(&mut self, names: &'static [&'static str]) {
747 self.names = Some(names);
748 }
749
750 fn variant(&mut self, _variant: &deser_core::ser::Variant<'_>) {
751 self.variant = true;
752 }
753}
754
755impl PausableSink for Writer {
756 const DESCRIBED: bool = true;
757
758 fn event(
759 &mut self,
760 event: Event<'_>,
761 value: &dyn Serialize,
762 state: &mut State,
763 ) -> Result<(), Error> {
764 Writer::event(self, event, value, state)
765 }
766
767 fn pause(&mut self) -> bool {
768 if self.final_until() - self.base < self.limit {
772 return false;
773 }
774 if let Err(err) = self.final_len() {
775 self.error = Some(err);
777 }
778 true
779 }
780}
781
782impl Writer {
783 fn new(config: &SerializerConfig) -> Writer {
784 let mut out = String::new();
785 if config.declaration {
786 out.push_str("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
787 if config.indent != Indent::None {
788 out.push('\n');
789 }
790 }
791 Writer {
792 config: config.clone(),
793 out,
794 base: 0,
795 limit: usize::MAX,
796 error: None,
797 stack: Vec::new(),
798 key: None,
799 root_bindings: std::iter::once(("xml", XML_NAMESPACE))
800 .chain(config.names.namespaces.iter().copied())
801 .map(|(prefix, uri)| (prefix.to_string(), uri.to_string()))
802 .collect(),
803 root_declared: false,
804 root_declarations: None,
805 local_bindings: Vec::new(),
806 depth: 0,
807 }
808 }
809
810 fn event(
811 &mut self,
812 event: Event<'_>,
813 value: &dyn Serialize,
814 state: &State,
815 ) -> Result<(), Error> {
816 match self.stack.last_mut() {
817 None => self.root(event, value, state)?,
818 Some(Frame::Items { .. }) => self.item(event, value, state)?,
819 Some(Frame::Element(element)) => match self.key.take() {
820 None => {
821 if matches!(event, Event::Atom(_)) && keeps_whitespace(state) {
824 element.lines = Lines::Inline;
825 }
826 self.key(event)?
827 }
828 Some(key) => self.entry(key, event, value, state)?,
829 },
830 }
831 Ok(())
832 }
833
834 fn root(
835 &mut self,
836 event: Event<'_>,
837 value: &dyn Serialize,
838 state: &State,
839 ) -> Result<(), Error> {
840 let root = state.event::<RootData>();
844 if let Some(root) = root {
845 self.bind_root(&root.namespaces)?;
846 }
847 let name = match root.and_then(|root| root.name.clone()) {
848 Some(name) => name,
849 None => {
850 let mut name = TypeName::default();
851 value.describe(&mut name);
852 name.0
853 .or_else(|| self.config.root.map(str::to_string))
854 .ok_or_else(|| {
855 Error::new(
856 ErrorKind::UnsupportedType,
857 "the name of the root element is unknown (see deser_xml::Root)",
858 )
859 })?
860 }
861 };
862 check_element_name(&name)?;
863 match event {
864 Event::MapStart(_) => self.open_element(&name, value, state),
865 Event::Atom(atom) => self.atom_element(&name, &atom, true, state),
866 _ => Err(Error::new(
867 ErrorKind::UnsupportedType,
868 "the root element must be a map or a single value",
869 )),
870 }
871 }
872
873 fn bind_root(&mut self, namespaces: &[(String, String)]) -> Result<(), Error> {
878 let mut bindings = vec![self.root_bindings[0].clone()];
879 for (prefix, uri) in namespaces {
880 check_prefix(prefix)?;
881 if !bindings.iter().any(|(x, _)| x == prefix) {
882 bindings.push((prefix.clone(), uri.clone()));
883 }
884 }
885 for binding in self.root_bindings.drain(1..) {
886 if !bindings.iter().any(|(x, _)| *x == binding.0) {
887 bindings.push(binding);
888 }
889 }
890 self.root_bindings = bindings;
891 Ok(())
892 }
893
894 fn key(&mut self, event: Event<'_>) -> Result<(), Error> {
895 let key = match event {
896 Event::MapEnd => return self.close_element(),
897 Event::Atom(ref atom) => match self.text(atom)? {
898 Some(key) => key.into_owned(),
899 None => return Err(unsupported_key()),
900 },
901 _ => return Err(unsupported_key()),
902 };
903
904 let Some(Frame::Element(element)) = self.stack.last_mut() else {
906 unreachable!()
907 };
908 let mut is_last = false;
909 if let Some((names, cursor)) = &mut element.fields {
910 match names[*cursor..].iter().position(|name| *name == key) {
911 Some(offset) => {
912 *cursor += offset + 1;
913 if let Attrs::Until(last) = element.attrs {
914 is_last = *cursor == last + 1;
915 if *cursor > last + 1 {
916 element.attrs = Attrs::Done;
917 }
918 }
919 }
920 None => {
922 element.fields = None;
923 if matches!(element.attrs, Attrs::Until(_)) {
924 element.attrs = Attrs::Unknown;
925 }
926 }
927 }
928 }
929
930 let names = &self.config.names;
931 self.key = Some(if key == names.text_key {
932 Key::Text
933 } else if let Some(name) = attribute_name(names, &key) {
934 check_element_name(name)?;
935 Key::Attribute {
936 name: name.to_string(),
937 last: is_last,
938 }
939 } else {
940 check_element_name(&key)?;
941 Key::Element(key)
942 });
943 self.settle();
944 Ok(())
945 }
946
947 fn entry(
948 &mut self,
949 key: Key,
950 event: Event<'_>,
951 value: &dyn Serialize,
952 state: &State,
953 ) -> Result<(), Error> {
954 match (key, event) {
955 (Key::Attribute { name, last }, Event::Atom(atom)) => {
956 if let Some(text) = self.text(&atom)? {
957 let text = text.into_owned();
958 self.attribute(&name, &text)?;
959 }
960 if last && let Some(Frame::Element(element)) = self.stack.last_mut() {
961 element.attrs = Attrs::Done;
962 self.settle();
963 }
964 Ok(())
965 }
966 (Key::Text, Event::Atom(atom)) => {
967 if let Some(text) = self.text(&atom)? {
968 let text = text.into_owned();
969 self.close_start_tag();
970 if !text.is_empty() {
971 let Some(Frame::Element(element)) = self.stack.last_mut() else {
973 unreachable!()
974 };
975 element.lines = Lines::Inline;
976 }
977 escape(&text, false, &mut self.out)?;
978 }
979 Ok(())
980 }
981 (Key::Element(name), Event::Atom(atom)) => {
982 self.atom_element(&name, &atom, false, state)
983 }
984 (Key::Element(name), Event::MapStart(_)) => {
985 self.before_child();
986 self.open_element(&name, value, state)
987 }
988 (Key::Element(name), Event::SeqStart(_)) => {
989 self.stack.push(Frame::Items {
990 name,
991 compact: Layout::of(state) == Layout::Compact,
992 started: false,
993 });
994 Ok(())
995 }
996 (Key::Attribute { name, .. }, _) => Err(Error::new(
997 ErrorKind::UnsupportedType,
998 format!("attribute `{name}` must be a single value"),
999 )),
1000 (Key::Text, _) => Err(Error::new(
1001 ErrorKind::UnsupportedType,
1002 "the text of an element must be a single value",
1003 )),
1004 (Key::Element(_), _) => unreachable!("ends are handled by the frames"),
1005 }
1006 }
1007
1008 fn item(
1009 &mut self,
1010 event: Event<'_>,
1011 value: &dyn Serialize,
1012 state: &State,
1013 ) -> Result<(), Error> {
1014 let Some(Frame::Items { name, .. }) = self.stack.last() else {
1015 unreachable!()
1016 };
1017 let name = name.clone();
1018 match event {
1019 Event::SeqEnd => {
1020 self.stack.pop();
1021 Ok(())
1022 }
1023 Event::Atom(Atom::Null) => {
1025 self.before_child();
1026 let bindings = self.local_bindings.len();
1027 self.start_tag(&name, false, state)?;
1028 self.out.push_str("/>");
1029 self.local_bindings.truncate(bindings);
1030 Ok(())
1031 }
1032 Event::Atom(atom) => self.atom_element(&name, &atom, false, state),
1033 Event::MapStart(_) => {
1034 self.before_child();
1035 self.open_element(&name, value, state)
1036 }
1037 _ => Err(Error::new(
1038 ErrorKind::UnsupportedType,
1039 "sequences in sequences are not supported",
1040 )),
1041 }
1042 }
1043
1044 fn attribute(&mut self, name: &str, value: &str) -> Result<(), Error> {
1046 let mut declarations = String::new();
1047 let name = self.qualify(name, true, &mut declarations)?;
1048 let Some(Frame::Element(element)) = self.stack.last_mut() else {
1049 unreachable!()
1050 };
1051 let out = if !element.content {
1052 &mut self.out
1053 } else if element.attrs_at >= self.base {
1054 &mut element.late
1055 } else {
1056 return Err(Error::new(
1057 ErrorKind::Unexpected,
1058 format!(
1059 "attribute `{name}` comes after the start tag of the element was written \
1060 (the fields the value described are not the keys it has)"
1061 ),
1062 ));
1063 };
1064 out.push_str(&declarations);
1065 out.push(' ');
1066 out.push_str(&name);
1067 out.push_str("=\"");
1068 escape(value, true, out)?;
1069 out.push('"');
1070 if !element.content {
1071 element.attrs_at = self.base + self.out.len();
1072 }
1073 self.settle();
1074 Ok(())
1075 }
1076
1077 fn settle(&mut self) {
1080 let Some(Frame::Element(element)) = self.stack.last_mut() else {
1081 return;
1082 };
1083 if !matches!(element.attrs, Attrs::Done) || element.late.is_empty() {
1084 return;
1085 }
1086 let late = std::mem::take(&mut element.late);
1087 let at = element.attrs_at;
1088 self.insert(at, &late);
1089 }
1090
1091 fn insert(&mut self, at: usize, text: &str) {
1095 self.out.insert_str(at - self.base, text);
1096 for frame in &mut self.stack {
1097 if let Frame::Element(element) = frame
1098 && element.attrs_at >= at
1099 {
1100 element.attrs_at += text.len();
1101 }
1102 }
1103 }
1104
1105 fn atom_element(
1109 &mut self,
1110 name: &str,
1111 atom: &Atom<'_>,
1112 is_root: bool,
1113 state: &State,
1114 ) -> Result<(), Error> {
1115 let text = match self.text(atom)? {
1116 Some(text) => text.into_owned(),
1117 None if is_root => String::new(),
1118 None => return Ok(()),
1119 };
1120 self.before_child();
1121 let bindings = self.local_bindings.len();
1122 let name = self.start_tag(name, is_root, state)?;
1123 if text.is_empty() {
1124 self.out.push_str("/>");
1125 } else {
1126 self.out.push('>');
1127 escape(&text, false, &mut self.out)?;
1128 write!(self.out, "</{name}>").unwrap();
1129 }
1130 self.local_bindings.truncate(bindings);
1131 Ok(())
1132 }
1133
1134 fn open_element(
1136 &mut self,
1137 name: &str,
1138 value: &dyn Serialize,
1139 state: &State,
1140 ) -> Result<(), Error> {
1141 let bindings = self.local_bindings.len();
1142 let name = self.start_tag(name, self.stack.is_empty(), state)?;
1143 let (fields, attrs) = self.fields_of(value);
1144 let layout = Layout::of(state);
1145 let lines = if self.config.indent == Indent::None
1146 || self.in_line()
1147 || layout == Layout::Compact
1148 || keeps_whitespace(state)
1149 {
1150 Lines::Inline
1151 } else {
1152 Lines::Pending
1153 };
1154 self.stack.push(Frame::Element(Element {
1155 name,
1156 attrs_at: self.base + self.out.len(),
1157 content: false,
1158 late: String::new(),
1159 attrs,
1160 fields: fields.map(|names| (names, 0)),
1161 bindings,
1162 lines,
1163 expanded: layout == Layout::Expanded,
1164 }));
1165 self.depth += 1;
1166 Ok(())
1167 }
1168
1169 fn fields_of(&self, value: &dyn Serialize) -> (Option<&'static [&'static str]>, Attrs) {
1172 let mut fields = Fields::default();
1173 value.describe(&mut fields);
1174 let Some(names) = fields.names.filter(|_| !fields.variant) else {
1175 return (None, Attrs::Unknown);
1176 };
1177 let names_config = &self.config.names;
1178 let last = names.iter().rposition(|name| {
1179 *name != names_config.text_key && attribute_name(names_config, name).is_some()
1180 });
1181 let attrs = match last {
1182 Some(last) => Attrs::Until(last),
1183 None => Attrs::Done,
1184 };
1185 (Some(names), attrs)
1186 }
1187
1188 fn in_line(&self) -> bool {
1191 match self.stack.last() {
1192 None => false,
1193 Some(Frame::Items { compact: true, .. }) => true,
1194 Some(Frame::Items { .. }) => match self.stack.iter().rev().nth(1) {
1195 Some(Frame::Element(element)) => element.lines == Lines::Inline,
1196 _ => unreachable!("sequences are in elements"),
1197 },
1198 Some(Frame::Element(element)) => element.lines == Lines::Inline,
1199 }
1200 }
1201
1202 fn before_child(&mut self) {
1205 self.close_start_tag();
1206 if self.config.indent == Indent::None {
1207 return;
1208 }
1209 let text_key = self.config.names.text_key;
1210 let mut frames = self.stack.iter_mut().rev();
1211 let element = match frames.next() {
1212 None => return,
1213 Some(Frame::Items {
1214 compact, started, ..
1215 }) => {
1216 if std::mem::replace(started, true) && *compact {
1218 return;
1219 }
1220 match frames.next() {
1221 Some(Frame::Element(element)) => element,
1222 _ => unreachable!("sequences are in elements"),
1223 }
1224 }
1225 Some(Frame::Element(element)) => element,
1226 };
1227 if element.lines == Lines::Pending {
1228 let text_ahead = !element.expanded
1231 && element
1232 .fields
1233 .is_some_and(|(names, cursor)| names[cursor..].contains(&text_key));
1234 element.lines = if text_ahead {
1235 Lines::Inline
1236 } else {
1237 Lines::Indented
1238 };
1239 }
1240 if element.lines == Lines::Indented {
1241 self.newline(self.depth);
1242 }
1243 }
1244
1245 fn newline(&mut self, depth: usize) {
1247 self.out.push('\n');
1248 let (unit, count) = match self.config.indent {
1249 Indent::None => return,
1250 Indent::Spaces(width) => (' ', width * depth),
1251 Indent::Tab => ('\t', depth),
1252 };
1253 self.out.extend(std::iter::repeat_n(unit, count));
1254 }
1255
1256 fn start_tag(&mut self, name: &str, is_root: bool, state: &State) -> Result<String, Error> {
1262 let mut declarations = String::new();
1263 if !is_root && let Some(Declarations(namespaces)) = state.event::<Declarations>() {
1264 for (prefix, uri) in namespaces {
1265 check_prefix(prefix)?;
1266 if prefix == "xml" {
1267 continue;
1268 }
1269 declare(prefix, uri, &mut declarations)?;
1270 self.local_bindings.push((prefix.clone(), uri.clone()));
1271 }
1272 }
1273 let name = self.qualify(name, false, &mut declarations)?;
1274 self.out.push('<');
1275 self.out.push_str(&name);
1276 if is_root {
1277 self.root_declarations = Some(self.base + self.out.len());
1278 }
1279 self.out.push_str(&declarations);
1280 Ok(name)
1281 }
1282
1283 fn qualify(
1290 &mut self,
1291 name: &str,
1292 is_attribute: bool,
1293 declarations: &mut String,
1294 ) -> Result<String, Error> {
1295 let Some((uri, local)) = split_name(name)? else {
1296 return Ok(name.to_string());
1297 };
1298 let usable = |(prefix, bound): &&(String, String)| {
1301 bound == uri && !(is_attribute && prefix.is_empty())
1302 };
1303 let scoped = &self.local_bindings;
1306 let bound = scoped
1307 .iter()
1308 .enumerate()
1309 .rev()
1310 .find(|(index, binding)| {
1311 usable(binding) && !scoped[index + 1..].iter().any(|(x, _)| *x == binding.0)
1312 })
1313 .map(|(_, binding)| binding)
1314 .or_else(|| {
1315 self.root_bindings
1316 .iter()
1317 .find(|binding| usable(binding) && !scoped.iter().any(|(x, _)| *x == binding.0))
1318 });
1319 let prefix = match bound {
1320 Some((prefix, _)) => prefix,
1321 None => {
1322 let prefix = (0..)
1324 .map(|n| format!("ns{n}"))
1325 .find(|prefix| {
1326 self.root_bindings
1327 .iter()
1328 .chain(&self.local_bindings)
1329 .all(|(x, _)| x != prefix)
1330 })
1331 .unwrap();
1332 let bindings = if self.root_declared {
1333 declare(&prefix, uri, declarations)?;
1334 &mut self.local_bindings
1335 } else {
1336 &mut self.root_bindings
1337 };
1338 bindings.push((prefix, uri.to_string()));
1339 &bindings.last().unwrap().0
1340 }
1341 };
1342 Ok(if prefix.is_empty() {
1343 local.to_string()
1344 } else {
1345 format!("{prefix}:{local}")
1346 })
1347 }
1348
1349 fn declare_root(&mut self) -> Result<(), Error> {
1351 if self.root_declared {
1352 return Ok(());
1353 }
1354 self.root_declared = true;
1355 let Some(at) = self.root_declarations else {
1356 return Ok(());
1357 };
1358 let mut declarations = String::new();
1359 for (prefix, uri) in &self.root_bindings[1..] {
1360 declare(prefix, uri, &mut declarations)?;
1361 }
1362 self.insert(at, &declarations);
1363 Ok(())
1364 }
1365
1366 fn final_until(&self) -> usize {
1368 for frame in &self.stack {
1369 if let Frame::Element(element) = frame
1370 && !matches!(element.attrs, Attrs::Done)
1371 {
1372 return element.attrs_at;
1373 }
1374 }
1375 self.base + self.out.len()
1376 }
1377
1378 fn final_len(&mut self) -> Result<usize, Error> {
1384 let mut until = self.final_until();
1385 if !self.root_declared && self.root_declarations.is_some_and(|at| at < until) {
1387 self.declare_root()?;
1388 until = self.final_until();
1389 }
1390 Ok(until - self.base)
1391 }
1392
1393 fn pass_on(&mut self, out: &mut String) {
1395 let len = self.final_until() - self.base;
1396 out.push_str(&self.out[..len]);
1397 self.out.drain(..len);
1398 self.base += len;
1399 }
1400
1401 fn finish(&mut self) -> Result<(), Error> {
1404 if !self.stack.is_empty() || self.depth > 0 {
1405 return Err(Error::new(ErrorKind::Unexpected, "incomplete document"));
1406 }
1407 self.declare_root()
1408 }
1409
1410 fn close_start_tag(&mut self) {
1412 let element = self.stack.iter_mut().rev().find_map(|frame| match frame {
1413 Frame::Element(element) => Some(element),
1414 Frame::Items { .. } => None,
1415 });
1416 if let Some(element) = element
1417 && !element.content
1418 {
1419 element.content = true;
1420 self.out.push('>');
1421 }
1422 }
1423
1424 fn close_element(&mut self) -> Result<(), Error> {
1425 if let Some(Frame::Element(element)) = self.stack.last_mut() {
1426 element.attrs = Attrs::Done;
1427 }
1428 self.settle();
1429 let Some(Frame::Element(element)) = self.stack.pop() else {
1430 unreachable!()
1431 };
1432 self.depth -= 1;
1433 if element.lines == Lines::Indented {
1434 self.newline(self.depth);
1435 }
1436 if element.content {
1437 write!(self.out, "</{}>", element.name).unwrap();
1438 } else {
1439 self.out.push_str("/>");
1440 }
1441 self.local_bindings.truncate(element.bindings);
1442 Ok(())
1443 }
1444
1445 fn text<'a>(&self, atom: &'a Atom<'_>) -> Result<Option<Cow<'a, str>>, Error> {
1447 Ok(Some(match *atom {
1448 Atom::Null => return Ok(None),
1449 Atom::Implicit(ref value) => {
1452 return Ok(self
1453 .text(&value.value().to_atom())?
1454 .map(|text| Cow::Owned(text.into_owned())));
1455 }
1456 Atom::Bool(value) => Cow::Borrowed(if value { "true" } else { "false" }),
1457 Atom::Str(ref value) | Atom::Lexical(ref value) => Cow::Borrowed(&**value),
1458 Atom::Char(value) => Cow::Owned(value.to_string()),
1459 Atom::U64(value) => Cow::Owned(value.to_string()),
1460 Atom::I64(value) => Cow::Owned(value.to_string()),
1461 Atom::F32(value) => Cow::Owned(float_text(value)),
1462 Atom::F64(value) => Cow::Owned(float_text(value)),
1463 Atom::Bytes(ref bytes) => {
1464 let format = bytes.fallback.copied().unwrap_or(self.config.bytes);
1465 Cow::Owned(
1466 format
1467 .encode(bytes)
1468 .or_else(|| BytesFormat::BASE64.encode(bytes))
1469 .unwrap_or_default(),
1470 )
1471 }
1472 Atom::Ext(ref ext) => {
1473 if let Some(number) = ext.downcast_value_ref::<Number>() {
1474 Cow::Owned(number.as_str().to_string())
1475 } else if let Some(value) = ext.downcast_ref::<u128>() {
1476 Cow::Owned(value.to_string())
1477 } else if let Some(value) = ext.downcast_ref::<i128>() {
1478 Cow::Owned(value.to_string())
1479 } else {
1480 match ext.fallback() {
1481 Atom::Ext(_) => {
1482 return Err(Error::new(
1483 ErrorKind::UnsupportedType,
1484 format!("XML does not support {}", ext.name()),
1485 ));
1486 }
1487 fallback => match self.text(&fallback)? {
1488 Some(text) => Cow::Owned(text.into_owned()),
1489 None => return Ok(None),
1490 },
1491 }
1492 }
1493 }
1494 _ => {
1495 return Err(Error::new(
1496 ErrorKind::UnsupportedType,
1497 format!("XML does not support {}", atom.name()),
1498 ));
1499 }
1500 }))
1501 }
1502}
1503
1504fn keeps_whitespace(state: &State) -> bool {
1506 state
1507 .event::<KeepsWhitespace>()
1508 .is_some_and(|keeps| keeps.0)
1509}
1510
1511fn float_text<F: Float>(value: F) -> String {
1518 let wide = value.to_f64();
1519 if wide.is_nan() {
1520 "NaN".into()
1521 } else if wide.is_infinite() {
1522 if wide > 0.0 { "INF" } else { "-INF" }.into()
1523 } else {
1524 format_finite(value)
1525 }
1526}
1527
1528fn escape(text: &str, attribute: bool, out: &mut String) -> Result<(), Error> {
1530 for c in text.chars() {
1531 match c {
1532 '&' => out.push_str("&"),
1533 '<' => out.push_str("<"),
1534 '>' => out.push_str(">"),
1535 '"' if attribute => out.push_str("""),
1536 '\t' if attribute => out.push_str("	"),
1539 '\n' if attribute => out.push_str(" "),
1540 '\r' => out.push_str(" "),
1541 '\t' | '\n' => out.push(c),
1542 c if (c as u32) < 0x20 || c == '\u{fffe}' || c == '\u{ffff}' => {
1543 return Err(Error::new(
1544 ErrorKind::UnsupportedType,
1545 format!("the character {c:?} cannot be written in XML"),
1546 ));
1547 }
1548 c => out.push(c),
1549 }
1550 }
1551 Ok(())
1552}
1553
1554fn attribute_name<'a>(names: &Names, key: &'a str) -> Option<&'a str> {
1558 key.strip_prefix(names.attribute_prefix)
1559 .filter(|_| !names.attribute_prefix.is_empty())
1560}
1561
1562fn declare(prefix: &str, uri: &str, out: &mut String) -> Result<(), Error> {
1564 out.push_str(" xmlns");
1565 if !prefix.is_empty() {
1566 out.push(':');
1567 out.push_str(prefix);
1568 }
1569 out.push_str("=\"");
1570 escape(uri, true, out)?;
1571 out.push('"');
1572 Ok(())
1573}
1574
1575fn split_name(name: &str) -> Result<Option<(&str, &str)>, Error> {
1577 let Some(rest) = name.strip_prefix('{') else {
1578 return Ok(None);
1579 };
1580 match rest.split_once('}') {
1581 Some((uri, local)) if !uri.is_empty() => Ok(Some((uri, local))),
1582 _ => Err(Error::new(
1583 ErrorKind::UnsupportedType,
1584 format!("`{name}` is not a name in XML"),
1585 )),
1586 }
1587}
1588
1589fn check_element_name(name: &str) -> Result<(), Error> {
1592 match split_name(name)? {
1593 Some((_, local)) if local.contains(':') => Err(Error::new(
1594 ErrorKind::UnsupportedType,
1595 format!("`{name}` is not a name in XML"),
1596 )),
1597 Some((_, local)) => check_name(local),
1598 None => check_name(name),
1599 }
1600}
1601
1602fn check_prefix(prefix: &str) -> Result<(), Error> {
1605 if prefix.is_empty() {
1606 return Ok(());
1607 }
1608 check_name(prefix)?;
1609 if prefix.contains(':') {
1610 return Err(Error::new(
1611 ErrorKind::UnsupportedType,
1612 format!("`{prefix}` is not a prefix in XML"),
1613 ));
1614 }
1615 Ok(())
1616}
1617
1618fn check_name(name: &str) -> Result<(), Error> {
1620 let mut chars = name.chars();
1621 let valid = match chars.next() {
1622 Some(c) if c.is_alphabetic() || c == '_' || c == ':' => {
1623 chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | ':' | '-' | '.' | '\u{b7}'))
1624 }
1625 _ => false,
1626 };
1627 if valid {
1628 Ok(())
1629 } else {
1630 Err(Error::new(
1631 ErrorKind::UnsupportedType,
1632 format!("`{name}` is not a name in XML"),
1633 ))
1634 }
1635}
1636
1637#[cold]
1638fn unsupported_key() -> Error {
1639 Error::new(
1640 ErrorKind::UnsupportedType,
1641 "the keys of elements must be names",
1642 )
1643}
1644
1645#[cfg(test)]
1646mod tests {
1647 use std::collections::BTreeMap;
1648
1649 use deser::Serialize;
1650
1651 use super::*;
1652
1653 fn pieces(config: &SerializerConfig, value: &dyn Serialize) -> Result<Vec<String>, Error> {
1656 let mut pieces = Vec::new();
1657 let mut driver = SerializeDriver::new(value);
1658 let mut progress = None;
1659 loop {
1660 let mut out = String::new();
1661 let done = config.serialize_part(&mut progress, &mut driver, &mut out, 1)?;
1662 pieces.push(out);
1663 if done {
1664 return Ok(pieces);
1665 }
1666 }
1667 }
1668
1669 #[derive(Serialize)]
1670 struct Feed {
1671 #[deser(rename = "@id")]
1672 id: u32,
1673 title: &'static str,
1674 entry: Vec<Entry>,
1675 }
1676
1677 #[derive(Serialize)]
1678 struct Entry {
1679 #[deser(rename = "$text")]
1680 text: &'static str,
1681 #[deser(rename = "@n")]
1682 n: u32,
1683 #[deser(skip_serializing_if = Option::is_none)]
1684 note: Option<&'static str>,
1685 }
1686
1687 fn feed() -> Feed {
1688 Feed {
1689 id: 1,
1690 title: "t",
1691 entry: vec![
1692 Entry {
1693 text: "a",
1694 n: 1,
1695 note: None,
1696 },
1697 Entry {
1698 text: "b",
1699 n: 2,
1700 note: Some("x"),
1701 },
1702 ],
1703 }
1704 }
1705
1706 #[test]
1707 fn test_structs_stream() {
1708 assert_eq!(
1711 pieces(&SerializerConfig::new(), &feed()).unwrap(),
1712 [
1713 "<Feed id=\"1\"",
1714 "><title>t</title>",
1715 "<entry",
1716 " n=\"1\">a",
1717 "</entry>",
1718 "<entry",
1719 " n=\"2\">b",
1720 "<note>x</note>",
1721 "</entry>",
1722 "</Feed>",
1723 ]
1724 );
1725 }
1726
1727 #[test]
1728 fn test_maps_are_buffered() {
1729 let config = SerializerConfig::new().root("m").declaration(true);
1731 let map = BTreeMap::from([
1732 ("a", BTreeMap::from([("$text", "1"), ("@x", "2")])),
1733 ("b", BTreeMap::from([("$text", "3"), ("@y", "4")])),
1734 ]);
1735 assert_eq!(
1736 pieces(&config, &map).unwrap(),
1737 [
1738 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><m",
1739 "><a x=\"2\">1</a><b y=\"4\">3</b></m>",
1740 ]
1741 );
1742
1743 let map = BTreeMap::from([("$text", "x"), ("@a", "1"), ("b", "2")]);
1744 assert_eq!(
1745 pieces(&config, &map).unwrap(),
1746 [
1747 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><m",
1748 " a=\"1\">x<b>2</b></m>",
1749 ]
1750 );
1751 }
1752
1753 #[test]
1754 fn test_same_output() {
1755 let map = BTreeMap::from([("$text", "x"), ("@a", "1"), ("b", "2")]);
1756 let nested = BTreeMap::from([("a", BTreeMap::from([("@x", "1"), ("b", "2")]))]);
1757 let values: [&dyn Serialize; 4] = [&feed(), &map, &nested, &Some(42)];
1758 for config in [
1759 SerializerConfig::new().root("r"),
1760 SerializerConfig::new()
1761 .root("r")
1762 .declaration(true)
1763 .indent(Indent::Spaces(2)),
1764 ] {
1765 for value in values {
1766 assert_eq!(
1767 pieces(&config, value).unwrap().concat(),
1768 config.to_string(value).unwrap()
1769 );
1770 }
1771 }
1772 }
1773
1774 #[test]
1775 fn test_indent_streams() {
1776 let config = SerializerConfig::new().indent(Indent::Spaces(2));
1778 assert_eq!(
1779 pieces(&config, &feed()).unwrap(),
1780 [
1781 "<Feed id=\"1\"",
1782 ">\n <title>t</title>",
1783 "\n <entry",
1784 " n=\"1\">a",
1785 "</entry>",
1786 "\n <entry",
1787 " n=\"2\">b",
1788 "<note>x</note>",
1789 "</entry>",
1790 "\n</Feed>",
1791 ]
1792 );
1793 }
1794
1795 #[test]
1796 fn test_namespaces_stream() {
1797 #[derive(Serialize)]
1798 #[deser(rename = "{urn:root}root")]
1799 struct Root {
1800 #[deser(rename = "{urn:a}a")]
1801 a: Vec<Child>,
1802 }
1803
1804 #[derive(Serialize)]
1805 struct Child {
1806 #[deser(rename = "@{urn:b}b")]
1807 b: u32,
1808 #[deser(rename = "{urn:a}c")]
1809 c: u32,
1810 }
1811
1812 let root = Root {
1813 a: vec![Child { b: 1, c: 2 }, Child { b: 3, c: 4 }],
1814 };
1815
1816 let config = SerializerConfig::new();
1818 assert_eq!(
1819 config.to_string(&root).unwrap(),
1820 "<ns0:root xmlns:ns0=\"urn:root\" xmlns:ns1=\"urn:a\" xmlns:ns2=\"urn:b\">\
1821 <ns1:a ns2:b=\"1\"><ns1:c>2</ns1:c></ns1:a>\
1822 <ns1:a ns2:b=\"3\"><ns1:c>4</ns1:c></ns1:a></ns0:root>"
1823 );
1824
1825 assert_eq!(
1828 pieces(&config, &root).unwrap().concat(),
1829 "<ns0:root xmlns:ns0=\"urn:root\" xmlns:ns1=\"urn:a\">\
1830 <ns1:a xmlns:ns2=\"urn:b\" ns2:b=\"1\"><ns1:c>2</ns1:c></ns1:a>\
1831 <ns1:a xmlns:ns2=\"urn:b\" ns2:b=\"3\"><ns1:c>4</ns1:c></ns1:a>\
1832 </ns0:root>"
1833 );
1834
1835 let config = SerializerConfig::new().namespaces(&[("r", "urn:root"), ("a", "urn:a")]);
1837 assert_eq!(
1838 pieces(&config, &root).unwrap().concat(),
1839 "<r:root xmlns:r=\"urn:root\" xmlns:a=\"urn:a\">\
1840 <a:a xmlns:ns0=\"urn:b\" ns0:b=\"1\"><a:c>2</a:c></a:a>\
1841 <a:a xmlns:ns0=\"urn:b\" ns0:b=\"3\"><a:c>4</a:c></a:a></r:root>"
1842 );
1843 }
1844
1845 #[test]
1846 fn test_nested_declarations_stream() {
1847 const RESOLVE: crate::DeserializerConfig =
1848 crate::DeserializerConfig::new().resolve_namespaces(true);
1849 let input = r#"<a:r xmlns:a="urn:a"><b xmlns:a="urn:b"><x>1</x></b><a:y>2</a:y></a:r>"#;
1850 let mut value: deser_value::Value = RESOLVE.from_str(input).unwrap();
1851 let config = SerializerConfig::new();
1852 assert_eq!(pieces(&config, &value).unwrap().concat(), input);
1853
1854 let b = value.as_map_mut().unwrap().get_mut("b").unwrap();
1856 b.as_map_mut().unwrap().insert("{urn:a}z", "3");
1857 let xml = config.to_string(&value).unwrap();
1858 assert_eq!(
1859 xml,
1860 "<a:r xmlns:a=\"urn:a\" xmlns:ns0=\"urn:a\"><b xmlns:a=\"urn:b\"><x>1</x>\
1861 <ns0:z>3</ns0:z></b><a:y>2</a:y></a:r>"
1862 );
1863 assert_eq!(pieces(&config, &value).unwrap().concat(), xml);
1864 }
1865
1866 #[test]
1867 fn test_wrong_fields() {
1868 struct Wrong(BTreeMap<&'static str, &'static str>);
1870
1871 impl Serialize for Wrong {
1872 fn describe(&self, d: &mut dyn Describe) {
1873 d.structure("Wrong");
1874 d.fields(&["$text"]);
1875 }
1876
1877 fn serialize(
1878 &self,
1879 state: &mut deser_core::State,
1880 ) -> Result<deser_core::ser::Chunk<'_>, Error> {
1881 self.0.serialize(state)
1882 }
1883 }
1884
1885 let wrong = Wrong(BTreeMap::from([("$text", "x"), ("@a", "1")]));
1886 let config = SerializerConfig::new();
1887 assert_eq!(
1889 config.to_string(&wrong).unwrap(),
1890 r#"<Wrong a="1">x</Wrong>"#
1891 );
1892 let err = pieces(&config, &wrong).unwrap_err();
1893 assert!(
1894 err.message()
1895 .starts_with("attribute `a` comes after the start tag")
1896 );
1897 }
1898}