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