1use alloc::string::String;
2use alloc::vec::Vec;
3use facet_core::{Def, DynValueKind, Facet, PointerType, StructKind, Type, UserType};
4use facet_reflect::{FieldItem, HasFields, Peek, ScalarType};
5use log::trace;
6
7use crate::RawJson;
8
9#[derive(Debug, Clone)]
11pub struct SerializeOptions {
12 pub pretty: bool,
14 pub indent: &'static str,
16}
17
18impl Default for SerializeOptions {
19 fn default() -> Self {
20 Self {
21 pretty: false,
22 indent: " ",
23 }
24 }
25}
26
27impl SerializeOptions {
28 pub fn new() -> Self {
30 Self::default()
31 }
32
33 pub fn pretty(mut self) -> Self {
35 self.pretty = true;
36 self
37 }
38
39 pub fn indent(mut self, indent: &'static str) -> Self {
41 self.indent = indent;
42 self.pretty = true;
43 self
44 }
45
46 fn indent_str(&self) -> Option<&str> {
48 if self.pretty { Some(self.indent) } else { None }
49 }
50}
51
52pub fn to_string<'facet, T: Facet<'facet> + ?Sized>(value: &T) -> String {
54 peek_to_string(Peek::new(value))
55}
56
57pub fn to_string_pretty<'facet, T: Facet<'facet> + ?Sized>(value: &T) -> String {
59 peek_to_string_pretty(Peek::new(value))
60}
61
62pub fn to_string_with_options<'facet, T: Facet<'facet> + ?Sized>(
86 value: &T,
87 options: &SerializeOptions,
88) -> String {
89 peek_to_string_with_options(Peek::new(value), options)
90}
91
92pub fn peek_to_string<'input, 'facet>(peek: Peek<'input, 'facet>) -> String {
94 peek_to_string_with_options(peek, &SerializeOptions::default())
95}
96
97pub fn peek_to_string_pretty<'input, 'facet>(peek: Peek<'input, 'facet>) -> String {
99 peek_to_string_with_options(peek, &SerializeOptions::default().pretty())
100}
101
102pub fn peek_to_string_with_options<'input, 'facet>(
104 peek: Peek<'input, 'facet>,
105 options: &SerializeOptions,
106) -> String {
107 let mut s = Vec::new();
108 peek_to_writer_with_options(peek, &mut s, options).unwrap();
109 String::from_utf8(s).unwrap()
110}
111
112pub fn to_writer<'mem, 'facet, T: Facet<'facet>, W: crate::JsonWrite>(
114 value: &'mem T,
115 writer: W,
116) -> Result<(), SerializeError> {
117 peek_to_writer(Peek::new(value), writer)
118}
119
120pub fn to_writer_pretty<'mem, 'facet, T: Facet<'facet>, W: crate::JsonWrite>(
122 value: &'mem T,
123 writer: W,
124) -> Result<(), SerializeError> {
125 peek_to_writer_pretty(Peek::new(value), writer)
126}
127
128pub fn to_writer_with_options<'mem, 'facet, T: Facet<'facet>, W: crate::JsonWrite>(
158 value: &'mem T,
159 writer: W,
160 options: &SerializeOptions,
161) -> Result<(), SerializeError> {
162 peek_to_writer_with_options(Peek::new(value), writer, options)
163}
164
165pub fn peek_to_writer<'mem, 'facet, W: crate::JsonWrite>(
167 peek: Peek<'mem, 'facet>,
168 writer: W,
169) -> Result<(), SerializeError> {
170 peek_to_writer_with_options(peek, writer, &SerializeOptions::default())
171}
172
173pub fn peek_to_writer_pretty<'mem, 'facet, W: crate::JsonWrite>(
175 peek: Peek<'mem, 'facet>,
176 writer: W,
177) -> Result<(), SerializeError> {
178 peek_to_writer_with_options(peek, writer, &SerializeOptions::default().pretty())
179}
180
181pub fn peek_to_writer_with_options<'mem, 'facet, W: crate::JsonWrite>(
183 peek: Peek<'mem, 'facet>,
184 mut writer: W,
185 options: &SerializeOptions,
186) -> Result<(), SerializeError> {
187 serialize_value(peek, None, &mut writer, options.indent_str(), 0)
188}
189
190#[cfg(feature = "std")]
213pub fn to_writer_std<'mem, 'facet, W: std::io::Write, T: Facet<'facet>>(
214 writer: W,
215 value: &'mem T,
216) -> std::io::Result<()> {
217 peek_to_writer_std(writer, Peek::new(value))
218}
219
220#[cfg(feature = "std")]
225pub fn to_writer_std_pretty<'mem, 'facet, W: std::io::Write, T: Facet<'facet>>(
226 writer: W,
227 value: &'mem T,
228) -> std::io::Result<()> {
229 peek_to_writer_std_pretty(writer, Peek::new(value))
230}
231
232#[cfg(feature = "std")]
258pub fn to_writer_std_with_options<'mem, 'facet, W: std::io::Write, T: Facet<'facet>>(
259 writer: W,
260 value: &'mem T,
261 options: &SerializeOptions,
262) -> std::io::Result<()> {
263 peek_to_writer_std_with_options(writer, Peek::new(value), options)
264}
265
266#[cfg(feature = "std")]
268pub fn peek_to_writer_std<'mem, 'facet, W: std::io::Write>(
269 writer: W,
270 peek: Peek<'mem, 'facet>,
271) -> std::io::Result<()> {
272 peek_to_writer_std_with_options(writer, peek, &SerializeOptions::default())
273}
274
275#[cfg(feature = "std")]
277pub fn peek_to_writer_std_pretty<'mem, 'facet, W: std::io::Write>(
278 writer: W,
279 peek: Peek<'mem, 'facet>,
280) -> std::io::Result<()> {
281 peek_to_writer_std_with_options(writer, peek, &SerializeOptions::default().pretty())
282}
283
284#[cfg(feature = "std")]
286pub fn peek_to_writer_std_with_options<'mem, 'facet, W: std::io::Write>(
287 writer: W,
288 peek: Peek<'mem, 'facet>,
289 options: &SerializeOptions,
290) -> std::io::Result<()> {
291 let mut adapter = StdWriteAdapter::new(writer);
292 let _ = peek_to_writer_with_options(peek, &mut adapter, options);
293 adapter.into_result()
294}
295
296#[cfg(feature = "std")]
298struct StdWriteAdapter<W> {
299 writer: W,
300 error: Option<std::io::Error>,
301}
302
303#[cfg(feature = "std")]
304impl<W: std::io::Write> StdWriteAdapter<W> {
305 fn new(writer: W) -> Self {
306 Self {
307 writer,
308 error: None,
309 }
310 }
311
312 fn into_result(self) -> std::io::Result<()> {
313 match self.error {
314 Some(e) => Err(e),
315 None => Ok(()),
316 }
317 }
318}
319
320#[cfg(feature = "std")]
321impl<W: std::io::Write> crate::JsonWrite for StdWriteAdapter<W> {
322 fn write(&mut self, buf: &[u8]) {
323 if self.error.is_none()
324 && let Err(e) = self.writer.write_all(buf)
325 {
326 self.error = Some(e);
327 }
328 }
329
330 fn reserve(&mut self, _additional: usize) {
331 }
333}
334
335#[cfg(feature = "std")]
336impl<W: std::io::Write> crate::JsonWrite for &mut StdWriteAdapter<W> {
337 fn write(&mut self, buf: &[u8]) {
338 if self.error.is_none()
339 && let Err(e) = self.writer.write_all(buf)
340 {
341 self.error = Some(e);
342 }
343 }
344
345 fn reserve(&mut self, _additional: usize) {
346 }
348}
349
350#[derive(Debug)]
352pub enum SerializeError {}
353
354fn variant_is_newtype_like(variant: &facet_core::Variant) -> bool {
355 matches!(
356 variant.data.kind,
357 StructKind::Tuple | StructKind::TupleStruct
358 ) && variant.data.fields.len() == 1
359}
360
361fn write_indent<W: crate::JsonWrite>(writer: &mut W, indent: Option<&str>, depth: usize) {
363 if let Some(indent_str) = indent {
364 for _ in 0..depth {
365 writer.write(indent_str.as_bytes());
366 }
367 }
368}
369
370fn write_newline<W: crate::JsonWrite>(writer: &mut W, indent: Option<&str>) {
372 if indent.is_some() {
373 writer.write(b"\n");
374 }
375}
376
377fn write_colon<W: crate::JsonWrite>(writer: &mut W, indent: Option<&str>) {
379 if indent.is_some() {
380 writer.write(b": ");
381 } else {
382 writer.write(b":");
383 }
384}
385
386fn serialize_value<'mem, 'facet, W: crate::JsonWrite>(
387 peek: Peek<'mem, 'facet>,
388 maybe_field_item: Option<FieldItem>,
389 writer: &mut W,
390 indent: Option<&str>,
391 depth: usize,
392) -> Result<(), SerializeError> {
393 trace!("Serializing a value, shape is {}", peek.shape());
394
395 #[cfg(feature = "alloc")]
397 if let Some(fi) = maybe_field_item
398 && fi.field.proxy_convert_out_fn().is_some()
399 {
400 let owned_peek = peek.custom_serialization(fi.field).unwrap();
401 let old_shape = peek.shape();
402 let new_shape = owned_peek.shape();
403 trace!("{old_shape} has custom serialization, serializing as {new_shape} instead");
404 return serialize_value(owned_peek.as_peek(), None, writer, indent, depth);
405 }
406
407 #[cfg(feature = "alloc")]
409 if let Ok(Some(owned_peek)) = peek.custom_serialization_from_shape() {
410 let old_shape = peek.shape();
411 let new_shape = owned_peek.shape();
412 trace!("{old_shape} has container-level proxy, serializing as {new_shape} instead");
413 return serialize_value(owned_peek.as_peek(), None, writer, indent, depth);
414 }
415
416 if peek.shape().is_transparent() {
418 let old_shape = peek.shape();
419 let ps = peek.into_struct().unwrap();
420 let (field, inner_peek) = ps.fields().next().unwrap();
421 let new_shape = inner_peek.shape();
422 trace!("{old_shape} is transparent, let's serialize the inner {new_shape} instead");
423 return serialize_value(
424 inner_peek,
425 Some(FieldItem::new(field)),
426 writer,
427 indent,
428 depth,
429 );
430 }
431
432 if peek.shape() == RawJson::SHAPE {
434 #[allow(unsafe_code)]
436 let raw = unsafe { peek.data().get::<RawJson<'static>>() };
437 writer.write(raw.as_str().as_bytes());
438 return Ok(());
439 }
440
441 trace!(
442 "Matching def={:?}, ty={:?} for shape={}",
443 peek.shape().def,
444 peek.shape().ty,
445 peek.shape()
446 );
447
448 match (peek.shape().def, peek.shape().ty) {
449 (Def::Scalar, _) => {
450 let peek = peek.innermost_peek();
451 serialize_scalar(peek, writer)?;
452 }
453 (Def::List(ld), _) => {
454 if ld.t().is_type::<u8>() && peek.shape().is_type::<Vec<u8>>() {
455 let bytes = peek.get::<Vec<u8>>().unwrap();
457 serialize_byte_array(bytes, writer, indent, depth)?;
458 } else {
459 let peek_list = peek.into_list_like().unwrap();
460 serialize_array(peek_list.iter(), writer, indent, depth)?;
461 }
462 }
463 (Def::Array(ad), _) => {
464 if ad.t().is_type::<u8>() {
465 let bytes: Vec<u8> = peek
466 .into_list_like()
467 .unwrap()
468 .iter()
469 .map(|p| *p.get::<u8>().unwrap())
470 .collect();
471 serialize_byte_array(&bytes, writer, indent, depth)?;
472 } else {
473 let peek_list = peek.into_list_like().unwrap();
474 serialize_array(peek_list.iter(), writer, indent, depth)?;
475 }
476 }
477 (Def::Slice(sd), _) => {
478 if sd.t().is_type::<u8>() {
479 let bytes = peek.get::<[u8]>().unwrap();
480 serialize_byte_array(bytes, writer, indent, depth)?;
481 } else {
482 let peek_list = peek.into_list_like().unwrap();
483 serialize_array(peek_list.iter(), writer, indent, depth)?;
484 }
485 }
486 (Def::Map(_), _) => {
487 let peek_map = peek.into_map().unwrap();
488 writer.write(b"{");
489 let mut first = true;
490 for (key, value) in peek_map.iter() {
491 if !first {
492 writer.write(b",");
493 }
494 first = false;
495 write_newline(writer, indent);
496 write_indent(writer, indent, depth + 1);
497 serialize_map_key(key, writer)?;
498 write_colon(writer, indent);
499 serialize_value(value, None, writer, indent, depth + 1)?;
500 }
501 if !first {
502 write_newline(writer, indent);
503 write_indent(writer, indent, depth);
504 }
505 writer.write(b"}");
506 }
507 (Def::Set(_), _) => {
508 let peek_set = peek.into_set().unwrap();
509 writer.write(b"[");
510 let mut first = true;
511 for item in peek_set.iter() {
512 if !first {
513 writer.write(b",");
514 }
515 first = false;
516 write_newline(writer, indent);
517 write_indent(writer, indent, depth + 1);
518 serialize_value(item, None, writer, indent, depth + 1)?;
519 }
520 if !first {
521 write_newline(writer, indent);
522 write_indent(writer, indent, depth);
523 }
524 writer.write(b"]");
525 }
526 (Def::Option(_), _) => {
527 let opt = peek.into_option().unwrap();
528 if let Some(inner_peek) = opt.value() {
529 serialize_value(inner_peek, None, writer, indent, depth)?;
530 } else {
531 writer.write(b"null");
532 }
533 }
534 (Def::Pointer(_), _) => {
535 let sp = peek.into_pointer().unwrap();
536 if let Some(inner_peek) = sp.borrow_inner() {
537 serialize_value(inner_peek, None, writer, indent, depth)?;
538 } else {
539 panic!(
540 "Smart pointer without borrow support or with opaque pointee cannot be serialized"
541 );
542 }
543 }
544 (_, Type::User(UserType::Struct(sd))) => {
545 trace!("Serializing struct: shape={}", peek.shape());
546 trace!(
547 " Struct details: kind={:?}, field_count={}",
548 sd.kind,
549 sd.fields.len()
550 );
551
552 match sd.kind {
553 StructKind::Unit => {
554 writer.write(b"null");
555 }
556 StructKind::Tuple => {
557 let peek_struct = peek.into_struct().unwrap();
558 writer.write(b"[");
559 let mut first = true;
560 for (field, value) in peek_struct.fields() {
561 if !first {
562 writer.write(b",");
563 }
564 first = false;
565 write_newline(writer, indent);
566 write_indent(writer, indent, depth + 1);
567 serialize_value(
568 value,
569 Some(FieldItem::new(field)),
570 writer,
571 indent,
572 depth + 1,
573 )?;
574 }
575 if !first {
576 write_newline(writer, indent);
577 write_indent(writer, indent, depth);
578 }
579 writer.write(b"]");
580 }
581 StructKind::TupleStruct => {
582 let peek_struct = peek.into_struct().unwrap();
583 writer.write(b"[");
584 let mut first = true;
585 for (field_item, value) in peek_struct.fields_for_serialize() {
586 if !first {
587 writer.write(b",");
588 }
589 first = false;
590 write_newline(writer, indent);
591 write_indent(writer, indent, depth + 1);
592 serialize_value(value, Some(field_item), writer, indent, depth + 1)?;
593 }
594 if !first {
595 write_newline(writer, indent);
596 write_indent(writer, indent, depth);
597 }
598 writer.write(b"]");
599 }
600 StructKind::Struct => {
601 let peek_struct = peek.into_struct().unwrap();
602 writer.write(b"{");
603 let mut first = true;
604 for (field_item, value) in peek_struct.fields_for_serialize() {
605 if !first {
606 writer.write(b",");
607 }
608 first = false;
609 write_newline(writer, indent);
610 write_indent(writer, indent, depth + 1);
611 crate::write_json_string(writer, field_item.name);
612 write_colon(writer, indent);
613 serialize_value(value, Some(field_item), writer, indent, depth + 1)?;
614 }
615 if !first {
616 write_newline(writer, indent);
617 write_indent(writer, indent, depth);
618 }
619 writer.write(b"}");
620 }
621 }
622 }
623 (_, Type::User(UserType::Enum(_))) => {
624 let shape = peek.shape();
625 let peek_enum = peek.into_enum().unwrap();
626 let variant = peek_enum
627 .active_variant()
628 .expect("Failed to get active variant");
629 let variant_index = peek_enum
630 .variant_index()
631 .expect("Failed to get variant index");
632 trace!("Active variant index is {variant_index}, variant is {variant:?}");
633
634 let is_untagged = shape.is_untagged();
636 let tag_field = shape.get_tag_attr();
637 let content_field = shape.get_content_attr();
638
639 if is_untagged {
640 serialize_enum_content(&peek_enum, variant, writer, indent, depth)?;
642 } else if let Some(tag) = tag_field {
643 if let Some(content) = content_field {
644 writer.write(b"{");
646 write_newline(writer, indent);
647 write_indent(writer, indent, depth + 1);
648 crate::write_json_string(writer, tag);
649 write_colon(writer, indent);
650 crate::write_json_string(writer, variant.name);
651
652 if !variant.data.fields.is_empty() {
654 writer.write(b",");
655 write_newline(writer, indent);
656 write_indent(writer, indent, depth + 1);
657 crate::write_json_string(writer, content);
658 write_colon(writer, indent);
659 serialize_enum_content(&peek_enum, variant, writer, indent, depth + 1)?;
660 }
661
662 write_newline(writer, indent);
663 write_indent(writer, indent, depth);
664 writer.write(b"}");
665 } else {
666 writer.write(b"{");
668 write_newline(writer, indent);
669 write_indent(writer, indent, depth + 1);
670 crate::write_json_string(writer, tag);
671 write_colon(writer, indent);
672 crate::write_json_string(writer, variant.name);
673
674 for (field_item, field_peek) in peek_enum.fields_for_serialize() {
676 writer.write(b",");
677 write_newline(writer, indent);
678 write_indent(writer, indent, depth + 1);
679 crate::write_json_string(writer, field_item.name);
680 write_colon(writer, indent);
681 serialize_value(field_peek, Some(field_item), writer, indent, depth + 1)?;
682 }
683
684 write_newline(writer, indent);
685 write_indent(writer, indent, depth);
686 writer.write(b"}");
687 }
688 } else {
689 let flattened = maybe_field_item.map(|fi| fi.flattened).unwrap_or_default();
691
692 if variant.data.fields.is_empty() {
693 crate::write_json_string(writer, variant.name);
695 } else {
696 if !flattened {
697 writer.write(b"{");
699 write_newline(writer, indent);
700 write_indent(writer, indent, depth + 1);
701 crate::write_json_string(writer, variant.name);
702 write_colon(writer, indent);
703 }
704
705 let inner_depth = if flattened { depth } else { depth + 1 };
706 serialize_enum_content(&peek_enum, variant, writer, indent, inner_depth)?;
707
708 if !flattened {
709 write_newline(writer, indent);
710 write_indent(writer, indent, depth);
711 writer.write(b"}");
712 }
713 }
714 }
715 }
716 (Def::DynamicValue(_), _) => {
717 let dyn_val = peek.into_dynamic_value().unwrap();
718 serialize_dynamic_value(dyn_val, writer, indent, depth)?;
719 }
720 (_, Type::Pointer(pointer_type)) => {
721 if let Some(str_value) = peek.as_str() {
722 crate::write_json_string(writer, str_value);
723 } else if let Some(bytes) = peek.as_bytes() {
724 serialize_byte_array(bytes, writer, indent, depth)?;
725 } else if let PointerType::Function(_) = pointer_type {
726 writer.write(b"null");
727 } else {
728 let innermost = peek.innermost_peek();
729 if innermost.shape() != peek.shape() {
730 serialize_value(innermost, None, writer, indent, depth)?;
731 } else {
732 writer.write(b"null");
733 }
734 }
735 }
736 _ => {
737 trace!(
738 "Unhandled type: {:?}, falling back to null",
739 peek.shape().ty
740 );
741 writer.write(b"null");
742 }
743 }
744
745 Ok(())
746}
747
748fn serialize_dynamic_value<'mem, 'facet, W: crate::JsonWrite>(
750 dyn_val: facet_reflect::PeekDynamicValue<'mem, 'facet>,
751 writer: &mut W,
752 indent: Option<&str>,
753 depth: usize,
754) -> Result<(), SerializeError> {
755 match dyn_val.kind() {
756 DynValueKind::Null => {
757 writer.write(b"null");
758 }
759 DynValueKind::Bool => {
760 if let Some(b) = dyn_val.as_bool() {
761 writer.write(if b { b"true" } else { b"false" });
762 } else {
763 writer.write(b"null");
764 }
765 }
766 DynValueKind::Number => {
767 if let Some(n) = dyn_val.as_i64() {
769 writer.write(itoa::Buffer::new().format(n).as_bytes());
770 } else if let Some(n) = dyn_val.as_u64() {
771 writer.write(itoa::Buffer::new().format(n).as_bytes());
772 } else if let Some(n) = dyn_val.as_f64() {
773 let mut buf = ryu::Buffer::new();
774 writer.write(buf.format(n).as_bytes());
775 } else {
776 writer.write(b"null");
777 }
778 }
779 DynValueKind::String => {
780 if let Some(s) = dyn_val.as_str() {
781 crate::write_json_string(writer, s);
782 } else {
783 writer.write(b"null");
784 }
785 }
786 DynValueKind::Bytes => {
787 if let Some(bytes) = dyn_val.as_bytes() {
789 serialize_byte_array(bytes, writer, indent, depth)?;
790 } else {
791 writer.write(b"null");
792 }
793 }
794 DynValueKind::Array => {
795 let len = dyn_val.array_len().unwrap_or(0);
796 if len == 0 {
797 writer.write(b"[]");
798 } else {
799 writer.write(b"[");
800 for idx in 0..len {
801 if idx > 0 {
802 writer.write(b",");
803 }
804 write_newline(writer, indent);
805 write_indent(writer, indent, depth + 1);
806 if let Some(elem) = dyn_val.array_get(idx) {
807 serialize_value(elem, None, writer, indent, depth + 1)?;
808 } else {
809 writer.write(b"null");
810 }
811 }
812 write_newline(writer, indent);
813 write_indent(writer, indent, depth);
814 writer.write(b"]");
815 }
816 }
817 DynValueKind::Object => {
818 let len = dyn_val.object_len().unwrap_or(0);
819 if len == 0 {
820 writer.write(b"{}");
821 } else {
822 writer.write(b"{");
823 for idx in 0..len {
824 if idx > 0 {
825 writer.write(b",");
826 }
827 write_newline(writer, indent);
828 write_indent(writer, indent, depth + 1);
829 if let Some((key, val)) = dyn_val.object_get_entry(idx) {
830 crate::write_json_string(writer, key);
831 write_colon(writer, indent);
832 serialize_value(val, None, writer, indent, depth + 1)?;
833 }
834 }
835 write_newline(writer, indent);
836 write_indent(writer, indent, depth);
837 writer.write(b"}");
838 }
839 }
840 DynValueKind::DateTime => {
841 if let Some((year, month, day, hour, minute, second, nanos, kind)) =
843 dyn_val.as_datetime()
844 {
845 use facet_core::DynDateTimeKind;
846 let mut buf = String::new();
847 use core::fmt::Write;
848
849 match kind {
850 DynDateTimeKind::LocalDate => {
851 write!(buf, "{year:04}-{month:02}-{day:02}").unwrap();
852 }
853 DynDateTimeKind::LocalTime => {
854 if nanos > 0 {
855 write!(buf, "{hour:02}:{minute:02}:{second:02}.{nanos:09}").unwrap();
856 while buf.ends_with('0') {
858 buf.pop();
859 }
860 } else {
861 write!(buf, "{hour:02}:{minute:02}:{second:02}").unwrap();
862 }
863 }
864 DynDateTimeKind::LocalDateTime => {
865 if nanos > 0 {
866 write!(
867 buf,
868 "{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}.{nanos:09}"
869 )
870 .unwrap();
871 while buf.ends_with('0') {
872 buf.pop();
873 }
874 } else {
875 write!(
876 buf,
877 "{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}"
878 )
879 .unwrap();
880 }
881 }
882 DynDateTimeKind::Offset { offset_minutes } => {
883 if nanos > 0 {
884 write!(
885 buf,
886 "{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}.{nanos:09}"
887 )
888 .unwrap();
889 while buf.ends_with('0') {
890 buf.pop();
891 }
892 } else {
893 write!(
894 buf,
895 "{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}"
896 )
897 .unwrap();
898 }
899 if offset_minutes == 0 {
900 buf.push('Z');
901 } else {
902 let sign = if offset_minutes >= 0 { '+' } else { '-' };
903 let abs_offset = offset_minutes.abs();
904 let offset_hours = abs_offset / 60;
905 let offset_mins = abs_offset % 60;
906 write!(buf, "{sign}{offset_hours:02}:{offset_mins:02}").unwrap();
907 }
908 }
909 }
910 crate::write_json_string(writer, &buf);
911 } else {
912 writer.write(b"null");
913 }
914 }
915 DynValueKind::QName | DynValueKind::Uuid => {
916 writer.write(b"null");
919 }
920 }
921 Ok(())
922}
923
924fn serialize_map_key<W: crate::JsonWrite>(
926 peek: Peek<'_, '_>,
927 writer: &mut W,
928) -> Result<(), SerializeError> {
929 if let Some(s) = peek.as_str() {
931 crate::write_json_string(writer, s);
932 return Ok(());
933 }
934
935 let peek = peek.innermost_peek();
936 match peek.scalar_type() {
937 Some(ScalarType::U8) => {
939 let v = *peek.get::<u8>().unwrap();
940 writer.write(b"\"");
941 writer.write(itoa::Buffer::new().format(v).as_bytes());
942 writer.write(b"\"");
943 }
944 Some(ScalarType::U16) => {
945 let v = *peek.get::<u16>().unwrap();
946 writer.write(b"\"");
947 writer.write(itoa::Buffer::new().format(v).as_bytes());
948 writer.write(b"\"");
949 }
950 Some(ScalarType::U32) => {
951 let v = *peek.get::<u32>().unwrap();
952 writer.write(b"\"");
953 writer.write(itoa::Buffer::new().format(v).as_bytes());
954 writer.write(b"\"");
955 }
956 Some(ScalarType::U64) => {
957 let v = *peek.get::<u64>().unwrap();
958 writer.write(b"\"");
959 writer.write(itoa::Buffer::new().format(v).as_bytes());
960 writer.write(b"\"");
961 }
962 Some(ScalarType::U128) => {
963 let v = *peek.get::<u128>().unwrap();
964 writer.write(b"\"");
965 writer.write(itoa::Buffer::new().format(v).as_bytes());
966 writer.write(b"\"");
967 }
968 Some(ScalarType::USize) => {
969 let v = *peek.get::<usize>().unwrap();
970 writer.write(b"\"");
971 writer.write(itoa::Buffer::new().format(v).as_bytes());
972 writer.write(b"\"");
973 }
974 Some(ScalarType::I8) => {
975 let v = *peek.get::<i8>().unwrap();
976 writer.write(b"\"");
977 writer.write(itoa::Buffer::new().format(v).as_bytes());
978 writer.write(b"\"");
979 }
980 Some(ScalarType::I16) => {
981 let v = *peek.get::<i16>().unwrap();
982 writer.write(b"\"");
983 writer.write(itoa::Buffer::new().format(v).as_bytes());
984 writer.write(b"\"");
985 }
986 Some(ScalarType::I32) => {
987 let v = *peek.get::<i32>().unwrap();
988 writer.write(b"\"");
989 writer.write(itoa::Buffer::new().format(v).as_bytes());
990 writer.write(b"\"");
991 }
992 Some(ScalarType::I64) => {
993 let v = *peek.get::<i64>().unwrap();
994 writer.write(b"\"");
995 writer.write(itoa::Buffer::new().format(v).as_bytes());
996 writer.write(b"\"");
997 }
998 Some(ScalarType::I128) => {
999 let v = *peek.get::<i128>().unwrap();
1000 writer.write(b"\"");
1001 writer.write(itoa::Buffer::new().format(v).as_bytes());
1002 writer.write(b"\"");
1003 }
1004 Some(ScalarType::ISize) => {
1005 let v = *peek.get::<isize>().unwrap();
1006 writer.write(b"\"");
1007 writer.write(itoa::Buffer::new().format(v).as_bytes());
1008 writer.write(b"\"");
1009 }
1010 _ => {
1011 if peek.shape().vtable.has_display() {
1013 crate::write_json_string(writer, &alloc::format!("{peek}"));
1014 } else {
1015 panic!("Unsupported map key type: {}", peek.shape())
1016 }
1017 }
1018 }
1019 Ok(())
1020}
1021
1022fn serialize_scalar<W: crate::JsonWrite>(
1023 peek: Peek<'_, '_>,
1024 writer: &mut W,
1025) -> Result<(), SerializeError> {
1026 match peek.scalar_type() {
1027 Some(ScalarType::Unit) => writer.write(b"null"),
1028 Some(ScalarType::Bool) => {
1029 let v = *peek.get::<bool>().unwrap();
1030 writer.write(if v { b"true" } else { b"false" });
1031 }
1032 Some(ScalarType::Char) => {
1033 let c = *peek.get::<char>().unwrap();
1034 writer.write(b"\"");
1035 crate::write_json_escaped_char(writer, c);
1036 writer.write(b"\"");
1037 }
1038 Some(ScalarType::Str) => {
1039 crate::write_json_string(writer, peek.get::<str>().unwrap());
1040 }
1041 Some(ScalarType::String) => {
1042 crate::write_json_string(writer, peek.get::<String>().unwrap());
1043 }
1044 Some(ScalarType::CowStr) => {
1045 #[allow(unsafe_code)]
1047 let cow_str = unsafe { peek.data().get::<alloc::borrow::Cow<'static, str>>() };
1048 crate::write_json_string(writer, cow_str.as_ref());
1049 }
1050 Some(ScalarType::F32) => {
1051 let v = *peek.get::<f32>().unwrap();
1052 writer.write(ryu::Buffer::new().format(v).as_bytes());
1053 }
1054 Some(ScalarType::F64) => {
1055 let v = *peek.get::<f64>().unwrap();
1056 writer.write(ryu::Buffer::new().format(v).as_bytes());
1057 }
1058 Some(ScalarType::U8) => {
1059 let v = *peek.get::<u8>().unwrap();
1060 writer.write(itoa::Buffer::new().format(v).as_bytes());
1061 }
1062 Some(ScalarType::U16) => {
1063 let v = *peek.get::<u16>().unwrap();
1064 writer.write(itoa::Buffer::new().format(v).as_bytes());
1065 }
1066 Some(ScalarType::U32) => {
1067 let v = *peek.get::<u32>().unwrap();
1068 writer.write(itoa::Buffer::new().format(v).as_bytes());
1069 }
1070 Some(ScalarType::U64) => {
1071 let v = *peek.get::<u64>().unwrap();
1072 writer.write(itoa::Buffer::new().format(v).as_bytes());
1073 }
1074 Some(ScalarType::U128) => {
1075 let v = *peek.get::<u128>().unwrap();
1076 writer.write(itoa::Buffer::new().format(v).as_bytes());
1077 }
1078 Some(ScalarType::USize) => {
1079 let v = *peek.get::<usize>().unwrap();
1080 writer.write(itoa::Buffer::new().format(v).as_bytes());
1081 }
1082 Some(ScalarType::I8) => {
1083 let v = *peek.get::<i8>().unwrap();
1084 writer.write(itoa::Buffer::new().format(v).as_bytes());
1085 }
1086 Some(ScalarType::I16) => {
1087 let v = *peek.get::<i16>().unwrap();
1088 writer.write(itoa::Buffer::new().format(v).as_bytes());
1089 }
1090 Some(ScalarType::I32) => {
1091 let v = *peek.get::<i32>().unwrap();
1092 writer.write(itoa::Buffer::new().format(v).as_bytes());
1093 }
1094 Some(ScalarType::I64) => {
1095 let v = *peek.get::<i64>().unwrap();
1096 writer.write(itoa::Buffer::new().format(v).as_bytes());
1097 }
1098 Some(ScalarType::I128) => {
1099 let v = *peek.get::<i128>().unwrap();
1100 writer.write(itoa::Buffer::new().format(v).as_bytes());
1101 }
1102 Some(ScalarType::ISize) => {
1103 let v = *peek.get::<isize>().unwrap();
1104 writer.write(itoa::Buffer::new().format(v).as_bytes());
1105 }
1106 Some(unsupported) => {
1107 panic!("Unsupported scalar type: {unsupported:?}")
1108 }
1109 None => {
1110 if peek.shape().vtable.has_display() {
1112 crate::write_json_string(writer, &alloc::format!("{peek}"));
1113 } else {
1114 panic!("Unsupported shape (no display): {}", peek.shape())
1115 }
1116 }
1117 }
1118 Ok(())
1119}
1120
1121fn serialize_array<'mem, 'facet, W: crate::JsonWrite>(
1122 iter: facet_reflect::PeekListLikeIter<'mem, 'facet>,
1123 writer: &mut W,
1124 indent: Option<&str>,
1125 depth: usize,
1126) -> Result<(), SerializeError> {
1127 writer.write(b"[");
1128 let mut first = true;
1129 for item in iter {
1130 if !first {
1131 writer.write(b",");
1132 }
1133 first = false;
1134 write_newline(writer, indent);
1135 write_indent(writer, indent, depth + 1);
1136 serialize_value(item, None, writer, indent, depth + 1)?;
1137 }
1138 if !first {
1139 write_newline(writer, indent);
1140 write_indent(writer, indent, depth);
1141 }
1142 writer.write(b"]");
1143 Ok(())
1144}
1145
1146fn serialize_byte_array<W: crate::JsonWrite>(
1147 bytes: &[u8],
1148 writer: &mut W,
1149 indent: Option<&str>,
1150 depth: usize,
1151) -> Result<(), SerializeError> {
1152 writer.write(b"[");
1153 let mut first = true;
1154 for &byte in bytes {
1155 if !first {
1156 writer.write(b",");
1157 }
1158 first = false;
1159 write_newline(writer, indent);
1160 write_indent(writer, indent, depth + 1);
1161 writer.write(itoa::Buffer::new().format(byte).as_bytes());
1162 }
1163 if !first {
1164 write_newline(writer, indent);
1165 write_indent(writer, indent, depth);
1166 }
1167 writer.write(b"]");
1168 Ok(())
1169}
1170
1171fn serialize_enum_content<'mem, 'facet, W: crate::JsonWrite>(
1173 peek_enum: &facet_reflect::PeekEnum<'mem, 'facet>,
1174 variant: &facet_core::Variant,
1175 writer: &mut W,
1176 indent: Option<&str>,
1177 depth: usize,
1178) -> Result<(), SerializeError> {
1179 if variant.data.fields.is_empty() {
1180 crate::write_json_string(writer, variant.name);
1183 } else if variant_is_newtype_like(variant) {
1184 let fields: Vec<_> = peek_enum.fields_for_serialize().collect();
1186 let (field_item, field_peek) = fields[0];
1187 serialize_value(field_peek, Some(field_item), writer, indent, depth)?;
1188 } else if variant.data.kind == StructKind::Tuple || variant.data.kind == StructKind::TupleStruct
1189 {
1190 writer.write(b"[");
1192 let mut first = true;
1193 for (field_item, field_peek) in peek_enum.fields_for_serialize() {
1194 if !first {
1195 writer.write(b",");
1196 }
1197 first = false;
1198 write_newline(writer, indent);
1199 write_indent(writer, indent, depth + 1);
1200 serialize_value(field_peek, Some(field_item), writer, indent, depth + 1)?;
1201 }
1202 if !first {
1203 write_newline(writer, indent);
1204 write_indent(writer, indent, depth);
1205 }
1206 writer.write(b"]");
1207 } else {
1208 writer.write(b"{");
1210 let mut first = true;
1211 for (field_item, field_peek) in peek_enum.fields_for_serialize() {
1212 if !first {
1213 writer.write(b",");
1214 }
1215 first = false;
1216 write_newline(writer, indent);
1217 write_indent(writer, indent, depth + 1);
1218 crate::write_json_string(writer, field_item.name);
1219 write_colon(writer, indent);
1220 serialize_value(field_peek, Some(field_item), writer, indent, depth + 1)?;
1221 }
1222 if !first {
1223 write_newline(writer, indent);
1224 write_indent(writer, indent, depth);
1225 }
1226 writer.write(b"}");
1227 }
1228 Ok(())
1229}