1use alloc::boxed::Box;
4use alloc::string::String;
5use alloc::string::ToString;
6use alloc::vec::Vec;
7use core::mem::ManuallyDrop;
8
9use deser_core::ext::RawInput;
10use deser_core::ext::{BigInt, Decimal, ExtValue, Number};
11use deser_core::ser::SerializeRef;
12use deser_core::ser::{self, EventSink, SerializeDriver};
13use deser_core::{Atom, BytesFormat, Error, ErrorKind, Event, Implicit, ImplicitValue, Serialize};
14
15use crate::Trailing;
16use crate::buf::Buffer;
17use crate::escape::find_escape;
18use crate::pretty::PrettyWriter;
19use crate::scan::skip_to_escape;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
25#[non_exhaustive]
26pub enum Indent {
27 #[default]
29 None,
30 Spaces(usize),
33 Tab,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
45#[non_exhaustive]
46pub enum InlinePolicy {
47 #[default]
49 Never,
50 LeafIfFits(usize),
55}
56
57#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct SerializerConfig {
90 indent: Indent,
91 compact: bool,
92 inline: InlinePolicy,
93 trailing: Trailing,
94 non_finite_floats: bool,
95 context: deser_core::Context,
96}
97
98impl Default for SerializerConfig {
99 fn default() -> SerializerConfig {
100 SerializerConfig::new()
101 }
102}
103
104impl SerializerConfig {
105 pub const fn new() -> SerializerConfig {
107 SerializerConfig {
108 indent: Indent::None,
109 compact: true,
110 inline: InlinePolicy::Never,
111 trailing: Trailing::Strict,
112 non_finite_floats: false,
113 context: deser_core::Context::new(),
114 }
115 }
116
117 pub const fn builder() -> SerializerConfigBuilder {
119 SerializerConfigBuilder::new()
120 }
121
122 pub const fn into_builder(self) -> SerializerConfigBuilder {
124 SerializerConfigBuilder { value: self }
125 }
126
127 pub fn set_context(&mut self, context: deser_core::Context) {
135 self.context = context;
136 }
137
138 pub fn context(&self) -> &deser_core::Context {
140 &self.context
141 }
142
143 #[inline]
145 fn apply_context(&self, driver: &mut SerializeDriver<'_>) {
146 if !self.context.is_empty() {
147 driver.set_default_context(self.context.clone());
148 }
149 }
150
151 pub const fn set_trailing(&mut self, trailing: Trailing) {
176 self.trailing = trailing;
177 }
178
179 pub(crate) fn trailing_mode(&self) -> Trailing {
181 self.trailing
182 }
183
184 pub const fn set_indent(&mut self, indent: Indent) {
200 self.indent = indent;
201 }
202
203 pub const fn set_compact(&mut self, yes: bool) {
218 self.compact = yes;
219 }
220
221 pub const fn set_inline(&mut self, policy: InlinePolicy) {
252 self.inline = policy;
253 }
254
255 pub const fn set_pretty(&mut self, indent: Indent) {
273 self.indent = indent;
274 self.compact = matches!(indent, Indent::None);
275 }
276
277 pub const fn set_non_finite_floats(&mut self, yes: bool) {
301 self.non_finite_floats = yes;
302 }
303
304 #[inline]
308 pub fn to_string<T: Serialize + ?Sized>(&self, value: &T) -> Result<String, Error> {
309 let value = SerializeRef::new(&value);
313 if self.is_compact() {
314 self.to_string_compact(value)
315 } else {
316 self.to_string_pretty(value)
317 }
318 }
319
320 #[inline(never)]
322 fn to_string_compact(&self, value: SerializeRef<'_>) -> Result<String, Error> {
323 let mut driver = SerializeDriver::from_ref(value);
324 self.apply_context(&mut driver);
325 accept_raw(&mut driver);
326 self.serialize_compact(&mut driver)
327 }
328
329 #[inline(never)]
331 fn to_string_pretty(&self, value: SerializeRef<'_>) -> Result<String, Error> {
332 let mut driver = SerializeDriver::from_ref(value);
333 self.apply_context(&mut driver);
334 accept_raw(&mut driver);
335 self.serialize_pretty(&mut driver)
336 }
337
338 pub fn to_string_with<F, T: Serialize + ?Sized>(
374 &self,
375 value: &T,
376 setup: F,
377 ) -> Result<String, Error>
378 where
379 F: FnOnce(&mut SerializeDriver<'_>),
380 {
381 let mut driver = SerializeDriver::new(&value);
382 setup(&mut driver);
383 self.apply_context(&mut driver);
384 self.serialize_driver(&mut driver)
385 }
386
387 #[inline]
392 pub(crate) fn serialize_driver(
393 &self,
394 driver: &mut SerializeDriver<'_>,
395 ) -> Result<String, Error> {
396 accept_raw(driver);
397 if self.is_compact() {
398 self.serialize_compact(driver)
399 } else {
400 self.serialize_pretty(driver)
401 }
402 }
403
404 #[inline(always)]
406 fn is_compact(&self) -> bool {
407 self.indent == Indent::None && self.compact
408 }
409
410 #[inline(never)]
412 fn serialize_compact(&self, driver: &mut SerializeDriver<'_>) -> Result<String, Error> {
413 let bytes = BytesFormat::of(driver.state());
414 let mut writer = self.compact_writer(Buffer::with_capacity(128), bytes);
415 driver.drive_sink(&mut writer)?;
416 Ok(writer.ser.out.into_string())
417 }
418
419 #[inline(never)]
421 fn serialize_pretty(&self, driver: &mut SerializeDriver<'_>) -> Result<String, Error> {
422 let bytes = BytesFormat::of(driver.state());
423 let mut writer = self.pretty_writer(Buffer::with_capacity(128), bytes);
424 driver.drive(|event, state| writer.event(event, state))?;
425 Ok(writer.finish())
426 }
427
428 fn compact_writer(&self, out: Buffer, bytes: BytesFormat) -> Writer {
430 Writer {
431 ser: Output {
432 out,
433 bytes,
434 non_finite_floats: self.non_finite_floats,
435 },
436 stack: Vec::new(),
437 container: Container::Top,
438 first: true,
439 is_key: false,
440 limit: usize::MAX,
441 }
442 }
443
444 fn pretty_writer(&self, out: Buffer, bytes: BytesFormat) -> PrettyWriter {
446 let ser = Output {
447 out,
448 bytes,
449 non_finite_floats: self.non_finite_floats,
450 };
451 let inline_width = match self.inline {
452 InlinePolicy::Never => None,
453 InlinePolicy::LeafIfFits(width) => Some(width),
454 };
455 PrettyWriter::new(ser, self.indent, self.compact, inline_width)
456 }
457
458 pub(crate) fn value_writer(&self, out: Buffer, bytes: BytesFormat) -> ValueWriter {
460 if self.is_compact() {
461 ValueWriter::Compact(self.compact_writer(out, bytes))
462 } else {
463 ValueWriter::Pretty(self.pretty_writer(out, bytes))
464 }
465 }
466}
467
468#[derive(Debug, Clone)]
472#[must_use]
473pub struct SerializerConfigBuilder {
474 value: SerializerConfig,
475}
476
477impl SerializerConfigBuilder {
478 pub const fn new() -> SerializerConfigBuilder {
480 SerializerConfigBuilder {
481 value: SerializerConfig::new(),
482 }
483 }
484
485 pub const fn trailing(mut self, trailing: Trailing) -> SerializerConfigBuilder {
489 self.value.set_trailing(trailing);
490 self
491 }
492
493 pub const fn indent(mut self, indent: Indent) -> SerializerConfigBuilder {
497 self.value.set_indent(indent);
498 self
499 }
500
501 pub const fn compact(mut self, yes: bool) -> SerializerConfigBuilder {
505 self.value.set_compact(yes);
506 self
507 }
508
509 pub const fn inline(mut self, policy: InlinePolicy) -> SerializerConfigBuilder {
513 self.value.set_inline(policy);
514 self
515 }
516
517 pub const fn pretty(mut self, indent: Indent) -> SerializerConfigBuilder {
521 self.value.set_pretty(indent);
522 self
523 }
524
525 pub const fn non_finite_floats(mut self, yes: bool) -> SerializerConfigBuilder {
529 self.value.set_non_finite_floats(yes);
530 self
531 }
532
533 pub fn context(mut self, context: deser_core::Context) -> SerializerConfigBuilder {
537 self.value.set_context(context);
538 self
539 }
540
541 pub const fn build(self) -> SerializerConfig {
543 let value = unsafe { core::ptr::read(&self.value) };
547 core::mem::forget(self);
548 value
549 }
550}
551
552impl Default for SerializerConfigBuilder {
553 fn default() -> SerializerConfigBuilder {
554 SerializerConfigBuilder::new()
555 }
556}
557
558fn accept_raw(driver: &mut SerializeDriver<'_>) {
560 driver.state_mut().declare_raw_format(&crate::raw::ID);
561}
562
563pub(crate) enum ValueWriter {
565 Compact(Writer),
567 Pretty(PrettyWriter),
569}
570
571impl ValueWriter {
572 pub(crate) fn drive(
578 &mut self,
579 driver: &mut SerializeDriver<'_>,
580 limit: usize,
581 ) -> Result<bool, Error> {
582 if limit == usize::MAX {
583 return self.drive_whole(driver).map(|()| true);
584 }
585 match self {
586 ValueWriter::Compact(writer) => {
587 writer.limit = limit;
588 driver.drive_until(writer)
589 }
590 ValueWriter::Pretty(writer) => {
591 writer.limit = limit;
592 driver.drive_until(writer)
593 }
594 }
595 }
596
597 pub(crate) fn drive_whole(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
602 match self {
603 ValueWriter::Compact(writer) => driver.drive_sink(writer),
604 ValueWriter::Pretty(writer) => driver.drive(|event, state| writer.event(event, state)),
605 }
606 }
607
608 pub(crate) fn output(&mut self) -> &mut Buffer {
610 match self {
611 ValueWriter::Compact(writer) => &mut writer.ser.out,
612 ValueWriter::Pretty(writer) => writer.output(),
613 }
614 }
615
616 pub(crate) fn take_output(&mut self) -> Vec<u8> {
619 match self {
620 ValueWriter::Compact(writer) => writer.ser.out.take(),
621 ValueWriter::Pretty(writer) => writer.take_output(),
622 }
623 }
624}
625
626pub struct Serializer {
661 config: SerializerConfig,
662 out: Vec<u8>,
665 written: usize,
666 value: Option<Box<ValueWriter>>,
668 in_progress: bool,
670}
671
672impl Default for Serializer {
673 fn default() -> Serializer {
674 Serializer::new()
675 }
676}
677
678impl Clone for Serializer {
679 fn clone(&self) -> Serializer {
685 Serializer {
686 config: self.config.clone(),
687 out: self.out.clone(),
688 written: self.written,
689 value: None,
690 in_progress: self.in_progress,
691 }
692 }
693}
694
695impl core::fmt::Debug for Serializer {
696 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
697 f.debug_struct("Serializer")
698 .field("config", &self.config)
699 .field("output", &self.as_str())
700 .field("written", &self.written)
701 .field("in_progress", &self.in_progress)
702 .finish()
703 }
704}
705
706impl Serializer {
707 pub fn new() -> Serializer {
709 Serializer::with_config(SerializerConfig::new())
710 }
711
712 pub fn with_config(config: SerializerConfig) -> Serializer {
714 Serializer::with_written(config, 0)
715 }
716
717 pub fn with_written(config: SerializerConfig, written: usize) -> Serializer {
723 Serializer {
724 config,
725 out: Vec::new(),
726 written,
727 value: None,
728 in_progress: false,
729 }
730 }
731
732 pub fn config(&self) -> &SerializerConfig {
734 &self.config
735 }
736
737 pub fn written(&self) -> usize {
739 self.written
740 }
741
742 pub fn serialize<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
746 ser::Serializer::serialize(self, value)
747 }
748
749 pub fn serialize_with<F, T: Serialize + ?Sized>(
754 &mut self,
755 value: &T,
756 setup: F,
757 ) -> Result<(), Error>
758 where
759 F: FnOnce(&mut SerializeDriver<'_>),
760 {
761 ser::Serializer::serialize_with(self, value, setup)
762 }
763
764 pub fn as_str(&self) -> &str {
766 unsafe { core::str::from_utf8_unchecked(&self.out) }
768 }
769
770 pub fn finish(self) -> String {
772 unsafe { String::from_utf8_unchecked(self.out) }
774 }
775
776 fn start_value(&mut self) -> Result<(), Error> {
778 if self.in_progress {
779 return Err(Error::in_progress());
780 }
781 match self.config.trailing_mode() {
782 Trailing::Strict if self.written > 0 => Err(Error::new(
783 ErrorKind::InvalidState,
784 "with Trailing::Strict only a single value can be written",
785 )),
786 Trailing::Stop if self.written > 0 => {
787 self.out.push(b'\n');
788 Ok(())
789 }
790 _ => Ok(()),
791 }
792 }
793
794 fn finish_value(&mut self) {
796 if self.config.trailing_mode() == Trailing::Newline {
797 self.out.push(b'\n');
798 }
799 self.written += 1;
800 self.in_progress = false;
801 }
802}
803
804impl ser::Serializer for Serializer {
805 fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
806 if self.in_progress {
808 return Err(Error::in_progress());
809 }
810 ser::StreamSerializer::drive_partial(self, driver, usize::MAX).map(|_| ())
811 }
812}
813
814impl ser::StreamSerializer for Serializer {
815 fn output(&self) -> &[u8] {
816 &self.out
817 }
818
819 fn clear_output(&mut self) {
820 self.out.clear();
821 }
822
823 fn supports_partial(&self) -> bool {
824 true
825 }
826
827 fn drive_partial(
828 &mut self,
829 driver: &mut SerializeDriver<'_>,
830 limit: usize,
831 ) -> Result<bool, Error> {
832 if !self.config.context.is_empty() {
833 driver.set_default_context(self.config.context.clone());
834 }
835 accept_raw(driver);
836 let rollback = self.out.len();
837 let (mut local, adopt) = match self.value.take() {
838 Some(mut writer) => {
841 let adopt = self.out.is_empty();
842 if adopt {
843 *writer.output() = Buffer::from_vec(core::mem::take(&mut self.out));
844 }
845 (writer, adopt)
846 }
847 None => {
848 self.start_value()?;
849 let out = Buffer::from_vec(core::mem::take(&mut self.out));
851 let writer = self
852 .config
853 .value_writer(out, BytesFormat::of(driver.state()));
854 if limit == usize::MAX {
855 return self.drive_whole(writer, driver, rollback);
856 }
857 (Box::new(writer), true)
858 }
859 };
860 let rv = local.drive(driver, limit);
861 match rv {
862 Ok(done) => {
863 let output = local.take_output();
864 if adopt {
865 self.out = output;
866 } else {
867 self.out.extend_from_slice(&output);
868 }
869 if done {
870 self.finish_value();
871 Ok(true)
872 } else {
873 self.value = Some(local);
874 self.in_progress = true;
875 Ok(false)
876 }
877 }
878 Err(err) => {
879 if adopt {
883 self.out = local.output().take();
884 self.out.truncate(rollback);
885 }
886 Err(err)
887 }
888 }
889 }
890
891 fn in_progress(&self) -> bool {
892 self.in_progress
893 }
894}
895
896impl Serializer {
897 fn drive_whole(
899 &mut self,
900 mut writer: ValueWriter,
901 driver: &mut SerializeDriver<'_>,
902 rollback: usize,
903 ) -> Result<bool, Error> {
904 let rv = writer.drive_whole(driver);
905 self.out = writer.output().take();
906 match rv {
907 Ok(_) => {
908 self.finish_value();
909 Ok(true)
910 }
911 Err(err) => {
912 self.out.truncate(rollback);
913 Err(err)
914 }
915 }
916 }
917}
918
919#[cfg(feature = "io")]
920impl SerializerConfig {
921 pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
939 deser_core::io::Writer::new(writer, Serializer::with_config(self.clone()))
940 }
941
942 pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
946 &self,
947 writer: W,
948 value: &T,
949 ) -> Result<(), Error> {
950 self.writer(writer).write(value)
951 }
952}
953
954#[cfg(feature = "io")]
966pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
967 writer: W,
968 value: &T,
969) -> Result<(), Error> {
970 SerializerConfig::new().to_writer(writer, value)
971}
972
973pub(crate) struct Output {
975 pub(crate) out: Buffer,
976 bytes: BytesFormat,
977 non_finite_floats: bool,
979}
980
981#[derive(Clone, Copy, PartialEq, Eq)]
982enum Container {
983 Top,
984 Seq,
985 Map,
986}
987
988pub(crate) struct Writer {
990 ser: Output,
991 stack: Vec<Container>,
994 container: Container,
995 first: bool,
996 is_key: bool,
997 limit: usize,
999}
1000
1001impl EventSink for Writer {
1002 #[inline(always)]
1003 fn event(
1004 &mut self,
1005 event: Event<'_>,
1006 _value: SerializeRef<'_>,
1007 _state: &mut deser_core::State,
1008 ) -> Result<(), Error> {
1009 Writer::event(self, event)
1010 }
1011
1012 #[inline(always)]
1013 fn pause(&mut self) -> bool {
1014 self.ser.out.len() >= self.limit
1015 }
1016}
1017
1018impl Writer {
1019 #[inline(always)]
1020 fn event(&mut self, event: Event) -> Result<(), Error> {
1021 match event {
1022 Event::Atom(atom) => {
1023 if self.is_key {
1024 self.ser.write_key_atom(atom, self.first)?;
1025 self.is_key = false;
1026 } else {
1027 match self.container {
1028 Container::Seq => {
1029 if !self.first {
1030 self.ser.write_char(',');
1031 }
1032 }
1033 Container::Map => self.is_key = true,
1034 Container::Top => {}
1035 }
1036 self.ser.write_atom(atom)?;
1037 }
1038 self.first = false;
1039 Ok(())
1040 }
1041 Event::MapStart(_) => self.start(true),
1042 Event::SeqStart(_) => self.start(false),
1043 Event::MapEnd => self.end(true),
1044 Event::SeqEnd => self.end(false),
1045 }
1046 }
1047
1048 #[inline]
1049 fn start(&mut self, is_map: bool) -> Result<(), Error> {
1050 if self.is_key {
1051 return Err(Error::new(
1052 ErrorKind::UnsupportedType,
1053 "JSON does not support this value for map keys",
1054 ));
1055 }
1056 if self.container == Container::Seq && !self.first {
1057 self.ser.write_char(',');
1058 }
1059 self.stack.push(self.container);
1060 self.first = true;
1061 if is_map {
1062 self.container = Container::Map;
1063 self.is_key = true;
1064 self.ser.write_char('{');
1065 } else {
1066 self.container = Container::Seq;
1067 self.ser.write_char('[');
1068 }
1069 Ok(())
1070 }
1071
1072 #[inline]
1073 fn end(&mut self, is_map: bool) -> Result<(), Error> {
1074 if is_map {
1075 if self.container != Container::Map || !self.is_key {
1076 return Err(Error::new(ErrorKind::InvalidState, "unexpected map end"));
1077 }
1078 self.ser.write_char('}');
1079 } else {
1080 if self.container != Container::Seq {
1081 return Err(Error::new(ErrorKind::InvalidState, "unexpected array end"));
1082 }
1083 self.ser.write_char(']');
1084 }
1085 self.container = self.stack.pop().unwrap_or(Container::Top);
1086 self.first = false;
1089 self.is_key = self.container == Container::Map;
1090 Ok(())
1091 }
1092}
1093
1094impl Output {
1095 #[inline(always)]
1097 fn write_key_atom(&mut self, atom: Atom, first: bool) -> Result<(), Error> {
1098 let atom = ManuallyDrop::new(atom);
1101 match *atom {
1102 Atom::Str(ref val) | Atom::Lexical(ref val) if val.is_borrowed() => {
1104 self.write_key(val, first);
1105 Ok(())
1106 }
1107 _ => self.write_other_key_atom(ManuallyDrop::into_inner(atom), first),
1108 }
1109 }
1110
1111 #[inline(never)]
1112 fn write_other_key_atom(&mut self, atom: Atom, first: bool) -> Result<(), Error> {
1113 if !first {
1114 self.write_char(',');
1115 }
1116 self.write_key_text(atom)?;
1117 self.write_char(':');
1118 Ok(())
1119 }
1120
1121 pub(crate) fn write_key_text(&mut self, atom: Atom) -> Result<(), Error> {
1123 match atom {
1124 Atom::Str(ref val) | Atom::Lexical(ref val) => self.write_escaped_str(val),
1125 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1126 Atom::U64(val) => {
1127 self.write_char('"');
1128 self.write_u64(val);
1129 self.write_char('"');
1130 }
1131 Atom::I64(val) => {
1132 self.write_char('"');
1133 self.write_i64(val);
1134 self.write_char('"');
1135 }
1136 Atom::Bool(val) => self.write_str(if val { "\"true\"" } else { "\"false\"" }),
1137 Atom::Ext(ref ext) => self.write_ext_key(ext)?,
1138 Atom::Bytes(ref val) => self.write_bytes_str(val, val.fallback),
1139 Atom::Implicit(ref val) => match json_literal(val) {
1140 Some(text) if val.value() != ImplicitValue::Null => self.write_escaped_str(text),
1141 _ => return self.write_key_text(val.value().to_atom()),
1142 },
1143 _ => {
1144 return Err(Error::new(
1145 ErrorKind::UnsupportedType,
1146 "JSON does not support this value for map keys",
1147 ));
1148 }
1149 }
1150 Ok(())
1151 }
1152
1153 #[inline(always)]
1155 pub(crate) fn write_atom(&mut self, atom: Atom) -> Result<(), Error> {
1156 let atom = ManuallyDrop::new(atom);
1159 match *atom {
1160 Atom::Null => self.write_str("null"),
1161 Atom::Bool(true) => self.write_str("true"),
1162 Atom::Bool(false) => self.write_str("false"),
1163 Atom::Str(ref val) if val.is_borrowed() => self.write_escaped_str(val),
1164 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1165 Atom::U64(val) => self.write_u64(val),
1166 Atom::I64(val) => self.write_i64(val),
1167 Atom::F64(val) => self.write_float(val),
1168 Atom::F32(val) => self.write_float(val),
1169 _ => return self.write_other_atom(ManuallyDrop::into_inner(atom)),
1170 }
1171 Ok(())
1172 }
1173
1174 #[inline(never)]
1175 fn write_other_atom(&mut self, atom: Atom) -> Result<(), Error> {
1176 match atom {
1177 Atom::Str(ref val) | Atom::Lexical(ref val) => self.write_escaped_str(val),
1178 Atom::Ext(ref ext) => self.write_ext_value(ext)?,
1179 Atom::Bytes(ref val) => {
1180 self.write_bytes(val, val.fallback.copied().unwrap_or(self.bytes))
1181 }
1182 Atom::Implicit(ref val) => match json_literal(val) {
1186 Some(text) => self.write_str(text),
1187 None => return self.write_atom(val.value().to_atom()),
1188 },
1189 _ => return Err(Error::new(ErrorKind::UnsupportedType, "unknown atom")),
1190 }
1191 Ok(())
1192 }
1193
1194 fn write_bytes(&mut self, bytes: &[u8], format: BytesFormat) {
1196 match format.encode(bytes) {
1197 Some(encoded) => self.write_escaped_str(&encoded),
1198 None => {
1199 self.write_char('[');
1200 for (idx, &byte) in bytes.iter().enumerate() {
1201 if idx > 0 {
1202 self.write_char(',');
1203 }
1204 self.write_u64(byte.into());
1205 }
1206 self.write_char(']');
1207 }
1208 }
1209 }
1210
1211 fn write_bytes_str(&mut self, bytes: &[u8], fallback: Option<&BytesFormat>) {
1215 let format = fallback.copied().unwrap_or(self.bytes);
1216 let encoded = format
1217 .encode(bytes)
1218 .or_else(|| BytesFormat::BASE64.encode(bytes))
1219 .unwrap_or_default();
1220 self.write_escaped_str(&encoded);
1221 }
1222
1223 #[inline(always)]
1224 pub(crate) fn write_str(&mut self, s: &str) {
1225 self.out.push_str(s);
1226 }
1227
1228 #[inline(always)]
1229 pub(crate) fn write_char(&mut self, c: char) {
1230 assert!(c.is_ascii(), "only ASCII characters can be written");
1233 self.out.push(c as u8);
1234 }
1235
1236 #[inline]
1238 fn write_key(&mut self, key: &str, first: bool) {
1239 if find_escape(key.as_bytes()) != key.len() {
1240 if !first {
1241 self.write_char(',');
1242 }
1243 self.write_escaped_str_slow(key);
1244 self.write_char(':');
1245 return;
1246 }
1247 self.out.reserve(key.len() + 4);
1248 unsafe {
1250 if !first {
1251 self.out.push_unchecked(b',');
1252 }
1253 self.out.push_unchecked(b'"');
1254 self.out.push_str_unchecked(key);
1255 self.out.push_unchecked(b'"');
1256 self.out.push_unchecked(b':');
1257 }
1258 }
1259
1260 #[inline]
1263 fn write_float<F: zmij::Float + Into<f64>>(&mut self, val: F) {
1264 let wide: f64 = val.into();
1265 if wide.is_finite() {
1266 self.write_str(zmij::Buffer::new().format_finite(val))
1267 } else {
1268 self.write_non_finite(wide)
1269 }
1270 }
1271
1272 #[cold]
1274 fn write_non_finite(&mut self, val: f64) {
1275 self.write_str(if !self.non_finite_floats {
1276 "null"
1277 } else if val.is_nan() {
1278 "NaN"
1279 } else if val > 0.0 {
1280 "Infinity"
1281 } else {
1282 "-Infinity"
1283 })
1284 }
1285
1286 #[cold]
1291 fn write_ext_key(&mut self, ext: &ExtValue) -> Result<(), Error> {
1292 if ext.is::<u128>() || ext.is::<i128>() {
1293 self.write_char('"');
1294 self.write_ext_value(ext)?;
1295 self.write_char('"');
1296 return Ok(());
1297 }
1298 match ext.fallback() {
1299 Atom::Str(val) | Atom::Lexical(val) => self.write_escaped_str(&val),
1300 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1301 Atom::U64(val) => {
1302 self.write_char('"');
1303 self.write_u64(val);
1304 self.write_char('"');
1305 }
1306 Atom::I64(val) => {
1307 self.write_char('"');
1308 self.write_i64(val);
1309 self.write_char('"');
1310 }
1311 Atom::Bool(val) => self.write_str(if val { "\"true\"" } else { "\"false\"" }),
1312 _ => {
1313 return Err(Error::new(
1314 ErrorKind::UnsupportedType,
1315 "JSON does not support this value for map keys",
1316 ));
1317 }
1318 }
1319 Ok(())
1320 }
1321
1322 #[cold]
1327 fn write_ext_value(&mut self, ext: &ExtValue) -> Result<(), Error> {
1328 if let Some(raw) = ext.downcast_value_ref::<RawInput>()
1331 && raw.is_format(&crate::raw::ID)
1332 && let Some(text) = raw.as_str()
1333 {
1334 self.write_str(text);
1335 return Ok(());
1336 }
1337 if let Some(&val) = ext.downcast_ref::<u128>() {
1340 self.write_int(val);
1341 return Ok(());
1342 } else if let Some(&val) = ext.downcast_ref::<i128>() {
1343 self.write_int(val);
1344 return Ok(());
1345 } else if let Some(val) = ext.downcast_ref::<BigInt>() {
1346 let text = val.to_string();
1347 check_number(&text)?;
1348 self.write_str(&text);
1349 return Ok(());
1350 } else if let Some(val) = ext.downcast_ref::<Decimal>() {
1351 check_number(val.as_str())?;
1353 self.write_str(val.as_str());
1354 return Ok(());
1355 } else if let Some(val) = ext.downcast_value_ref::<Number>() {
1356 check_number(val.as_str())?;
1358 self.write_str(val.as_str());
1359 return Ok(());
1360 }
1361 match ext.fallback() {
1362 Atom::Null => self.write_str("null"),
1363 Atom::Bool(val) => self.write_str(if val { "true" } else { "false" }),
1364 Atom::Str(val) | Atom::Lexical(val) => self.write_escaped_str(&val),
1365 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1366 Atom::U64(val) => self.write_u64(val),
1367 Atom::I64(val) => self.write_i64(val),
1368 Atom::F64(val) => self.write_float(val),
1369 Atom::F32(val) => self.write_float(val),
1370 Atom::Bytes(val) => self.write_bytes_str(&val, val.fallback),
1373 _ => {
1374 return Err(Error::new(
1375 ErrorKind::UnsupportedType,
1376 "JSON does not support this value",
1377 ));
1378 }
1379 }
1380 Ok(())
1381 }
1382
1383 fn write_int<I: core::fmt::Display>(&mut self, val: I) {
1384 self.write_str(&val.to_string())
1385 }
1386
1387 #[inline]
1388 fn write_u64(&mut self, val: u64) {
1389 self.write_str(itoa::Buffer::new().format(val))
1390 }
1391
1392 #[inline]
1393 fn write_i64(&mut self, val: i64) {
1394 self.write_str(itoa::Buffer::new().format(val))
1395 }
1396
1397 #[inline]
1398 fn write_escaped_str(&mut self, value: &str) {
1399 if find_escape(value.as_bytes()) != value.len() {
1400 return self.write_escaped_str_slow(value);
1401 }
1402 self.out.reserve(value.len() + 2);
1403 unsafe {
1405 self.out.push_unchecked(b'"');
1406 self.out.push_str_unchecked(value);
1407 self.out.push_unchecked(b'"');
1408 }
1409 }
1410
1411 #[inline(never)]
1412 fn write_escaped_str_slow(&mut self, value: &str) {
1413 self.write_char('"');
1414
1415 let bytes = value.as_bytes();
1416 let mut start = 0;
1417
1418 loop {
1419 let next = skip_to_escape(bytes, start);
1420 if start < next {
1421 self.write_str(&value[start..next]);
1422 }
1423 if next == bytes.len() {
1424 break;
1425 }
1426
1427 let byte = bytes[next];
1428 match ESCAPE[byte as usize] {
1429 self::BB => self.write_str("\\b"),
1430 self::TT => self.write_str("\\t"),
1431 self::NN => self.write_str("\\n"),
1432 self::FF => self.write_str("\\f"),
1433 self::RR => self.write_str("\\r"),
1434 self::QU => self.write_str("\\\""),
1435 self::BS => self.write_str("\\\\"),
1436 self::U => {
1437 static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
1438 self.write_str("\\u00");
1439 self.write_char(HEX_DIGITS[(byte >> 4) as usize] as char);
1440 self.write_char(HEX_DIGITS[(byte & 0xF) as usize] as char);
1441 }
1442 _ => unreachable!(),
1443 }
1444
1445 start = next + 1;
1446 }
1447
1448 self.write_char('"');
1449 }
1450}
1451
1452const 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]
1464static ESCAPE: [u8; 256] = [
1465 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, ];
1483
1484#[inline]
1488pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String, Error> {
1489 SerializerConfig::new().to_string(value)
1490}
1491
1492fn json_literal<'a>(value: &'a Implicit) -> Option<&'a str> {
1498 let text = value.text().as_str();
1499 let same = match value.value() {
1500 ImplicitValue::Null => text == "null",
1501 ImplicitValue::Bool(value) => text == if value { "true" } else { "false" },
1502 ImplicitValue::U64(value) => is_json_int(text) && text.parse::<u64>() == Ok(value),
1503 ImplicitValue::I64(value) => is_json_int(text) && text.parse::<i64>() == Ok(value),
1504 ImplicitValue::F64(value) => {
1505 value.is_finite()
1506 && Number::parse(text)
1507 .is_ok_and(|x| !x.is_integer() && x.value().to_bits() == value.to_bits())
1508 }
1509 _ => false,
1510 };
1511 same.then_some(text)
1512}
1513
1514#[cold]
1519fn check_number(text: &str) -> Result<(), Error> {
1520 match text.parse::<f64>() {
1521 Ok(value) if value.is_finite() => Ok(()),
1522 _ => Err(Error::new(ErrorKind::OutOfRange, "number out of range")),
1523 }
1524}
1525
1526fn is_json_int(text: &str) -> bool {
1529 let digits = text.strip_prefix('-').unwrap_or(text).as_bytes();
1530 match digits {
1531 [b'0'] => true,
1532 [b'1'..=b'9', rest @ ..] => rest.iter().all(u8::is_ascii_digit),
1533 _ => false,
1534 }
1535}