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 variant.data.kind == StructKind::Tuple && variant.data.fields.len() == 1
356}
357
358fn write_indent<W: crate::JsonWrite>(writer: &mut W, indent: Option<&str>, depth: usize) {
360 if let Some(indent_str) = indent {
361 for _ in 0..depth {
362 writer.write(indent_str.as_bytes());
363 }
364 }
365}
366
367fn write_newline<W: crate::JsonWrite>(writer: &mut W, indent: Option<&str>) {
369 if indent.is_some() {
370 writer.write(b"\n");
371 }
372}
373
374fn write_colon<W: crate::JsonWrite>(writer: &mut W, indent: Option<&str>) {
376 if indent.is_some() {
377 writer.write(b": ");
378 } else {
379 writer.write(b":");
380 }
381}
382
383fn serialize_value<'mem, 'facet, W: crate::JsonWrite>(
384 peek: Peek<'mem, 'facet>,
385 maybe_field_item: Option<FieldItem>,
386 writer: &mut W,
387 indent: Option<&str>,
388 depth: usize,
389) -> Result<(), SerializeError> {
390 trace!("Serializing a value, shape is {}", peek.shape());
391
392 #[cfg(feature = "alloc")]
394 if let Some(fi) = maybe_field_item
395 && fi.field.proxy_convert_out_fn().is_some()
396 {
397 let owned_peek = peek.custom_serialization(fi.field).unwrap();
398 let old_shape = peek.shape();
399 let new_shape = owned_peek.shape();
400 trace!("{old_shape} has custom serialization, serializing as {new_shape} instead");
401 return serialize_value(owned_peek.as_peek(), None, writer, indent, depth);
402 }
403
404 #[cfg(feature = "alloc")]
406 if let Ok(Some(owned_peek)) = peek.custom_serialization_from_shape() {
407 let old_shape = peek.shape();
408 let new_shape = owned_peek.shape();
409 trace!("{old_shape} has container-level proxy, serializing as {new_shape} instead");
410 return serialize_value(owned_peek.as_peek(), None, writer, indent, depth);
411 }
412
413 if peek.shape().is_transparent() {
415 let old_shape = peek.shape();
416 let ps = peek.into_struct().unwrap();
417 let (field, inner_peek) = ps.fields().next().unwrap();
418 let new_shape = inner_peek.shape();
419 trace!("{old_shape} is transparent, let's serialize the inner {new_shape} instead");
420 return serialize_value(
421 inner_peek,
422 Some(FieldItem::new(field)),
423 writer,
424 indent,
425 depth,
426 );
427 }
428
429 if peek.shape() == RawJson::SHAPE {
431 #[allow(unsafe_code)]
433 let raw = unsafe { peek.data().get::<RawJson<'static>>() };
434 writer.write(raw.as_str().as_bytes());
435 return Ok(());
436 }
437
438 trace!(
439 "Matching def={:?}, ty={:?} for shape={}",
440 peek.shape().def,
441 peek.shape().ty,
442 peek.shape()
443 );
444
445 match (peek.shape().def, peek.shape().ty) {
446 (Def::Scalar, _) => {
447 let peek = peek.innermost_peek();
448 serialize_scalar(peek, writer)?;
449 }
450 (Def::List(ld), _) => {
451 if ld.t().is_type::<u8>() && peek.shape().is_type::<Vec<u8>>() {
452 let bytes = peek.get::<Vec<u8>>().unwrap();
454 serialize_byte_array(bytes, writer, indent, depth)?;
455 } else {
456 let peek_list = peek.into_list_like().unwrap();
457 serialize_array(peek_list.iter(), writer, indent, depth)?;
458 }
459 }
460 (Def::Array(ad), _) => {
461 if ad.t().is_type::<u8>() {
462 let bytes: Vec<u8> = peek
463 .into_list_like()
464 .unwrap()
465 .iter()
466 .map(|p| *p.get::<u8>().unwrap())
467 .collect();
468 serialize_byte_array(&bytes, writer, indent, depth)?;
469 } else {
470 let peek_list = peek.into_list_like().unwrap();
471 serialize_array(peek_list.iter(), writer, indent, depth)?;
472 }
473 }
474 (Def::Slice(sd), _) => {
475 if sd.t().is_type::<u8>() {
476 let bytes = peek.get::<[u8]>().unwrap();
477 serialize_byte_array(bytes, writer, indent, depth)?;
478 } else {
479 let peek_list = peek.into_list_like().unwrap();
480 serialize_array(peek_list.iter(), writer, indent, depth)?;
481 }
482 }
483 (Def::Map(_), _) => {
484 let peek_map = peek.into_map().unwrap();
485 writer.write(b"{");
486 let mut first = true;
487 for (key, value) in peek_map.iter() {
488 if !first {
489 writer.write(b",");
490 }
491 first = false;
492 write_newline(writer, indent);
493 write_indent(writer, indent, depth + 1);
494 serialize_map_key(key, writer)?;
495 write_colon(writer, indent);
496 serialize_value(value, None, writer, indent, depth + 1)?;
497 }
498 if !first {
499 write_newline(writer, indent);
500 write_indent(writer, indent, depth);
501 }
502 writer.write(b"}");
503 }
504 (Def::Set(_), _) => {
505 let peek_set = peek.into_set().unwrap();
506 writer.write(b"[");
507 let mut first = true;
508 for item in peek_set.iter() {
509 if !first {
510 writer.write(b",");
511 }
512 first = false;
513 write_newline(writer, indent);
514 write_indent(writer, indent, depth + 1);
515 serialize_value(item, None, writer, indent, depth + 1)?;
516 }
517 if !first {
518 write_newline(writer, indent);
519 write_indent(writer, indent, depth);
520 }
521 writer.write(b"]");
522 }
523 (Def::Option(_), _) => {
524 let opt = peek.into_option().unwrap();
525 if let Some(inner_peek) = opt.value() {
526 serialize_value(inner_peek, None, writer, indent, depth)?;
527 } else {
528 writer.write(b"null");
529 }
530 }
531 (Def::Pointer(_), _) => {
532 let sp = peek.into_pointer().unwrap();
533 if let Some(inner_peek) = sp.borrow_inner() {
534 serialize_value(inner_peek, None, writer, indent, depth)?;
535 } else {
536 panic!(
537 "Smart pointer without borrow support or with opaque pointee cannot be serialized"
538 );
539 }
540 }
541 (_, Type::User(UserType::Struct(sd))) => {
542 trace!("Serializing struct: shape={}", peek.shape());
543 trace!(
544 " Struct details: kind={:?}, field_count={}",
545 sd.kind,
546 sd.fields.len()
547 );
548
549 match sd.kind {
550 StructKind::Unit => {
551 writer.write(b"null");
552 }
553 StructKind::Tuple => {
554 let peek_struct = peek.into_struct().unwrap();
555 writer.write(b"[");
556 let mut first = true;
557 for (field, value) in peek_struct.fields() {
558 if !first {
559 writer.write(b",");
560 }
561 first = false;
562 write_newline(writer, indent);
563 write_indent(writer, indent, depth + 1);
564 serialize_value(
565 value,
566 Some(FieldItem::new(field)),
567 writer,
568 indent,
569 depth + 1,
570 )?;
571 }
572 if !first {
573 write_newline(writer, indent);
574 write_indent(writer, indent, depth);
575 }
576 writer.write(b"]");
577 }
578 StructKind::TupleStruct => {
579 let peek_struct = peek.into_struct().unwrap();
580 writer.write(b"[");
581 let mut first = true;
582 for (field_item, value) in peek_struct.fields_for_serialize() {
583 if !first {
584 writer.write(b",");
585 }
586 first = false;
587 write_newline(writer, indent);
588 write_indent(writer, indent, depth + 1);
589 serialize_value(value, Some(field_item), writer, indent, depth + 1)?;
590 }
591 if !first {
592 write_newline(writer, indent);
593 write_indent(writer, indent, depth);
594 }
595 writer.write(b"]");
596 }
597 StructKind::Struct => {
598 let peek_struct = peek.into_struct().unwrap();
599 writer.write(b"{");
600 let mut first = true;
601 for (field_item, value) in peek_struct.fields_for_serialize() {
602 if !first {
603 writer.write(b",");
604 }
605 first = false;
606 write_newline(writer, indent);
607 write_indent(writer, indent, depth + 1);
608 crate::write_json_string(writer, field_item.name);
609 write_colon(writer, indent);
610 serialize_value(value, Some(field_item), writer, indent, depth + 1)?;
611 }
612 if !first {
613 write_newline(writer, indent);
614 write_indent(writer, indent, depth);
615 }
616 writer.write(b"}");
617 }
618 }
619 }
620 (_, Type::User(UserType::Enum(_))) => {
621 let shape = peek.shape();
622 let peek_enum = peek.into_enum().unwrap();
623 let variant = peek_enum
624 .active_variant()
625 .expect("Failed to get active variant");
626 let variant_index = peek_enum
627 .variant_index()
628 .expect("Failed to get variant index");
629 trace!("Active variant index is {variant_index}, variant is {variant:?}");
630
631 let is_untagged = shape.is_untagged();
633 let tag_field = shape.get_tag_attr();
634 let content_field = shape.get_content_attr();
635
636 if is_untagged {
637 serialize_enum_content(&peek_enum, variant, writer, indent, depth)?;
639 } else if let Some(tag) = tag_field {
640 if let Some(content) = content_field {
641 writer.write(b"{");
643 write_newline(writer, indent);
644 write_indent(writer, indent, depth + 1);
645 crate::write_json_string(writer, tag);
646 write_colon(writer, indent);
647 crate::write_json_string(writer, variant.name);
648
649 if !variant.data.fields.is_empty() {
651 writer.write(b",");
652 write_newline(writer, indent);
653 write_indent(writer, indent, depth + 1);
654 crate::write_json_string(writer, content);
655 write_colon(writer, indent);
656 serialize_enum_content(&peek_enum, variant, writer, indent, depth + 1)?;
657 }
658
659 write_newline(writer, indent);
660 write_indent(writer, indent, depth);
661 writer.write(b"}");
662 } else {
663 writer.write(b"{");
665 write_newline(writer, indent);
666 write_indent(writer, indent, depth + 1);
667 crate::write_json_string(writer, tag);
668 write_colon(writer, indent);
669 crate::write_json_string(writer, variant.name);
670
671 for (field_item, field_peek) in peek_enum.fields_for_serialize() {
673 writer.write(b",");
674 write_newline(writer, indent);
675 write_indent(writer, indent, depth + 1);
676 crate::write_json_string(writer, field_item.name);
677 write_colon(writer, indent);
678 serialize_value(field_peek, Some(field_item), writer, indent, depth + 1)?;
679 }
680
681 write_newline(writer, indent);
682 write_indent(writer, indent, depth);
683 writer.write(b"}");
684 }
685 } else {
686 let flattened = maybe_field_item.map(|fi| fi.flattened).unwrap_or_default();
688
689 if variant.data.fields.is_empty() {
690 crate::write_json_string(writer, variant.name);
692 } else {
693 if !flattened {
694 writer.write(b"{");
696 write_newline(writer, indent);
697 write_indent(writer, indent, depth + 1);
698 crate::write_json_string(writer, variant.name);
699 write_colon(writer, indent);
700 }
701
702 let inner_depth = if flattened { depth } else { depth + 1 };
703 serialize_enum_content(&peek_enum, variant, writer, indent, inner_depth)?;
704
705 if !flattened {
706 write_newline(writer, indent);
707 write_indent(writer, indent, depth);
708 writer.write(b"}");
709 }
710 }
711 }
712 }
713 (Def::DynamicValue(_), _) => {
714 let dyn_val = peek.into_dynamic_value().unwrap();
715 serialize_dynamic_value(dyn_val, writer, indent, depth)?;
716 }
717 (_, Type::Pointer(pointer_type)) => {
718 if let Some(str_value) = peek.as_str() {
719 crate::write_json_string(writer, str_value);
720 } else if let Some(bytes) = peek.as_bytes() {
721 serialize_byte_array(bytes, writer, indent, depth)?;
722 } else if let PointerType::Function(_) = pointer_type {
723 writer.write(b"null");
724 } else {
725 let innermost = peek.innermost_peek();
726 if innermost.shape() != peek.shape() {
727 serialize_value(innermost, None, writer, indent, depth)?;
728 } else {
729 writer.write(b"null");
730 }
731 }
732 }
733 _ => {
734 trace!(
735 "Unhandled type: {:?}, falling back to null",
736 peek.shape().ty
737 );
738 writer.write(b"null");
739 }
740 }
741
742 Ok(())
743}
744
745fn serialize_dynamic_value<'mem, 'facet, W: crate::JsonWrite>(
747 dyn_val: facet_reflect::PeekDynamicValue<'mem, 'facet>,
748 writer: &mut W,
749 indent: Option<&str>,
750 depth: usize,
751) -> Result<(), SerializeError> {
752 match dyn_val.kind() {
753 DynValueKind::Null => {
754 writer.write(b"null");
755 }
756 DynValueKind::Bool => {
757 if let Some(b) = dyn_val.as_bool() {
758 writer.write(if b { b"true" } else { b"false" });
759 } else {
760 writer.write(b"null");
761 }
762 }
763 DynValueKind::Number => {
764 if let Some(n) = dyn_val.as_i64() {
766 writer.write(itoa::Buffer::new().format(n).as_bytes());
767 } else if let Some(n) = dyn_val.as_u64() {
768 writer.write(itoa::Buffer::new().format(n).as_bytes());
769 } else if let Some(n) = dyn_val.as_f64() {
770 let mut buf = ryu::Buffer::new();
771 writer.write(buf.format(n).as_bytes());
772 } else {
773 writer.write(b"null");
774 }
775 }
776 DynValueKind::String => {
777 if let Some(s) = dyn_val.as_str() {
778 crate::write_json_string(writer, s);
779 } else {
780 writer.write(b"null");
781 }
782 }
783 DynValueKind::Bytes => {
784 if let Some(bytes) = dyn_val.as_bytes() {
786 serialize_byte_array(bytes, writer, indent, depth)?;
787 } else {
788 writer.write(b"null");
789 }
790 }
791 DynValueKind::Array => {
792 let len = dyn_val.array_len().unwrap_or(0);
793 if len == 0 {
794 writer.write(b"[]");
795 } else {
796 writer.write(b"[");
797 for idx in 0..len {
798 if idx > 0 {
799 writer.write(b",");
800 }
801 write_newline(writer, indent);
802 write_indent(writer, indent, depth + 1);
803 if let Some(elem) = dyn_val.array_get(idx) {
804 serialize_value(elem, None, writer, indent, depth + 1)?;
805 } else {
806 writer.write(b"null");
807 }
808 }
809 write_newline(writer, indent);
810 write_indent(writer, indent, depth);
811 writer.write(b"]");
812 }
813 }
814 DynValueKind::Object => {
815 let len = dyn_val.object_len().unwrap_or(0);
816 if len == 0 {
817 writer.write(b"{}");
818 } else {
819 writer.write(b"{");
820 for idx in 0..len {
821 if idx > 0 {
822 writer.write(b",");
823 }
824 write_newline(writer, indent);
825 write_indent(writer, indent, depth + 1);
826 if let Some((key, val)) = dyn_val.object_get_entry(idx) {
827 crate::write_json_string(writer, key);
828 write_colon(writer, indent);
829 serialize_value(val, None, writer, indent, depth + 1)?;
830 }
831 }
832 write_newline(writer, indent);
833 write_indent(writer, indent, depth);
834 writer.write(b"}");
835 }
836 }
837 DynValueKind::DateTime => {
838 if let Some((year, month, day, hour, minute, second, nanos, kind)) =
840 dyn_val.as_datetime()
841 {
842 use facet_core::DynDateTimeKind;
843 let mut buf = String::new();
844 use core::fmt::Write;
845
846 match kind {
847 DynDateTimeKind::LocalDate => {
848 write!(buf, "{year:04}-{month:02}-{day:02}").unwrap();
849 }
850 DynDateTimeKind::LocalTime => {
851 if nanos > 0 {
852 write!(buf, "{hour:02}:{minute:02}:{second:02}.{nanos:09}").unwrap();
853 while buf.ends_with('0') {
855 buf.pop();
856 }
857 } else {
858 write!(buf, "{hour:02}:{minute:02}:{second:02}").unwrap();
859 }
860 }
861 DynDateTimeKind::LocalDateTime => {
862 if nanos > 0 {
863 write!(
864 buf,
865 "{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}.{nanos:09}"
866 )
867 .unwrap();
868 while buf.ends_with('0') {
869 buf.pop();
870 }
871 } else {
872 write!(
873 buf,
874 "{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}"
875 )
876 .unwrap();
877 }
878 }
879 DynDateTimeKind::Offset { offset_minutes } => {
880 if nanos > 0 {
881 write!(
882 buf,
883 "{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}.{nanos:09}"
884 )
885 .unwrap();
886 while buf.ends_with('0') {
887 buf.pop();
888 }
889 } else {
890 write!(
891 buf,
892 "{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}"
893 )
894 .unwrap();
895 }
896 if offset_minutes == 0 {
897 buf.push('Z');
898 } else {
899 let sign = if offset_minutes >= 0 { '+' } else { '-' };
900 let abs_offset = offset_minutes.abs();
901 let offset_hours = abs_offset / 60;
902 let offset_mins = abs_offset % 60;
903 write!(buf, "{sign}{offset_hours:02}:{offset_mins:02}").unwrap();
904 }
905 }
906 }
907 crate::write_json_string(writer, &buf);
908 } else {
909 writer.write(b"null");
910 }
911 }
912 DynValueKind::QName | DynValueKind::Uuid => {
913 writer.write(b"null");
916 }
917 }
918 Ok(())
919}
920
921fn serialize_map_key<W: crate::JsonWrite>(
923 peek: Peek<'_, '_>,
924 writer: &mut W,
925) -> Result<(), SerializeError> {
926 if let Some(s) = peek.as_str() {
928 crate::write_json_string(writer, s);
929 return Ok(());
930 }
931
932 let peek = peek.innermost_peek();
933 match peek.scalar_type() {
934 Some(ScalarType::U8) => {
936 let v = *peek.get::<u8>().unwrap();
937 writer.write(b"\"");
938 writer.write(itoa::Buffer::new().format(v).as_bytes());
939 writer.write(b"\"");
940 }
941 Some(ScalarType::U16) => {
942 let v = *peek.get::<u16>().unwrap();
943 writer.write(b"\"");
944 writer.write(itoa::Buffer::new().format(v).as_bytes());
945 writer.write(b"\"");
946 }
947 Some(ScalarType::U32) => {
948 let v = *peek.get::<u32>().unwrap();
949 writer.write(b"\"");
950 writer.write(itoa::Buffer::new().format(v).as_bytes());
951 writer.write(b"\"");
952 }
953 Some(ScalarType::U64) => {
954 let v = *peek.get::<u64>().unwrap();
955 writer.write(b"\"");
956 writer.write(itoa::Buffer::new().format(v).as_bytes());
957 writer.write(b"\"");
958 }
959 Some(ScalarType::U128) => {
960 let v = *peek.get::<u128>().unwrap();
961 writer.write(b"\"");
962 writer.write(itoa::Buffer::new().format(v).as_bytes());
963 writer.write(b"\"");
964 }
965 Some(ScalarType::USize) => {
966 let v = *peek.get::<usize>().unwrap();
967 writer.write(b"\"");
968 writer.write(itoa::Buffer::new().format(v).as_bytes());
969 writer.write(b"\"");
970 }
971 Some(ScalarType::I8) => {
972 let v = *peek.get::<i8>().unwrap();
973 writer.write(b"\"");
974 writer.write(itoa::Buffer::new().format(v).as_bytes());
975 writer.write(b"\"");
976 }
977 Some(ScalarType::I16) => {
978 let v = *peek.get::<i16>().unwrap();
979 writer.write(b"\"");
980 writer.write(itoa::Buffer::new().format(v).as_bytes());
981 writer.write(b"\"");
982 }
983 Some(ScalarType::I32) => {
984 let v = *peek.get::<i32>().unwrap();
985 writer.write(b"\"");
986 writer.write(itoa::Buffer::new().format(v).as_bytes());
987 writer.write(b"\"");
988 }
989 Some(ScalarType::I64) => {
990 let v = *peek.get::<i64>().unwrap();
991 writer.write(b"\"");
992 writer.write(itoa::Buffer::new().format(v).as_bytes());
993 writer.write(b"\"");
994 }
995 Some(ScalarType::I128) => {
996 let v = *peek.get::<i128>().unwrap();
997 writer.write(b"\"");
998 writer.write(itoa::Buffer::new().format(v).as_bytes());
999 writer.write(b"\"");
1000 }
1001 Some(ScalarType::ISize) => {
1002 let v = *peek.get::<isize>().unwrap();
1003 writer.write(b"\"");
1004 writer.write(itoa::Buffer::new().format(v).as_bytes());
1005 writer.write(b"\"");
1006 }
1007 _ => {
1008 if peek.shape().vtable.has_display() {
1010 crate::write_json_string(writer, &alloc::format!("{peek}"));
1011 } else {
1012 panic!("Unsupported map key type: {}", peek.shape())
1013 }
1014 }
1015 }
1016 Ok(())
1017}
1018
1019fn serialize_scalar<W: crate::JsonWrite>(
1020 peek: Peek<'_, '_>,
1021 writer: &mut W,
1022) -> Result<(), SerializeError> {
1023 match peek.scalar_type() {
1024 Some(ScalarType::Unit) => writer.write(b"null"),
1025 Some(ScalarType::Bool) => {
1026 let v = *peek.get::<bool>().unwrap();
1027 writer.write(if v { b"true" } else { b"false" });
1028 }
1029 Some(ScalarType::Char) => {
1030 let c = *peek.get::<char>().unwrap();
1031 writer.write(b"\"");
1032 crate::write_json_escaped_char(writer, c);
1033 writer.write(b"\"");
1034 }
1035 Some(ScalarType::Str) => {
1036 crate::write_json_string(writer, peek.get::<str>().unwrap());
1037 }
1038 Some(ScalarType::String) => {
1039 crate::write_json_string(writer, peek.get::<String>().unwrap());
1040 }
1041 Some(ScalarType::CowStr) => {
1042 #[allow(unsafe_code)]
1044 let cow_str = unsafe { peek.data().get::<alloc::borrow::Cow<'static, str>>() };
1045 crate::write_json_string(writer, cow_str.as_ref());
1046 }
1047 Some(ScalarType::F32) => {
1048 let v = *peek.get::<f32>().unwrap();
1049 writer.write(ryu::Buffer::new().format(v).as_bytes());
1050 }
1051 Some(ScalarType::F64) => {
1052 let v = *peek.get::<f64>().unwrap();
1053 writer.write(ryu::Buffer::new().format(v).as_bytes());
1054 }
1055 Some(ScalarType::U8) => {
1056 let v = *peek.get::<u8>().unwrap();
1057 writer.write(itoa::Buffer::new().format(v).as_bytes());
1058 }
1059 Some(ScalarType::U16) => {
1060 let v = *peek.get::<u16>().unwrap();
1061 writer.write(itoa::Buffer::new().format(v).as_bytes());
1062 }
1063 Some(ScalarType::U32) => {
1064 let v = *peek.get::<u32>().unwrap();
1065 writer.write(itoa::Buffer::new().format(v).as_bytes());
1066 }
1067 Some(ScalarType::U64) => {
1068 let v = *peek.get::<u64>().unwrap();
1069 writer.write(itoa::Buffer::new().format(v).as_bytes());
1070 }
1071 Some(ScalarType::U128) => {
1072 let v = *peek.get::<u128>().unwrap();
1073 writer.write(itoa::Buffer::new().format(v).as_bytes());
1074 }
1075 Some(ScalarType::USize) => {
1076 let v = *peek.get::<usize>().unwrap();
1077 writer.write(itoa::Buffer::new().format(v).as_bytes());
1078 }
1079 Some(ScalarType::I8) => {
1080 let v = *peek.get::<i8>().unwrap();
1081 writer.write(itoa::Buffer::new().format(v).as_bytes());
1082 }
1083 Some(ScalarType::I16) => {
1084 let v = *peek.get::<i16>().unwrap();
1085 writer.write(itoa::Buffer::new().format(v).as_bytes());
1086 }
1087 Some(ScalarType::I32) => {
1088 let v = *peek.get::<i32>().unwrap();
1089 writer.write(itoa::Buffer::new().format(v).as_bytes());
1090 }
1091 Some(ScalarType::I64) => {
1092 let v = *peek.get::<i64>().unwrap();
1093 writer.write(itoa::Buffer::new().format(v).as_bytes());
1094 }
1095 Some(ScalarType::I128) => {
1096 let v = *peek.get::<i128>().unwrap();
1097 writer.write(itoa::Buffer::new().format(v).as_bytes());
1098 }
1099 Some(ScalarType::ISize) => {
1100 let v = *peek.get::<isize>().unwrap();
1101 writer.write(itoa::Buffer::new().format(v).as_bytes());
1102 }
1103 Some(unsupported) => {
1104 panic!("Unsupported scalar type: {unsupported:?}")
1105 }
1106 None => {
1107 if peek.shape().vtable.has_display() {
1109 crate::write_json_string(writer, &alloc::format!("{peek}"));
1110 } else {
1111 panic!("Unsupported shape (no display): {}", peek.shape())
1112 }
1113 }
1114 }
1115 Ok(())
1116}
1117
1118fn serialize_array<'mem, 'facet, W: crate::JsonWrite>(
1119 iter: facet_reflect::PeekListLikeIter<'mem, 'facet>,
1120 writer: &mut W,
1121 indent: Option<&str>,
1122 depth: usize,
1123) -> Result<(), SerializeError> {
1124 writer.write(b"[");
1125 let mut first = true;
1126 for item in iter {
1127 if !first {
1128 writer.write(b",");
1129 }
1130 first = false;
1131 write_newline(writer, indent);
1132 write_indent(writer, indent, depth + 1);
1133 serialize_value(item, None, writer, indent, depth + 1)?;
1134 }
1135 if !first {
1136 write_newline(writer, indent);
1137 write_indent(writer, indent, depth);
1138 }
1139 writer.write(b"]");
1140 Ok(())
1141}
1142
1143fn serialize_byte_array<W: crate::JsonWrite>(
1144 bytes: &[u8],
1145 writer: &mut W,
1146 indent: Option<&str>,
1147 depth: usize,
1148) -> Result<(), SerializeError> {
1149 writer.write(b"[");
1150 let mut first = true;
1151 for &byte in bytes {
1152 if !first {
1153 writer.write(b",");
1154 }
1155 first = false;
1156 write_newline(writer, indent);
1157 write_indent(writer, indent, depth + 1);
1158 writer.write(itoa::Buffer::new().format(byte).as_bytes());
1159 }
1160 if !first {
1161 write_newline(writer, indent);
1162 write_indent(writer, indent, depth);
1163 }
1164 writer.write(b"]");
1165 Ok(())
1166}
1167
1168fn serialize_enum_content<'mem, 'facet, W: crate::JsonWrite>(
1170 peek_enum: &facet_reflect::PeekEnum<'mem, 'facet>,
1171 variant: &facet_core::Variant,
1172 writer: &mut W,
1173 indent: Option<&str>,
1174 depth: usize,
1175) -> Result<(), SerializeError> {
1176 if variant.data.fields.is_empty() {
1177 crate::write_json_string(writer, variant.name);
1180 } else if variant_is_newtype_like(variant) {
1181 let fields: Vec<_> = peek_enum.fields_for_serialize().collect();
1183 let (field_item, field_peek) = fields[0];
1184 serialize_value(field_peek, Some(field_item), writer, indent, depth)?;
1185 } else if variant.data.kind == StructKind::Tuple || variant.data.kind == StructKind::TupleStruct
1186 {
1187 writer.write(b"[");
1189 let mut first = true;
1190 for (field_item, field_peek) in peek_enum.fields_for_serialize() {
1191 if !first {
1192 writer.write(b",");
1193 }
1194 first = false;
1195 write_newline(writer, indent);
1196 write_indent(writer, indent, depth + 1);
1197 serialize_value(field_peek, Some(field_item), writer, indent, depth + 1)?;
1198 }
1199 if !first {
1200 write_newline(writer, indent);
1201 write_indent(writer, indent, depth);
1202 }
1203 writer.write(b"]");
1204 } else {
1205 writer.write(b"{");
1207 let mut first = true;
1208 for (field_item, field_peek) in peek_enum.fields_for_serialize() {
1209 if !first {
1210 writer.write(b",");
1211 }
1212 first = false;
1213 write_newline(writer, indent);
1214 write_indent(writer, indent, depth + 1);
1215 crate::write_json_string(writer, field_item.name);
1216 write_colon(writer, indent);
1217 serialize_value(field_peek, Some(field_item), writer, indent, depth + 1)?;
1218 }
1219 if !first {
1220 write_newline(writer, indent);
1221 write_indent(writer, indent, depth);
1222 }
1223 writer.write(b"}");
1224 }
1225 Ok(())
1226}