1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::string::ToString;
4use alloc::vec::Vec;
5use core::mem::ManuallyDrop;
6
7use deser_core::ext::{BigInt, Decimal, ExtValue, Number, RawInput};
8use deser_core::ser::SerializeRef;
9use deser_core::ser::{self, EventSink, SerializeDriver};
10use deser_core::{Atom, BytesFormat, Error, ErrorKind, Event, Implicit, ImplicitValue, Serialize};
11
12use crate::Trailing;
13use crate::buf::Buffer;
14use crate::escape::find_escape;
15use crate::pretty::PrettyWriter;
16use crate::scan::skip_to_escape;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
22#[non_exhaustive]
23pub enum Indent {
24 #[default]
26 None,
27 Spaces(usize),
30 Tab,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
42#[non_exhaustive]
43pub enum InlinePolicy {
44 #[default]
46 Never,
47 LeafIfFits(usize),
52}
53
54#[derive(Debug, Clone, PartialEq, Eq)]
86pub struct SerializerConfig {
87 indent: Indent,
88 compact: bool,
89 inline: InlinePolicy,
90 trailing: Trailing,
91 non_finite_floats: bool,
92 context: deser_core::Context,
93}
94
95impl Default for SerializerConfig {
96 fn default() -> SerializerConfig {
97 SerializerConfig::new()
98 }
99}
100
101impl SerializerConfig {
102 pub const fn new() -> SerializerConfig {
104 SerializerConfig {
105 indent: Indent::None,
106 compact: true,
107 inline: InlinePolicy::Never,
108 trailing: Trailing::Strict,
109 non_finite_floats: false,
110 context: deser_core::Context::new(),
111 }
112 }
113
114 pub const fn builder() -> SerializerConfigBuilder {
116 SerializerConfigBuilder::new()
117 }
118
119 pub const fn into_builder(self) -> SerializerConfigBuilder {
121 SerializerConfigBuilder { value: self }
122 }
123
124 pub fn set_context(&mut self, context: deser_core::Context) {
132 self.context = context;
133 }
134
135 pub fn context(&self) -> &deser_core::Context {
137 &self.context
138 }
139
140 #[inline]
142 fn apply_context(&self, driver: &mut SerializeDriver<'_>) {
143 if !self.context.is_empty() {
144 driver.set_default_context(self.context.clone());
145 }
146 }
147
148 pub const fn set_trailing(&mut self, trailing: Trailing) {
173 self.trailing = trailing;
174 }
175
176 pub(crate) fn trailing_mode(&self) -> Trailing {
178 self.trailing
179 }
180
181 pub const fn set_indent(&mut self, indent: Indent) {
197 self.indent = indent;
198 }
199
200 pub const fn set_compact(&mut self, yes: bool) {
215 self.compact = yes;
216 }
217
218 pub const fn set_inline(&mut self, policy: InlinePolicy) {
249 self.inline = policy;
250 }
251
252 pub const fn set_pretty(&mut self, indent: Indent) {
270 self.indent = indent;
271 self.compact = matches!(indent, Indent::None);
272 }
273
274 pub const fn set_non_finite_floats(&mut self, yes: bool) {
295 self.non_finite_floats = yes;
296 }
297
298 #[inline]
302 pub fn to_string<T: Serialize + ?Sized>(&self, value: &T) -> Result<String, Error> {
303 let value = SerializeRef::new(&value);
307 if self.is_compact() {
308 self.to_string_compact(value)
309 } else {
310 self.to_string_pretty(value)
311 }
312 }
313
314 #[inline(never)]
316 fn to_string_compact(&self, value: SerializeRef<'_>) -> Result<String, Error> {
317 let mut driver = SerializeDriver::from_ref(value);
318 self.apply_context(&mut driver);
319 accept_raw(&mut driver);
320 self.serialize_compact(&mut driver)
321 }
322
323 #[inline(never)]
325 fn to_string_pretty(&self, value: SerializeRef<'_>) -> Result<String, Error> {
326 let mut driver = SerializeDriver::from_ref(value);
327 self.apply_context(&mut driver);
328 accept_raw(&mut driver);
329 self.serialize_pretty(&mut driver)
330 }
331
332 pub fn to_string_with<F, T: Serialize + ?Sized>(
368 &self,
369 value: &T,
370 setup: F,
371 ) -> Result<String, Error>
372 where
373 F: FnOnce(&mut SerializeDriver<'_>),
374 {
375 let mut driver = SerializeDriver::new(&value);
376 setup(&mut driver);
377 self.apply_context(&mut driver);
378 self.serialize_driver(&mut driver)
379 }
380
381 #[inline]
386 pub(crate) fn serialize_driver(
387 &self,
388 driver: &mut SerializeDriver<'_>,
389 ) -> Result<String, Error> {
390 accept_raw(driver);
391 if self.is_compact() {
392 self.serialize_compact(driver)
393 } else {
394 self.serialize_pretty(driver)
395 }
396 }
397
398 #[inline(always)]
400 fn is_compact(&self) -> bool {
401 self.indent == Indent::None && self.compact
402 }
403
404 #[inline(never)]
406 fn serialize_compact(&self, driver: &mut SerializeDriver<'_>) -> Result<String, Error> {
407 let bytes = BytesFormat::of(driver.state());
408 let mut writer = self.compact_writer(Buffer::with_capacity(128), bytes);
409 driver.drive_sink(&mut writer)?;
410 Ok(writer.ser.out.into_string())
411 }
412
413 #[inline(never)]
415 fn serialize_pretty(&self, driver: &mut SerializeDriver<'_>) -> Result<String, Error> {
416 let bytes = BytesFormat::of(driver.state());
417 let mut writer = self.pretty_writer(Buffer::with_capacity(128), bytes);
418 driver.drive(|event, state| writer.event(event, state))?;
419 Ok(writer.finish())
420 }
421
422 fn compact_writer(&self, out: Buffer, bytes: BytesFormat) -> Writer {
424 Writer {
425 ser: Output {
426 out,
427 bytes,
428 non_finite_floats: self.non_finite_floats,
429 },
430 stack: Vec::new(),
431 container: Container::Top,
432 first: true,
433 is_key: false,
434 limit: usize::MAX,
435 }
436 }
437
438 fn pretty_writer(&self, out: Buffer, bytes: BytesFormat) -> PrettyWriter {
440 let ser = Output {
441 out,
442 bytes,
443 non_finite_floats: self.non_finite_floats,
444 };
445 let inline_width = match self.inline {
446 InlinePolicy::Never => None,
447 InlinePolicy::LeafIfFits(width) => Some(width),
448 };
449 PrettyWriter::new(ser, self.indent, self.compact, inline_width)
450 }
451
452 pub(crate) fn value_writer(&self, out: Buffer, bytes: BytesFormat) -> ValueWriter {
454 if self.is_compact() {
455 ValueWriter::Compact(self.compact_writer(out, bytes))
456 } else {
457 ValueWriter::Pretty(self.pretty_writer(out, bytes))
458 }
459 }
460}
461
462#[derive(Debug, Clone)]
466#[must_use]
467pub struct SerializerConfigBuilder {
468 value: SerializerConfig,
469}
470
471impl SerializerConfigBuilder {
472 pub const fn new() -> SerializerConfigBuilder {
474 SerializerConfigBuilder {
475 value: SerializerConfig::new(),
476 }
477 }
478
479 pub const fn trailing(mut self, trailing: Trailing) -> SerializerConfigBuilder {
483 self.value.set_trailing(trailing);
484 self
485 }
486
487 pub const fn indent(mut self, indent: Indent) -> SerializerConfigBuilder {
491 self.value.set_indent(indent);
492 self
493 }
494
495 pub const fn compact(mut self, yes: bool) -> SerializerConfigBuilder {
499 self.value.set_compact(yes);
500 self
501 }
502
503 pub const fn inline(mut self, policy: InlinePolicy) -> SerializerConfigBuilder {
507 self.value.set_inline(policy);
508 self
509 }
510
511 pub const fn pretty(mut self, indent: Indent) -> SerializerConfigBuilder {
515 self.value.set_pretty(indent);
516 self
517 }
518
519 pub const fn non_finite_floats(mut self, yes: bool) -> SerializerConfigBuilder {
523 self.value.set_non_finite_floats(yes);
524 self
525 }
526
527 pub fn context(mut self, context: deser_core::Context) -> SerializerConfigBuilder {
531 self.value.set_context(context);
532 self
533 }
534
535 pub const fn build(self) -> SerializerConfig {
537 let value = unsafe { core::ptr::read(&self.value) };
541 core::mem::forget(self);
542 value
543 }
544}
545
546impl Default for SerializerConfigBuilder {
547 fn default() -> SerializerConfigBuilder {
548 SerializerConfigBuilder::new()
549 }
550}
551
552fn accept_raw(driver: &mut SerializeDriver<'_>) {
554 driver.state_mut().declare_raw_format(&crate::raw::ID);
555}
556
557pub(crate) enum ValueWriter {
559 Compact(Writer),
561 Pretty(PrettyWriter),
563}
564
565impl ValueWriter {
566 pub(crate) fn drive(
572 &mut self,
573 driver: &mut SerializeDriver<'_>,
574 limit: usize,
575 ) -> Result<bool, Error> {
576 if limit == usize::MAX {
577 return self.drive_whole(driver).map(|()| true);
578 }
579 match self {
580 ValueWriter::Compact(writer) => {
581 writer.limit = limit;
582 driver.drive_until(writer)
583 }
584 ValueWriter::Pretty(writer) => {
585 writer.limit = limit;
586 driver.drive_until(writer)
587 }
588 }
589 }
590
591 pub(crate) fn drive_whole(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
596 match self {
597 ValueWriter::Compact(writer) => driver.drive_sink(writer),
598 ValueWriter::Pretty(writer) => driver.drive(|event, state| writer.event(event, state)),
599 }
600 }
601
602 pub(crate) fn output(&mut self) -> &mut Buffer {
604 match self {
605 ValueWriter::Compact(writer) => &mut writer.ser.out,
606 ValueWriter::Pretty(writer) => writer.output(),
607 }
608 }
609
610 pub(crate) fn take_output(&mut self) -> Vec<u8> {
613 match self {
614 ValueWriter::Compact(writer) => writer.ser.out.take(),
615 ValueWriter::Pretty(writer) => writer.take_output(),
616 }
617 }
618}
619
620pub struct Serializer {
655 config: SerializerConfig,
656 out: Vec<u8>,
659 written: usize,
660 value: Option<Box<ValueWriter>>,
662 in_progress: bool,
664}
665
666impl Default for Serializer {
667 fn default() -> Serializer {
668 Serializer::new()
669 }
670}
671
672impl Clone for Serializer {
673 fn clone(&self) -> Serializer {
679 Serializer {
680 config: self.config.clone(),
681 out: self.out.clone(),
682 written: self.written,
683 value: None,
684 in_progress: self.in_progress,
685 }
686 }
687}
688
689impl core::fmt::Debug for Serializer {
690 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
691 f.debug_struct("Serializer")
692 .field("config", &self.config)
693 .field("output", &self.as_str())
694 .field("written", &self.written)
695 .field("in_progress", &self.in_progress)
696 .finish()
697 }
698}
699
700impl Serializer {
701 pub fn new() -> Serializer {
703 Serializer::with_config(SerializerConfig::new())
704 }
705
706 pub fn with_config(config: SerializerConfig) -> Serializer {
708 Serializer::with_written(config, 0)
709 }
710
711 pub fn with_written(config: SerializerConfig, written: usize) -> Serializer {
717 Serializer {
718 config,
719 out: Vec::new(),
720 written,
721 value: None,
722 in_progress: false,
723 }
724 }
725
726 pub fn config(&self) -> &SerializerConfig {
728 &self.config
729 }
730
731 pub fn written(&self) -> usize {
733 self.written
734 }
735
736 pub fn serialize<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
740 ser::Serializer::serialize(self, value)
741 }
742
743 pub fn serialize_with<F, T: Serialize + ?Sized>(
748 &mut self,
749 value: &T,
750 setup: F,
751 ) -> Result<(), Error>
752 where
753 F: FnOnce(&mut SerializeDriver<'_>),
754 {
755 ser::Serializer::serialize_with(self, value, setup)
756 }
757
758 pub fn as_str(&self) -> &str {
760 unsafe { core::str::from_utf8_unchecked(&self.out) }
762 }
763
764 pub fn finish(self) -> String {
766 unsafe { String::from_utf8_unchecked(self.out) }
768 }
769
770 fn start_value(&mut self) -> Result<(), Error> {
772 if self.in_progress {
773 return Err(Error::in_progress());
774 }
775 match self.config.trailing_mode() {
776 Trailing::Strict if self.written > 0 => Err(Error::new(
777 ErrorKind::InvalidState,
778 "with Trailing::Strict only a single value can be written",
779 )),
780 Trailing::Stop if self.written > 0 => {
781 self.out.push(b'\n');
782 Ok(())
783 }
784 _ => Ok(()),
785 }
786 }
787
788 fn finish_value(&mut self) {
790 if self.config.trailing_mode() == Trailing::Newline {
791 self.out.push(b'\n');
792 }
793 self.written += 1;
794 self.in_progress = false;
795 }
796}
797
798impl ser::Serializer for Serializer {
799 fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
800 if self.in_progress {
802 return Err(Error::in_progress());
803 }
804 ser::StreamSerializer::drive_partial(self, driver, usize::MAX).map(|_| ())
805 }
806}
807
808impl ser::StreamSerializer for Serializer {
809 fn output(&self) -> &[u8] {
810 &self.out
811 }
812
813 fn clear_output(&mut self) {
814 self.out.clear();
815 }
816
817 fn supports_partial(&self) -> bool {
818 true
819 }
820
821 fn drive_partial(
822 &mut self,
823 driver: &mut SerializeDriver<'_>,
824 limit: usize,
825 ) -> Result<bool, Error> {
826 if !self.config.context.is_empty() {
827 driver.set_default_context(self.config.context.clone());
828 }
829 accept_raw(driver);
830 let rollback = self.out.len();
831 let (mut local, adopt) = match self.value.take() {
832 Some(mut writer) => {
835 let adopt = self.out.is_empty();
836 if adopt {
837 *writer.output() = Buffer::from_vec(core::mem::take(&mut self.out));
838 }
839 (writer, adopt)
840 }
841 None => {
842 self.start_value()?;
843 let out = Buffer::from_vec(core::mem::take(&mut self.out));
845 let writer = self
846 .config
847 .value_writer(out, BytesFormat::of(driver.state()));
848 if limit == usize::MAX {
849 return self.drive_whole(writer, driver, rollback);
850 }
851 (Box::new(writer), true)
852 }
853 };
854 let rv = local.drive(driver, limit);
855 match rv {
856 Ok(done) => {
857 let output = local.take_output();
858 if adopt {
859 self.out = output;
860 } else {
861 self.out.extend_from_slice(&output);
862 }
863 if done {
864 self.finish_value();
865 Ok(true)
866 } else {
867 self.value = Some(local);
868 self.in_progress = true;
869 Ok(false)
870 }
871 }
872 Err(err) => {
873 if adopt {
877 self.out = local.output().take();
878 self.out.truncate(rollback);
879 }
880 Err(err)
881 }
882 }
883 }
884
885 fn in_progress(&self) -> bool {
886 self.in_progress
887 }
888}
889
890impl Serializer {
891 fn drive_whole(
893 &mut self,
894 mut writer: ValueWriter,
895 driver: &mut SerializeDriver<'_>,
896 rollback: usize,
897 ) -> Result<bool, Error> {
898 let rv = writer.drive_whole(driver);
899 self.out = writer.output().take();
900 match rv {
901 Ok(_) => {
902 self.finish_value();
903 Ok(true)
904 }
905 Err(err) => {
906 self.out.truncate(rollback);
907 Err(err)
908 }
909 }
910 }
911}
912
913#[cfg(feature = "io")]
914impl SerializerConfig {
915 pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
933 deser_core::io::Writer::new(writer, Serializer::with_config(self.clone()))
934 }
935
936 pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
940 &self,
941 writer: W,
942 value: &T,
943 ) -> Result<(), Error> {
944 self.writer(writer).write(value)
945 }
946}
947
948#[cfg(feature = "io")]
960pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
961 writer: W,
962 value: &T,
963) -> Result<(), Error> {
964 SerializerConfig::new().to_writer(writer, value)
965}
966
967pub(crate) struct Output {
969 pub(crate) out: Buffer,
970 bytes: BytesFormat,
971 non_finite_floats: bool,
973}
974
975#[derive(Clone, Copy, PartialEq, Eq)]
976enum Container {
977 Top,
978 Seq,
979 Map,
980}
981
982pub(crate) struct Writer {
984 ser: Output,
985 stack: Vec<Container>,
988 container: Container,
989 first: bool,
990 is_key: bool,
991 limit: usize,
993}
994
995impl EventSink for Writer {
996 #[inline(always)]
997 fn event(
998 &mut self,
999 event: Event<'_>,
1000 _value: SerializeRef<'_>,
1001 _state: &mut deser_core::State,
1002 ) -> Result<(), Error> {
1003 Writer::event(self, event)
1004 }
1005
1006 #[inline(always)]
1007 fn pause(&mut self) -> bool {
1008 self.ser.out.len() >= self.limit
1009 }
1010}
1011
1012impl Writer {
1013 #[inline(always)]
1014 fn event(&mut self, event: Event) -> Result<(), Error> {
1015 match event {
1016 Event::Atom(atom) => {
1017 if self.is_key {
1018 self.ser.write_key_atom(atom, self.first)?;
1019 self.is_key = false;
1020 } else {
1021 match self.container {
1022 Container::Seq => {
1023 if !self.first {
1024 self.ser.write_char(',');
1025 }
1026 }
1027 Container::Map => self.is_key = true,
1028 Container::Top => {}
1029 }
1030 self.ser.write_atom(atom)?;
1031 }
1032 self.first = false;
1033 Ok(())
1034 }
1035 Event::MapStart(_) => self.start(true),
1036 Event::SeqStart(_) => self.start(false),
1037 Event::MapEnd => self.end(true),
1038 Event::SeqEnd => self.end(false),
1039 }
1040 }
1041
1042 #[inline]
1043 fn start(&mut self, is_map: bool) -> Result<(), Error> {
1044 if self.is_key {
1045 return Err(Error::new(
1046 ErrorKind::UnsupportedType,
1047 "JSON does not support this value for map keys",
1048 ));
1049 }
1050 if self.container == Container::Seq && !self.first {
1051 self.ser.write_char(',');
1052 }
1053 self.stack.push(self.container);
1054 self.first = true;
1055 if is_map {
1056 self.container = Container::Map;
1057 self.is_key = true;
1058 self.ser.write_char('{');
1059 } else {
1060 self.container = Container::Seq;
1061 self.ser.write_char('[');
1062 }
1063 Ok(())
1064 }
1065
1066 #[inline]
1067 fn end(&mut self, is_map: bool) -> Result<(), Error> {
1068 if is_map {
1069 if self.container != Container::Map || !self.is_key {
1070 return Err(Error::new(ErrorKind::InvalidState, "unexpected map end"));
1071 }
1072 self.ser.write_char('}');
1073 } else {
1074 if self.container != Container::Seq {
1075 return Err(Error::new(ErrorKind::InvalidState, "unexpected array end"));
1076 }
1077 self.ser.write_char(']');
1078 }
1079 self.container = self.stack.pop().unwrap_or(Container::Top);
1080 self.first = false;
1083 self.is_key = self.container == Container::Map;
1084 Ok(())
1085 }
1086}
1087
1088impl Output {
1089 #[inline(always)]
1091 fn write_key_atom(&mut self, atom: Atom, first: bool) -> Result<(), Error> {
1092 let atom = ManuallyDrop::new(atom);
1095 match *atom {
1096 Atom::Str(ref val) | Atom::Lexical(ref val) if val.is_borrowed() => {
1098 self.write_key(val, first);
1099 Ok(())
1100 }
1101 _ => self.write_other_key_atom(ManuallyDrop::into_inner(atom), first),
1102 }
1103 }
1104
1105 #[inline(never)]
1106 fn write_other_key_atom(&mut self, atom: Atom, first: bool) -> Result<(), Error> {
1107 if !first {
1108 self.write_char(',');
1109 }
1110 self.write_key_text(atom)?;
1111 self.write_char(':');
1112 Ok(())
1113 }
1114
1115 pub(crate) fn write_key_text(&mut self, atom: Atom) -> Result<(), Error> {
1117 match atom {
1118 Atom::Str(ref val) | Atom::Lexical(ref val) => self.write_escaped_str(val),
1119 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1120 Atom::U64(val) => {
1121 self.write_char('"');
1122 self.write_u64(val);
1123 self.write_char('"');
1124 }
1125 Atom::I64(val) => {
1126 self.write_char('"');
1127 self.write_i64(val);
1128 self.write_char('"');
1129 }
1130 Atom::Bool(val) => self.write_str(if val { "\"true\"" } else { "\"false\"" }),
1131 Atom::Ext(ref ext) => self.write_ext_key(ext)?,
1132 Atom::Bytes(ref val) => self.write_bytes_str(val, val.fallback),
1133 Atom::Implicit(ref val) => match json_literal(val) {
1134 Some(text) if val.value() != ImplicitValue::Null => self.write_escaped_str(text),
1135 _ => return self.write_key_text(val.value().to_atom()),
1136 },
1137 _ => {
1138 return Err(Error::new(
1139 ErrorKind::UnsupportedType,
1140 "JSON does not support this value for map keys",
1141 ));
1142 }
1143 }
1144 Ok(())
1145 }
1146
1147 #[inline(always)]
1149 pub(crate) fn write_atom(&mut self, atom: Atom) -> Result<(), Error> {
1150 let atom = ManuallyDrop::new(atom);
1153 match *atom {
1154 Atom::Null => self.write_str("null"),
1155 Atom::Bool(true) => self.write_str("true"),
1156 Atom::Bool(false) => self.write_str("false"),
1157 Atom::Str(ref val) if val.is_borrowed() => self.write_escaped_str(val),
1158 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1159 Atom::U64(val) => self.write_u64(val),
1160 Atom::I64(val) => self.write_i64(val),
1161 Atom::F64(val) => self.write_float(val),
1162 Atom::F32(val) => self.write_float(val),
1163 _ => return self.write_other_atom(ManuallyDrop::into_inner(atom)),
1164 }
1165 Ok(())
1166 }
1167
1168 #[inline(never)]
1169 fn write_other_atom(&mut self, atom: Atom) -> Result<(), Error> {
1170 match atom {
1171 Atom::Str(ref val) | Atom::Lexical(ref val) => self.write_escaped_str(val),
1172 Atom::Ext(ref ext) => self.write_ext_value(ext)?,
1173 Atom::Bytes(ref val) => {
1174 self.write_bytes(val, val.fallback.copied().unwrap_or(self.bytes))
1175 }
1176 Atom::Implicit(ref val) => match json_literal(val) {
1180 Some(text) => self.write_str(text),
1181 None => return self.write_atom(val.value().to_atom()),
1182 },
1183 _ => return Err(Error::new(ErrorKind::UnsupportedType, "unknown atom")),
1184 }
1185 Ok(())
1186 }
1187
1188 fn write_bytes(&mut self, bytes: &[u8], format: BytesFormat) {
1190 match format.encode(bytes) {
1191 Some(encoded) => self.write_escaped_str(&encoded),
1192 None => {
1193 self.write_char('[');
1194 for (idx, &byte) in bytes.iter().enumerate() {
1195 if idx > 0 {
1196 self.write_char(',');
1197 }
1198 self.write_u64(byte.into());
1199 }
1200 self.write_char(']');
1201 }
1202 }
1203 }
1204
1205 fn write_bytes_str(&mut self, bytes: &[u8], fallback: Option<&BytesFormat>) {
1209 let format = fallback.copied().unwrap_or(self.bytes);
1210 let encoded = format
1211 .encode(bytes)
1212 .or_else(|| BytesFormat::BASE64.encode(bytes))
1213 .unwrap_or_default();
1214 self.write_escaped_str(&encoded);
1215 }
1216
1217 #[inline(always)]
1218 pub(crate) fn write_str(&mut self, s: &str) {
1219 self.out.push_str(s);
1220 }
1221
1222 #[inline(always)]
1223 pub(crate) fn write_char(&mut self, c: char) {
1224 debug_assert!(c.is_ascii());
1225 self.out.push(c as u8);
1226 }
1227
1228 #[inline]
1230 fn write_key(&mut self, key: &str, first: bool) {
1231 if find_escape(key.as_bytes()) != key.len() {
1232 if !first {
1233 self.write_char(',');
1234 }
1235 self.write_escaped_str_slow(key);
1236 self.write_char(':');
1237 return;
1238 }
1239 self.out.reserve(key.len() + 4);
1240 unsafe {
1242 if !first {
1243 self.out.push_unchecked(b',');
1244 }
1245 self.out.push_unchecked(b'"');
1246 self.out.push_str_unchecked(key);
1247 self.out.push_unchecked(b'"');
1248 self.out.push_unchecked(b':');
1249 }
1250 }
1251
1252 #[inline]
1255 fn write_float<F: zmij::Float + Into<f64>>(&mut self, val: F) {
1256 let wide: f64 = val.into();
1257 if wide.is_finite() {
1258 self.write_str(zmij::Buffer::new().format_finite(val))
1259 } else {
1260 self.write_non_finite(wide)
1261 }
1262 }
1263
1264 #[cold]
1266 fn write_non_finite(&mut self, val: f64) {
1267 self.write_str(if !self.non_finite_floats {
1268 "null"
1269 } else if val.is_nan() {
1270 "NaN"
1271 } else if val > 0.0 {
1272 "Infinity"
1273 } else {
1274 "-Infinity"
1275 })
1276 }
1277
1278 #[cold]
1283 fn write_ext_key(&mut self, ext: &ExtValue) -> Result<(), Error> {
1284 if ext.is::<u128>() || ext.is::<i128>() {
1285 self.write_char('"');
1286 self.write_ext_value(ext)?;
1287 self.write_char('"');
1288 return Ok(());
1289 }
1290 match ext.fallback() {
1291 Atom::Str(val) | Atom::Lexical(val) => self.write_escaped_str(&val),
1292 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1293 Atom::U64(val) => {
1294 self.write_char('"');
1295 self.write_u64(val);
1296 self.write_char('"');
1297 }
1298 Atom::I64(val) => {
1299 self.write_char('"');
1300 self.write_i64(val);
1301 self.write_char('"');
1302 }
1303 Atom::Bool(val) => self.write_str(if val { "\"true\"" } else { "\"false\"" }),
1304 _ => {
1305 return Err(Error::new(
1306 ErrorKind::UnsupportedType,
1307 "JSON does not support this value for map keys",
1308 ));
1309 }
1310 }
1311 Ok(())
1312 }
1313
1314 #[cold]
1319 fn write_ext_value(&mut self, ext: &ExtValue) -> Result<(), Error> {
1320 if let Some(raw) = ext.downcast_value_ref::<RawInput>()
1323 && raw.is_format(&crate::raw::ID)
1324 && let Some(text) = raw.as_str()
1325 {
1326 self.write_str(text);
1327 return Ok(());
1328 }
1329 if let Some(&val) = ext.downcast_ref::<u128>() {
1332 self.write_int(val);
1333 return Ok(());
1334 } else if let Some(&val) = ext.downcast_ref::<i128>() {
1335 self.write_int(val);
1336 return Ok(());
1337 } else if let Some(val) = ext.downcast_ref::<BigInt>() {
1338 self.write_str(&val.to_string());
1339 return Ok(());
1340 } else if let Some(val) = ext.downcast_ref::<Decimal>() {
1341 self.write_str(val.as_str());
1343 return Ok(());
1344 } else if let Some(val) = ext.downcast_value_ref::<Number>() {
1345 self.write_str(val.as_str());
1347 return Ok(());
1348 }
1349 match ext.fallback() {
1350 Atom::Null => self.write_str("null"),
1351 Atom::Bool(val) => self.write_str(if val { "true" } else { "false" }),
1352 Atom::Str(val) | Atom::Lexical(val) => self.write_escaped_str(&val),
1353 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1354 Atom::U64(val) => self.write_u64(val),
1355 Atom::I64(val) => self.write_i64(val),
1356 Atom::F64(val) => self.write_float(val),
1357 Atom::F32(val) => self.write_float(val),
1358 Atom::Bytes(val) => self.write_bytes_str(&val, val.fallback),
1361 _ => {
1362 return Err(Error::new(
1363 ErrorKind::UnsupportedType,
1364 "JSON does not support this value",
1365 ));
1366 }
1367 }
1368 Ok(())
1369 }
1370
1371 fn write_int<I: core::fmt::Display>(&mut self, val: I) {
1372 self.write_str(&val.to_string())
1373 }
1374
1375 #[inline]
1376 fn write_u64(&mut self, val: u64) {
1377 self.write_str(itoa::Buffer::new().format(val))
1378 }
1379
1380 #[inline]
1381 fn write_i64(&mut self, val: i64) {
1382 self.write_str(itoa::Buffer::new().format(val))
1383 }
1384
1385 #[inline]
1386 fn write_escaped_str(&mut self, value: &str) {
1387 if find_escape(value.as_bytes()) != value.len() {
1388 return self.write_escaped_str_slow(value);
1389 }
1390 self.out.reserve(value.len() + 2);
1391 unsafe {
1393 self.out.push_unchecked(b'"');
1394 self.out.push_str_unchecked(value);
1395 self.out.push_unchecked(b'"');
1396 }
1397 }
1398
1399 #[inline(never)]
1400 fn write_escaped_str_slow(&mut self, value: &str) {
1401 self.write_char('"');
1402
1403 let bytes = value.as_bytes();
1404 let mut start = 0;
1405
1406 loop {
1407 let next = skip_to_escape(bytes, start);
1408 if start < next {
1409 self.write_str(&value[start..next]);
1410 }
1411 if next == bytes.len() {
1412 break;
1413 }
1414
1415 let byte = bytes[next];
1416 match ESCAPE[byte as usize] {
1417 self::BB => self.write_str("\\b"),
1418 self::TT => self.write_str("\\t"),
1419 self::NN => self.write_str("\\n"),
1420 self::FF => self.write_str("\\f"),
1421 self::RR => self.write_str("\\r"),
1422 self::QU => self.write_str("\\\""),
1423 self::BS => self.write_str("\\\\"),
1424 self::U => {
1425 static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
1426 self.write_str("\\u00");
1427 self.write_char(HEX_DIGITS[(byte >> 4) as usize] as char);
1428 self.write_char(HEX_DIGITS[(byte & 0xF) as usize] as char);
1429 }
1430 _ => unreachable!(),
1431 }
1432
1433 start = next + 1;
1434 }
1435
1436 self.write_char('"');
1437 }
1438}
1439
1440const BB: u8 = b'b'; const TT: u8 = b't'; const NN: u8 = b'n'; const FF: u8 = b'f'; const RR: u8 = b'r'; const QU: u8 = b'"'; const BS: u8 = b'\\'; const U: u8 = b'u'; #[rustfmt::skip]
1452static ESCAPE: [u8; 256] = [
1453 U, U, U, U, U, U, U, U, BB, TT, NN, U, FF, RR, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, 0, 0, QU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, BS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ];
1471
1472#[inline]
1476pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String, Error> {
1477 SerializerConfig::new().to_string(value)
1478}
1479
1480fn json_literal<'a>(value: &'a Implicit) -> Option<&'a str> {
1486 let text = value.text().as_str();
1487 let same = match value.value() {
1488 ImplicitValue::Null => text == "null",
1489 ImplicitValue::Bool(value) => text == if value { "true" } else { "false" },
1490 ImplicitValue::U64(value) => is_json_int(text) && text.parse::<u64>() == Ok(value),
1491 ImplicitValue::I64(value) => is_json_int(text) && text.parse::<i64>() == Ok(value),
1492 ImplicitValue::F64(value) => {
1493 value.is_finite()
1494 && Number::parse(text)
1495 .is_ok_and(|x| !x.is_integer() && x.value().to_bits() == value.to_bits())
1496 }
1497 _ => false,
1498 };
1499 same.then_some(text)
1500}
1501
1502fn is_json_int(text: &str) -> bool {
1505 let digits = text.strip_prefix('-').unwrap_or(text).as_bytes();
1506 match digits {
1507 [b'0'] => true,
1508 [b'1'..=b'9', rest @ ..] => rest.iter().all(u8::is_ascii_digit),
1509 _ => false,
1510 }
1511}