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::{BigInt, Decimal, ExtValue, Number};
10use deser_core::ser::SerializeRef;
11use deser_core::ser::{self, EventSink, SerializeDriver};
12use deser_core::{Atom, BytesFormat, Error, ErrorKind, Event, Implicit, ImplicitValue, Serialize};
13
14use crate::Trailing;
15use crate::buf::Buffer;
16use crate::escape::find_escape;
17use crate::pretty::PrettyWriter;
18use crate::scan::skip_to_escape;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
24#[non_exhaustive]
25pub enum Indent {
26 #[default]
28 None,
29 Spaces(usize),
32 Tab,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
44#[non_exhaustive]
45pub enum InlinePolicy {
46 #[default]
48 Never,
49 LeafIfFits(usize),
54}
55
56#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct SerializerConfig {
89 indent: Indent,
90 compact: bool,
91 inline: InlinePolicy,
92 trailing: Trailing,
93 non_finite_floats: bool,
94 context: deser_core::Context,
95}
96
97impl Default for SerializerConfig {
98 fn default() -> SerializerConfig {
99 SerializerConfig::new()
100 }
101}
102
103impl SerializerConfig {
104 pub const fn new() -> SerializerConfig {
106 SerializerConfig {
107 indent: Indent::None,
108 compact: true,
109 inline: InlinePolicy::Never,
110 trailing: Trailing::Strict,
111 non_finite_floats: false,
112 context: deser_core::Context::new(),
113 }
114 }
115
116 pub const fn builder() -> SerializerConfigBuilder {
118 SerializerConfigBuilder::new()
119 }
120
121 pub const fn into_builder(self) -> SerializerConfigBuilder {
123 SerializerConfigBuilder { value: self }
124 }
125
126 pub fn set_context(&mut self, context: deser_core::Context) {
134 self.context = context;
135 }
136
137 pub fn context(&self) -> &deser_core::Context {
139 &self.context
140 }
141
142 #[inline]
144 fn apply_context(&self, driver: &mut SerializeDriver<'_>) {
145 if !self.context.is_empty() {
146 driver.set_default_context(self.context.clone());
147 }
148 }
149
150 pub const fn set_trailing(&mut self, trailing: Trailing) {
175 self.trailing = trailing;
176 }
177
178 pub(crate) fn trailing_mode(&self) -> Trailing {
180 self.trailing
181 }
182
183 pub const fn set_indent(&mut self, indent: Indent) {
199 self.indent = indent;
200 }
201
202 pub const fn set_compact(&mut self, yes: bool) {
217 self.compact = yes;
218 }
219
220 pub const fn set_inline(&mut self, policy: InlinePolicy) {
251 self.inline = policy;
252 }
253
254 pub const fn set_pretty(&mut self, indent: Indent) {
272 self.indent = indent;
273 self.compact = matches!(indent, Indent::None);
274 }
275
276 pub const fn set_non_finite_floats(&mut self, yes: bool) {
300 self.non_finite_floats = yes;
301 }
302
303 #[inline]
307 pub fn to_string<T: Serialize + ?Sized>(&self, value: &T) -> Result<String, Error> {
308 let value = SerializeRef::new(&value);
312 if self.is_compact() {
313 self.to_string_compact(value)
314 } else {
315 self.to_string_pretty(value)
316 }
317 }
318
319 #[inline(never)]
321 fn to_string_compact(&self, value: SerializeRef<'_>) -> Result<String, Error> {
322 let mut driver = SerializeDriver::from_ref(value);
323 self.apply_context(&mut driver);
324 accept_raw(&mut driver);
325 self.serialize_compact(&mut driver)
326 }
327
328 #[inline(never)]
330 fn to_string_pretty(&self, value: SerializeRef<'_>) -> Result<String, Error> {
331 let mut driver = SerializeDriver::from_ref(value);
332 self.apply_context(&mut driver);
333 accept_raw(&mut driver);
334 self.serialize_pretty(&mut driver)
335 }
336
337 pub fn to_string_with<F, T: Serialize + ?Sized>(
373 &self,
374 value: &T,
375 setup: F,
376 ) -> Result<String, Error>
377 where
378 F: FnOnce(&mut SerializeDriver<'_>),
379 {
380 let mut driver = SerializeDriver::new(&value);
381 setup(&mut driver);
382 self.apply_context(&mut driver);
383 self.serialize_driver(&mut driver)
384 }
385
386 #[inline]
391 pub(crate) fn serialize_driver(
392 &self,
393 driver: &mut SerializeDriver<'_>,
394 ) -> Result<String, Error> {
395 accept_raw(driver);
396 if self.is_compact() {
397 self.serialize_compact(driver)
398 } else {
399 self.serialize_pretty(driver)
400 }
401 }
402
403 #[inline(always)]
405 fn is_compact(&self) -> bool {
406 self.indent == Indent::None && self.compact
407 }
408
409 #[inline(never)]
411 fn serialize_compact(&self, driver: &mut SerializeDriver<'_>) -> Result<String, Error> {
412 let bytes = BytesFormat::of(driver.state());
413 let mut writer = self.compact_writer(Buffer::with_capacity(128), bytes);
414 driver.drive_sink(&mut writer)?;
415 Ok(writer.ser.out.into_string())
416 }
417
418 #[inline(never)]
420 fn serialize_pretty(&self, driver: &mut SerializeDriver<'_>) -> Result<String, Error> {
421 let bytes = BytesFormat::of(driver.state());
422 let mut writer = self.pretty_writer(Buffer::with_capacity(128), bytes);
423 driver.drive(|event, state| writer.event(event, state))?;
424 Ok(writer.finish())
425 }
426
427 fn compact_writer(&self, out: Buffer, bytes: BytesFormat) -> Writer {
429 Writer {
430 ser: Output {
431 out,
432 bytes,
433 non_finite_floats: self.non_finite_floats,
434 },
435 stack: Vec::new(),
436 container: Container::Top,
437 first: true,
438 is_key: false,
439 limit: usize::MAX,
440 }
441 }
442
443 fn pretty_writer(&self, out: Buffer, bytes: BytesFormat) -> PrettyWriter {
445 let ser = Output {
446 out,
447 bytes,
448 non_finite_floats: self.non_finite_floats,
449 };
450 let inline_width = match self.inline {
451 InlinePolicy::Never => None,
452 InlinePolicy::LeafIfFits(width) => Some(width),
453 };
454 PrettyWriter::new(ser, self.indent, self.compact, inline_width)
455 }
456
457 pub(crate) fn value_writer(&self, out: Buffer, bytes: BytesFormat) -> ValueWriter {
459 if self.is_compact() {
460 ValueWriter::Compact(self.compact_writer(out, bytes))
461 } else {
462 ValueWriter::Pretty(self.pretty_writer(out, bytes))
463 }
464 }
465}
466
467#[derive(Debug, Clone)]
471#[must_use]
472pub struct SerializerConfigBuilder {
473 value: SerializerConfig,
474}
475
476impl SerializerConfigBuilder {
477 pub const fn new() -> SerializerConfigBuilder {
479 SerializerConfigBuilder {
480 value: SerializerConfig::new(),
481 }
482 }
483
484 pub const fn trailing(mut self, trailing: Trailing) -> SerializerConfigBuilder {
488 self.value.set_trailing(trailing);
489 self
490 }
491
492 pub const fn indent(mut self, indent: Indent) -> SerializerConfigBuilder {
496 self.value.set_indent(indent);
497 self
498 }
499
500 pub const fn compact(mut self, yes: bool) -> SerializerConfigBuilder {
504 self.value.set_compact(yes);
505 self
506 }
507
508 pub const fn inline(mut self, policy: InlinePolicy) -> SerializerConfigBuilder {
512 self.value.set_inline(policy);
513 self
514 }
515
516 pub const fn pretty(mut self, indent: Indent) -> SerializerConfigBuilder {
520 self.value.set_pretty(indent);
521 self
522 }
523
524 pub const fn non_finite_floats(mut self, yes: bool) -> SerializerConfigBuilder {
528 self.value.set_non_finite_floats(yes);
529 self
530 }
531
532 pub fn context(mut self, context: deser_core::Context) -> SerializerConfigBuilder {
536 self.value.set_context(context);
537 self
538 }
539
540 pub const fn build(self) -> SerializerConfig {
542 let value = unsafe { core::ptr::read(&self.value) };
546 core::mem::forget(self);
547 value
548 }
549}
550
551impl Default for SerializerConfigBuilder {
552 fn default() -> SerializerConfigBuilder {
553 SerializerConfigBuilder::new()
554 }
555}
556
557fn accept_raw(_driver: &mut SerializeDriver<'_>) {}
559
560pub(crate) enum ValueWriter {
562 Compact(Writer),
564 Pretty(PrettyWriter),
566}
567
568impl ValueWriter {
569 pub(crate) fn drive(
575 &mut self,
576 driver: &mut SerializeDriver<'_>,
577 limit: usize,
578 ) -> Result<bool, Error> {
579 if limit == usize::MAX {
580 return self.drive_whole(driver).map(|()| true);
581 }
582 match self {
583 ValueWriter::Compact(writer) => {
584 writer.limit = limit;
585 driver.drive_until(writer)
586 }
587 ValueWriter::Pretty(writer) => {
588 writer.limit = limit;
589 driver.drive_until(writer)
590 }
591 }
592 }
593
594 pub(crate) fn drive_whole(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
599 match self {
600 ValueWriter::Compact(writer) => driver.drive_sink(writer),
601 ValueWriter::Pretty(writer) => driver.drive(|event, state| writer.event(event, state)),
602 }
603 }
604
605 pub(crate) fn output(&mut self) -> &mut Buffer {
607 match self {
608 ValueWriter::Compact(writer) => &mut writer.ser.out,
609 ValueWriter::Pretty(writer) => writer.output(),
610 }
611 }
612
613 pub(crate) fn take_output(&mut self) -> Vec<u8> {
616 match self {
617 ValueWriter::Compact(writer) => writer.ser.out.take(),
618 ValueWriter::Pretty(writer) => writer.take_output(),
619 }
620 }
621}
622
623pub struct Serializer {
658 config: SerializerConfig,
659 out: Vec<u8>,
662 written: usize,
663 value: Option<Box<ValueWriter>>,
665 in_progress: bool,
667}
668
669impl Default for Serializer {
670 fn default() -> Serializer {
671 Serializer::new()
672 }
673}
674
675impl Clone for Serializer {
676 fn clone(&self) -> Serializer {
682 Serializer {
683 config: self.config.clone(),
684 out: self.out.clone(),
685 written: self.written,
686 value: None,
687 in_progress: self.in_progress,
688 }
689 }
690}
691
692impl core::fmt::Debug for Serializer {
693 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
694 f.debug_struct("Serializer")
695 .field("config", &self.config)
696 .field("output", &self.as_str())
697 .field("written", &self.written)
698 .field("in_progress", &self.in_progress)
699 .finish()
700 }
701}
702
703impl Serializer {
704 pub fn new() -> Serializer {
706 Serializer::with_config(SerializerConfig::new())
707 }
708
709 pub fn with_config(config: SerializerConfig) -> Serializer {
711 Serializer::with_written(config, 0)
712 }
713
714 pub fn with_written(config: SerializerConfig, written: usize) -> Serializer {
720 Serializer {
721 config,
722 out: Vec::new(),
723 written,
724 value: None,
725 in_progress: false,
726 }
727 }
728
729 pub fn config(&self) -> &SerializerConfig {
731 &self.config
732 }
733
734 pub fn written(&self) -> usize {
736 self.written
737 }
738
739 pub fn serialize<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
743 ser::Serializer::serialize(self, value)
744 }
745
746 pub fn serialize_with<F, T: Serialize + ?Sized>(
751 &mut self,
752 value: &T,
753 setup: F,
754 ) -> Result<(), Error>
755 where
756 F: FnOnce(&mut SerializeDriver<'_>),
757 {
758 ser::Serializer::serialize_with(self, value, setup)
759 }
760
761 pub fn as_str(&self) -> &str {
763 unsafe { core::str::from_utf8_unchecked(&self.out) }
765 }
766
767 pub fn finish(self) -> String {
769 unsafe { String::from_utf8_unchecked(self.out) }
771 }
772
773 fn start_value(&mut self) -> Result<(), Error> {
775 if self.in_progress {
776 return Err(Error::in_progress());
777 }
778 match self.config.trailing_mode() {
779 Trailing::Strict if self.written > 0 => Err(Error::new(
780 ErrorKind::InvalidState,
781 "with Trailing::Strict only a single value can be written",
782 )),
783 Trailing::Stop if self.written > 0 => {
784 self.out.push(b'\n');
785 Ok(())
786 }
787 _ => Ok(()),
788 }
789 }
790
791 fn finish_value(&mut self) {
793 if self.config.trailing_mode() == Trailing::Newline {
794 self.out.push(b'\n');
795 }
796 self.written += 1;
797 self.in_progress = false;
798 }
799}
800
801impl ser::Serializer for Serializer {
802 fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
803 if self.in_progress {
805 return Err(Error::in_progress());
806 }
807 ser::StreamSerializer::drive_partial(self, driver, usize::MAX).map(|_| ())
808 }
809}
810
811impl ser::StreamSerializer for Serializer {
812 fn output(&self) -> &[u8] {
813 &self.out
814 }
815
816 fn clear_output(&mut self) {
817 self.out.clear();
818 }
819
820 fn supports_partial(&self) -> bool {
821 true
822 }
823
824 fn drive_partial(
825 &mut self,
826 driver: &mut SerializeDriver<'_>,
827 limit: usize,
828 ) -> Result<bool, Error> {
829 if !self.config.context.is_empty() {
830 driver.set_default_context(self.config.context.clone());
831 }
832 accept_raw(driver);
833 let rollback = self.out.len();
834 let (mut local, adopt) = match self.value.take() {
835 Some(mut writer) => {
838 let adopt = self.out.is_empty();
839 if adopt {
840 *writer.output() = Buffer::from_vec(core::mem::take(&mut self.out));
841 }
842 (writer, adopt)
843 }
844 None => {
845 self.start_value()?;
846 let out = Buffer::from_vec(core::mem::take(&mut self.out));
848 let writer = self
849 .config
850 .value_writer(out, BytesFormat::of(driver.state()));
851 if limit == usize::MAX {
852 return self.drive_whole(writer, driver, rollback);
853 }
854 (Box::new(writer), true)
855 }
856 };
857 let rv = local.drive(driver, limit);
858 match rv {
859 Ok(done) => {
860 let output = local.take_output();
861 if adopt {
862 self.out = output;
863 } else {
864 self.out.extend_from_slice(&output);
865 }
866 if done {
867 self.finish_value();
868 Ok(true)
869 } else {
870 self.value = Some(local);
871 self.in_progress = true;
872 Ok(false)
873 }
874 }
875 Err(err) => {
876 if adopt {
880 self.out = local.output().take();
881 self.out.truncate(rollback);
882 }
883 Err(err)
884 }
885 }
886 }
887
888 fn in_progress(&self) -> bool {
889 self.in_progress
890 }
891}
892
893impl Serializer {
894 fn drive_whole(
896 &mut self,
897 mut writer: ValueWriter,
898 driver: &mut SerializeDriver<'_>,
899 rollback: usize,
900 ) -> Result<bool, Error> {
901 let rv = writer.drive_whole(driver);
902 self.out = writer.output().take();
903 match rv {
904 Ok(_) => {
905 self.finish_value();
906 Ok(true)
907 }
908 Err(err) => {
909 self.out.truncate(rollback);
910 Err(err)
911 }
912 }
913 }
914}
915
916#[cfg(feature = "io")]
917impl SerializerConfig {
918 pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
936 deser_core::io::Writer::new(writer, Serializer::with_config(self.clone()))
937 }
938
939 pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
943 &self,
944 writer: W,
945 value: &T,
946 ) -> Result<(), Error> {
947 self.writer(writer).write(value)
948 }
949}
950
951#[cfg(feature = "io")]
963pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
964 writer: W,
965 value: &T,
966) -> Result<(), Error> {
967 SerializerConfig::new().to_writer(writer, value)
968}
969
970pub(crate) struct Output {
972 pub(crate) out: Buffer,
973 bytes: BytesFormat,
974 non_finite_floats: bool,
976}
977
978#[derive(Clone, Copy, PartialEq, Eq)]
979enum Container {
980 Top,
981 Seq,
982 Map,
983}
984
985pub(crate) struct Writer {
987 ser: Output,
988 stack: Vec<Container>,
991 container: Container,
992 first: bool,
993 is_key: bool,
994 limit: usize,
996}
997
998impl EventSink for Writer {
999 #[inline(always)]
1000 fn event(
1001 &mut self,
1002 event: Event<'_>,
1003 _value: SerializeRef<'_>,
1004 _state: &mut deser_core::State,
1005 ) -> Result<(), Error> {
1006 Writer::event(self, event)
1007 }
1008
1009 #[inline(always)]
1010 fn pause(&mut self) -> bool {
1011 self.ser.out.len() >= self.limit
1012 }
1013}
1014
1015impl Writer {
1016 #[inline(always)]
1017 fn event(&mut self, event: Event) -> Result<(), Error> {
1018 match event {
1019 Event::Atom(atom) => {
1020 if self.is_key {
1021 self.ser.write_key_atom(atom, self.first)?;
1022 self.is_key = false;
1023 } else {
1024 match self.container {
1025 Container::Seq => {
1026 if !self.first {
1027 self.ser.write_char(',');
1028 }
1029 }
1030 Container::Map => self.is_key = true,
1031 Container::Top => {}
1032 }
1033 self.ser.write_atom(atom)?;
1034 }
1035 self.first = false;
1036 Ok(())
1037 }
1038 Event::MapStart(_) => self.start(true),
1039 Event::SeqStart(_) => self.start(false),
1040 Event::MapEnd => self.end(true),
1041 Event::SeqEnd => self.end(false),
1042 }
1043 }
1044
1045 #[inline]
1046 fn start(&mut self, is_map: bool) -> Result<(), Error> {
1047 if self.is_key {
1048 return Err(Error::new(
1049 ErrorKind::UnsupportedType,
1050 "JSON does not support this value for map keys",
1051 ));
1052 }
1053 if self.container == Container::Seq && !self.first {
1054 self.ser.write_char(',');
1055 }
1056 self.stack.push(self.container);
1057 self.first = true;
1058 if is_map {
1059 self.container = Container::Map;
1060 self.is_key = true;
1061 self.ser.write_char('{');
1062 } else {
1063 self.container = Container::Seq;
1064 self.ser.write_char('[');
1065 }
1066 Ok(())
1067 }
1068
1069 #[inline]
1070 fn end(&mut self, is_map: bool) -> Result<(), Error> {
1071 if is_map {
1072 if self.container != Container::Map || !self.is_key {
1073 return Err(Error::new(ErrorKind::InvalidState, "unexpected map end"));
1074 }
1075 self.ser.write_char('}');
1076 } else {
1077 if self.container != Container::Seq {
1078 return Err(Error::new(ErrorKind::InvalidState, "unexpected array end"));
1079 }
1080 self.ser.write_char(']');
1081 }
1082 self.container = self.stack.pop().unwrap_or(Container::Top);
1083 self.first = false;
1086 self.is_key = self.container == Container::Map;
1087 Ok(())
1088 }
1089}
1090
1091impl Output {
1092 #[inline(always)]
1094 fn write_key_atom(&mut self, atom: Atom, first: bool) -> Result<(), Error> {
1095 let atom = ManuallyDrop::new(atom);
1098 match *atom {
1099 Atom::Str(ref val) | Atom::Lexical(ref val) if val.is_borrowed() => {
1101 self.write_key(val, first);
1102 Ok(())
1103 }
1104 _ => self.write_other_key_atom(ManuallyDrop::into_inner(atom), first),
1105 }
1106 }
1107
1108 #[inline(never)]
1109 fn write_other_key_atom(&mut self, atom: Atom, first: bool) -> Result<(), Error> {
1110 if !first {
1111 self.write_char(',');
1112 }
1113 self.write_key_text(atom)?;
1114 self.write_char(':');
1115 Ok(())
1116 }
1117
1118 pub(crate) fn write_key_text(&mut self, atom: Atom) -> Result<(), Error> {
1120 match atom {
1121 Atom::Str(ref val) | Atom::Lexical(ref val) => self.write_escaped_str(val),
1122 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1123 Atom::U64(val) => {
1124 self.write_char('"');
1125 self.write_u64(val);
1126 self.write_char('"');
1127 }
1128 Atom::I64(val) => {
1129 self.write_char('"');
1130 self.write_i64(val);
1131 self.write_char('"');
1132 }
1133 Atom::Bool(val) => self.write_str(if val { "\"true\"" } else { "\"false\"" }),
1134 Atom::Ext(ref ext) => self.write_ext_key(ext)?,
1135 Atom::Bytes(ref val) => self.write_bytes_str(val, val.fallback),
1136 Atom::Implicit(ref val) => match json_literal(val) {
1137 Some(text) if val.value() != ImplicitValue::Null => self.write_escaped_str(text),
1138 _ => return self.write_key_text(val.value().to_atom()),
1139 },
1140 _ => {
1141 return Err(Error::new(
1142 ErrorKind::UnsupportedType,
1143 "JSON does not support this value for map keys",
1144 ));
1145 }
1146 }
1147 Ok(())
1148 }
1149
1150 #[inline(always)]
1152 pub(crate) fn write_atom(&mut self, atom: Atom) -> Result<(), Error> {
1153 let atom = ManuallyDrop::new(atom);
1156 match *atom {
1157 Atom::Null => self.write_str("null"),
1158 Atom::Bool(true) => self.write_str("true"),
1159 Atom::Bool(false) => self.write_str("false"),
1160 Atom::Str(ref val) if val.is_borrowed() => self.write_escaped_str(val),
1161 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1162 Atom::U64(val) => self.write_u64(val),
1163 Atom::I64(val) => self.write_i64(val),
1164 Atom::F64(val) => self.write_float(val),
1165 Atom::F32(val) => self.write_float(val),
1166 _ => return self.write_other_atom(ManuallyDrop::into_inner(atom)),
1167 }
1168 Ok(())
1169 }
1170
1171 #[inline(never)]
1172 fn write_other_atom(&mut self, atom: Atom) -> Result<(), Error> {
1173 match atom {
1174 Atom::Str(ref val) | Atom::Lexical(ref val) => self.write_escaped_str(val),
1175 Atom::Ext(ref ext) => self.write_ext_value(ext)?,
1176 Atom::Bytes(ref val) => {
1177 self.write_bytes(val, val.fallback.copied().unwrap_or(self.bytes))
1178 }
1179 Atom::Implicit(ref val) => match json_literal(val) {
1183 Some(text) => self.write_str(text),
1184 None => return self.write_atom(val.value().to_atom()),
1185 },
1186 _ => return Err(Error::new(ErrorKind::UnsupportedType, "unknown atom")),
1187 }
1188 Ok(())
1189 }
1190
1191 fn write_bytes(&mut self, bytes: &[u8], format: BytesFormat) {
1193 match format.encode(bytes) {
1194 Some(encoded) => self.write_escaped_str(&encoded),
1195 None => {
1196 self.write_char('[');
1197 for (idx, &byte) in bytes.iter().enumerate() {
1198 if idx > 0 {
1199 self.write_char(',');
1200 }
1201 self.write_u64(byte.into());
1202 }
1203 self.write_char(']');
1204 }
1205 }
1206 }
1207
1208 fn write_bytes_str(&mut self, bytes: &[u8], fallback: Option<&BytesFormat>) {
1212 let format = fallback.copied().unwrap_or(self.bytes);
1213 let encoded = format
1214 .encode(bytes)
1215 .or_else(|| BytesFormat::BASE64.encode(bytes))
1216 .unwrap_or_default();
1217 self.write_escaped_str(&encoded);
1218 }
1219
1220 #[inline(always)]
1221 pub(crate) fn write_str(&mut self, s: &str) {
1222 self.out.push_str(s);
1223 }
1224
1225 #[inline(always)]
1226 pub(crate) fn write_char(&mut self, c: char) {
1227 assert!(c.is_ascii(), "only ASCII characters can be written");
1230 self.out.push(c as u8);
1231 }
1232
1233 #[inline]
1235 fn write_key(&mut self, key: &str, first: bool) {
1236 if find_escape(key.as_bytes()) != key.len() {
1237 if !first {
1238 self.write_char(',');
1239 }
1240 self.write_escaped_str_slow(key);
1241 self.write_char(':');
1242 return;
1243 }
1244 self.out.reserve(key.len() + 4);
1245 unsafe {
1247 if !first {
1248 self.out.push_unchecked(b',');
1249 }
1250 self.out.push_unchecked(b'"');
1251 self.out.push_str_unchecked(key);
1252 self.out.push_unchecked(b'"');
1253 self.out.push_unchecked(b':');
1254 }
1255 }
1256
1257 #[inline]
1260 fn write_float<F: zmij::Float + Into<f64>>(&mut self, val: F) {
1261 let wide: f64 = val.into();
1262 if wide.is_finite() {
1263 self.write_str(zmij::Buffer::new().format_finite(val))
1264 } else {
1265 self.write_non_finite(wide)
1266 }
1267 }
1268
1269 #[cold]
1271 fn write_non_finite(&mut self, val: f64) {
1272 self.write_str(if !self.non_finite_floats {
1273 "null"
1274 } else if val.is_nan() {
1275 "NaN"
1276 } else if val > 0.0 {
1277 "Infinity"
1278 } else {
1279 "-Infinity"
1280 })
1281 }
1282
1283 #[cold]
1288 fn write_ext_key(&mut self, ext: &ExtValue) -> Result<(), Error> {
1289 if ext.is::<u128>() || ext.is::<i128>() {
1290 self.write_char('"');
1291 self.write_ext_value(ext)?;
1292 self.write_char('"');
1293 return Ok(());
1294 }
1295 match ext.fallback() {
1296 Atom::Str(val) | Atom::Lexical(val) => self.write_escaped_str(&val),
1297 Atom::Char(c) => self.write_escaped_str(c.encode_utf8(&mut [0u8; 4])),
1298 Atom::U64(val) => {
1299 self.write_char('"');
1300 self.write_u64(val);
1301 self.write_char('"');
1302 }
1303 Atom::I64(val) => {
1304 self.write_char('"');
1305 self.write_i64(val);
1306 self.write_char('"');
1307 }
1308 Atom::Bool(val) => self.write_str(if val { "\"true\"" } else { "\"false\"" }),
1309 _ => {
1310 return Err(Error::new(
1311 ErrorKind::UnsupportedType,
1312 "JSON does not support this value for map keys",
1313 ));
1314 }
1315 }
1316 Ok(())
1317 }
1318
1319 #[cold]
1324 fn write_ext_value(&mut self, ext: &ExtValue) -> Result<(), Error> {
1325 if let Some(&val) = ext.downcast_ref::<u128>() {
1328 self.write_int(val);
1329 return Ok(());
1330 } else if let Some(&val) = ext.downcast_ref::<i128>() {
1331 self.write_int(val);
1332 return Ok(());
1333 } else if let Some(val) = ext.downcast_ref::<BigInt>() {
1334 let text = val.to_string();
1335 check_number(&text)?;
1336 self.write_str(&text);
1337 return Ok(());
1338 } else if let Some(val) = ext.downcast_ref::<Decimal>() {
1339 check_number(val.as_str())?;
1341 self.write_str(val.as_str());
1342 return Ok(());
1343 } else if let Some(val) = ext.downcast_value_ref::<Number>() {
1344 check_number(val.as_str())?;
1346 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
1502#[cold]
1507fn check_number(text: &str) -> Result<(), Error> {
1508 match text.parse::<f64>() {
1509 Ok(value) if value.is_finite() => Ok(()),
1510 _ => Err(Error::new(ErrorKind::OutOfRange, "number out of range")),
1511 }
1512}
1513
1514fn is_json_int(text: &str) -> bool {
1517 let digits = text.strip_prefix('-').unwrap_or(text).as_bytes();
1518 match digits {
1519 [b'0'] => true,
1520 [b'1'..=b'9', rest @ ..] => rest.iter().all(u8::is_ascii_digit),
1521 _ => false,
1522 }
1523}