1extern crate alloc;
2
3use alloc::borrow::Cow;
4use alloc::string::String;
5use core::fmt::Debug;
6use core::fmt::Write as _;
7
8use facet_core::{Def, DynDateTimeKind, DynValueKind, ScalarType, StructKind};
9use facet_reflect::{HasFields as _, Peek, ReflectError};
10
11use crate::ScalarValue;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
15pub enum FieldOrdering {
16 #[default]
18 Declaration,
19 AttributesFirst,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
25pub enum StructFieldMode {
26 #[default]
28 Named,
29 Unnamed,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
35pub enum MapEncoding {
36 #[default]
38 Struct,
39 Pairs,
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
45pub enum EnumVariantEncoding {
46 #[default]
48 Tagged,
49 Index,
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
55pub enum DynamicValueEncoding {
56 #[default]
58 SelfDescribing,
59 Tagged,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub enum DynamicValueTag {
66 Null,
68 Bool,
70 I64,
72 U64,
74 F64,
76 String,
78 Bytes,
80 Array,
82 Object,
84 DateTime,
86}
87
88pub trait FormatSerializer {
93 type Error: Debug;
95
96 fn begin_struct(&mut self) -> Result<(), Self::Error>;
98 fn field_key(&mut self, key: &str) -> Result<(), Self::Error>;
100 fn end_struct(&mut self) -> Result<(), Self::Error>;
102
103 fn begin_seq(&mut self) -> Result<(), Self::Error>;
105 fn end_seq(&mut self) -> Result<(), Self::Error>;
107
108 fn scalar(&mut self, scalar: ScalarValue<'_>) -> Result<(), Self::Error>;
110
111 fn field_metadata(&mut self, _field: &facet_reflect::FieldItem) -> Result<(), Self::Error> {
115 Ok(())
116 }
117
118 fn struct_metadata(&mut self, _shape: &facet_core::Shape) -> Result<(), Self::Error> {
122 Ok(())
123 }
124
125 fn variant_metadata(
130 &mut self,
131 _variant: &'static facet_core::Variant,
132 ) -> Result<(), Self::Error> {
133 Ok(())
134 }
135
136 fn preferred_field_order(&self) -> FieldOrdering {
140 FieldOrdering::Declaration
141 }
142
143 fn struct_field_mode(&self) -> StructFieldMode {
145 StructFieldMode::Named
146 }
147
148 fn map_encoding(&self) -> MapEncoding {
150 MapEncoding::Struct
151 }
152
153 fn enum_variant_encoding(&self) -> EnumVariantEncoding {
155 EnumVariantEncoding::Tagged
156 }
157
158 fn dynamic_value_encoding(&self) -> DynamicValueEncoding {
160 DynamicValueEncoding::SelfDescribing
161 }
162
163 fn raw_serialize_shape(&self) -> Option<&'static facet_core::Shape> {
169 None
170 }
171
172 fn raw_scalar(&mut self, content: &str) -> Result<(), Self::Error> {
177 self.scalar(ScalarValue::Str(Cow::Borrowed(content)))
179 }
180
181 fn serialize_opaque_scalar(
185 &mut self,
186 _shape: &'static facet_core::Shape,
187 _value: Peek<'_, '_>,
188 ) -> Result<bool, Self::Error> {
189 Ok(false)
190 }
191
192 fn dynamic_value_tag(&mut self, _tag: DynamicValueTag) -> Result<(), Self::Error> {
197 Ok(())
198 }
199
200 fn begin_seq_with_len(&mut self, _len: usize) -> Result<(), Self::Error> {
217 self.begin_seq()
218 }
219
220 fn begin_map_with_len(&mut self, _len: usize) -> Result<(), Self::Error> {
224 self.begin_struct()
225 }
226
227 fn end_map(&mut self) -> Result<(), Self::Error> {
231 self.end_struct()
232 }
233
234 fn typed_scalar(
244 &mut self,
245 scalar_type: ScalarType,
246 value: Peek<'_, '_>,
247 ) -> Result<(), Self::Error> {
248 let scalar = match scalar_type {
250 ScalarType::Unit => ScalarValue::Null,
251 ScalarType::Bool => ScalarValue::Bool(*value.get::<bool>().unwrap()),
252 ScalarType::Char => ScalarValue::Char(*value.get::<char>().unwrap()),
253 ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
254 ScalarValue::Str(Cow::Borrowed(value.as_str().unwrap()))
255 }
256 ScalarType::F32 => ScalarValue::F64(*value.get::<f32>().unwrap() as f64),
257 ScalarType::F64 => ScalarValue::F64(*value.get::<f64>().unwrap()),
258 ScalarType::U8 => ScalarValue::U64(*value.get::<u8>().unwrap() as u64),
259 ScalarType::U16 => ScalarValue::U64(*value.get::<u16>().unwrap() as u64),
260 ScalarType::U32 => ScalarValue::U64(*value.get::<u32>().unwrap() as u64),
261 ScalarType::U64 => ScalarValue::U64(*value.get::<u64>().unwrap()),
262 ScalarType::U128 => {
263 let n = *value.get::<u128>().unwrap();
264 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&n)))
265 }
266 ScalarType::USize => ScalarValue::U64(*value.get::<usize>().unwrap() as u64),
267 ScalarType::I8 => ScalarValue::I64(*value.get::<i8>().unwrap() as i64),
268 ScalarType::I16 => ScalarValue::I64(*value.get::<i16>().unwrap() as i64),
269 ScalarType::I32 => ScalarValue::I64(*value.get::<i32>().unwrap() as i64),
270 ScalarType::I64 => ScalarValue::I64(*value.get::<i64>().unwrap()),
271 ScalarType::I128 => {
272 let n = *value.get::<i128>().unwrap();
273 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&n)))
274 }
275 ScalarType::ISize => ScalarValue::I64(*value.get::<isize>().unwrap() as i64),
276 #[cfg(feature = "net")]
277 ScalarType::IpAddr => {
278 let addr = *value.get::<core::net::IpAddr>().unwrap();
279 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&addr)))
280 }
281 #[cfg(feature = "net")]
282 ScalarType::Ipv4Addr => {
283 let addr = *value.get::<core::net::Ipv4Addr>().unwrap();
284 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&addr)))
285 }
286 #[cfg(feature = "net")]
287 ScalarType::Ipv6Addr => {
288 let addr = *value.get::<core::net::Ipv6Addr>().unwrap();
289 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&addr)))
290 }
291 #[cfg(feature = "net")]
292 ScalarType::SocketAddr => {
293 let addr = *value.get::<core::net::SocketAddr>().unwrap();
294 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&addr)))
295 }
296 _ => {
297 if let Some(s) = value.as_str() {
299 ScalarValue::Str(Cow::Borrowed(s))
300 } else {
301 ScalarValue::Null
302 }
303 }
304 };
305 self.scalar(scalar)
306 }
307
308 fn begin_option_some(&mut self) -> Result<(), Self::Error> {
315 Ok(())
316 }
317
318 fn serialize_none(&mut self) -> Result<(), Self::Error> {
325 self.scalar(ScalarValue::Null)
326 }
327
328 fn begin_enum_variant(
338 &mut self,
339 _variant_index: usize,
340 _variant_name: &'static str,
341 ) -> Result<(), Self::Error> {
342 Ok(())
343 }
344}
345
346#[derive(Debug)]
348pub enum SerializeError<E: Debug> {
349 Backend(E),
351 Reflect(ReflectError),
353 Unsupported(Cow<'static, str>),
355 Internal(Cow<'static, str>),
357}
358
359impl<E: Debug> core::fmt::Display for SerializeError<E> {
360 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
361 match self {
362 SerializeError::Backend(_) => f.write_str("format serializer error"),
363 SerializeError::Reflect(err) => write!(f, "{err}"),
364 SerializeError::Unsupported(msg) => f.write_str(msg.as_ref()),
365 SerializeError::Internal(msg) => f.write_str(msg.as_ref()),
366 }
367 }
368}
369
370impl<E: Debug> std::error::Error for SerializeError<E> {}
371
372pub fn serialize_root<'mem, 'facet, S>(
374 serializer: &mut S,
375 value: Peek<'mem, 'facet>,
376) -> Result<(), SerializeError<S::Error>>
377where
378 S: FormatSerializer,
379{
380 shared_serialize(serializer, value)
381}
382
383fn sort_fields_if_needed<'mem, 'facet, S>(
385 serializer: &S,
386 fields: &mut alloc::vec::Vec<(facet_reflect::FieldItem, Peek<'mem, 'facet>)>,
387) where
388 S: FormatSerializer,
389{
390 if serializer.preferred_field_order() == FieldOrdering::AttributesFirst {
391 fields.sort_by_key(|(field_item, _)| {
392 match &field_item.field {
395 Some(field) if field.is_attribute() => 0, Some(field) if field.is_text() => 2, None => 0, _ => 1, }
400 });
401 }
402}
403
404fn shared_serialize<'mem, 'facet, S>(
405 serializer: &mut S,
406 value: Peek<'mem, 'facet>,
407) -> Result<(), SerializeError<S::Error>>
408where
409 S: FormatSerializer,
410{
411 let value = deref_if_pointer(value);
413
414 if serializer.raw_serialize_shape() == Some(value.shape()) {
417 if let Ok(struct_) = value.into_struct()
420 && let Some((_field_item, inner_value)) = struct_.fields_for_serialize().next()
421 && let Some(s) = inner_value.as_str()
422 {
423 return serializer.raw_scalar(s).map_err(SerializeError::Backend);
424 }
425 return Err(SerializeError::Unsupported(Cow::Borrowed(
428 "raw capture type matched but could not extract inner string",
429 )));
430 }
431
432 if serializer
433 .serialize_opaque_scalar(value.shape(), value)
434 .map_err(SerializeError::Backend)?
435 {
436 return Ok(());
437 }
438
439 let value = value.innermost_peek();
440
441 if let Some(proxy_def) = value.shape().proxy {
443 return serialize_via_proxy(serializer, value, proxy_def);
444 }
445
446 if let Some(scalar_type) = value.scalar_type() {
448 return serializer
449 .typed_scalar(scalar_type, value)
450 .map_err(SerializeError::Backend);
451 }
452
453 if matches!(value.shape().def, Def::Scalar) && value.shape().vtable.has_display() {
456 use alloc::string::ToString;
457 let formatted = value.to_string();
458 return serializer
459 .scalar(ScalarValue::Str(Cow::Owned(formatted)))
460 .map_err(SerializeError::Backend);
461 }
462
463 if let Ok(opt) = value.into_option() {
465 return match opt.value() {
466 Some(inner) => {
467 serializer
468 .begin_option_some()
469 .map_err(SerializeError::Backend)?;
470 shared_serialize(serializer, inner)
471 }
472 None => serializer.serialize_none().map_err(SerializeError::Backend),
473 };
474 }
475
476 if let Ok(result) = value.into_result() {
477 let (variant_index, variant_name, inner) = if result.is_ok() {
478 (
479 0,
480 "Ok",
481 result.ok().ok_or(SerializeError::Internal(Cow::Borrowed(
482 "result reported Ok but value was missing",
483 )))?,
484 )
485 } else {
486 (
487 1,
488 "Err",
489 result.err().ok_or(SerializeError::Internal(Cow::Borrowed(
490 "result reported Err but value was missing",
491 )))?,
492 )
493 };
494
495 if serializer.enum_variant_encoding() == EnumVariantEncoding::Index {
496 serializer
497 .begin_enum_variant(variant_index, variant_name)
498 .map_err(SerializeError::Backend)?;
499 return shared_serialize(serializer, inner);
500 }
501
502 serializer.begin_struct().map_err(SerializeError::Backend)?;
504 serializer
505 .field_key(variant_name)
506 .map_err(SerializeError::Backend)?;
507 shared_serialize(serializer, inner)?;
508 serializer.end_struct().map_err(SerializeError::Backend)?;
509 return Ok(());
510 }
511
512 if let Ok(dynamic) = value.into_dynamic_value() {
513 return serialize_dynamic_value(serializer, dynamic);
514 }
515
516 match value.shape().def {
517 facet_core::Def::List(_) | facet_core::Def::Array(_) | facet_core::Def::Slice(_) => {
518 let list = value.into_list_like().map_err(SerializeError::Reflect)?;
519 let len = list.len();
520 match value.shape().def {
521 facet_core::Def::Array(_) => {
522 serializer.begin_seq().map_err(SerializeError::Backend)?
523 }
524 _ => serializer
525 .begin_seq_with_len(len)
526 .map_err(SerializeError::Backend)?,
527 };
528 for item in list.iter() {
529 shared_serialize(serializer, item)?;
530 }
531 serializer.end_seq().map_err(SerializeError::Backend)?;
532 return Ok(());
533 }
534 _ => {}
535 }
536
537 if let Ok(map) = value.into_map() {
538 let len = map.len();
539 match serializer.map_encoding() {
540 MapEncoding::Pairs => {
541 serializer
542 .begin_map_with_len(len)
543 .map_err(SerializeError::Backend)?;
544 for (key, val) in map.iter() {
545 shared_serialize(serializer, key)?;
546 shared_serialize(serializer, val)?;
547 }
548 serializer.end_map().map_err(SerializeError::Backend)?;
549 }
550 MapEncoding::Struct => {
551 serializer.begin_struct().map_err(SerializeError::Backend)?;
552 for (key, val) in map.iter() {
553 let key_str = if let Some(s) = key.as_str() {
555 Cow::Borrowed(s)
556 } else {
557 Cow::Owned(alloc::format!("{}", key))
559 };
560 serializer
561 .field_key(&key_str)
562 .map_err(SerializeError::Backend)?;
563 shared_serialize(serializer, val)?;
564 }
565 serializer.end_struct().map_err(SerializeError::Backend)?;
566 }
567 }
568 return Ok(());
569 }
570
571 if let Ok(set) = value.into_set() {
572 let len = set.len();
574 serializer
575 .begin_seq_with_len(len)
576 .map_err(SerializeError::Backend)?;
577 for item in set.iter() {
578 shared_serialize(serializer, item)?;
579 }
580 serializer.end_seq().map_err(SerializeError::Backend)?;
581 return Ok(());
582 }
583
584 if let Ok(struct_) = value.into_struct() {
585 let kind = struct_.ty().kind;
586 if kind == StructKind::Tuple || kind == StructKind::TupleStruct {
587 let fields: alloc::vec::Vec<_> = struct_.fields_for_serialize().collect();
589 serializer.begin_seq().map_err(SerializeError::Backend)?;
590 for (field_item, field_value) in fields {
591 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
593 serialize_via_proxy(serializer, field_value, proxy_def)?;
594 } else {
595 shared_serialize(serializer, field_value)?;
596 }
597 }
598 serializer.end_seq().map_err(SerializeError::Backend)?;
599 } else {
600 serializer
602 .struct_metadata(value.shape())
603 .map_err(SerializeError::Backend)?;
604 serializer.begin_struct().map_err(SerializeError::Backend)?;
605
606 let mut fields: alloc::vec::Vec<_> = struct_.fields_for_serialize().collect();
608 sort_fields_if_needed(serializer, &mut fields);
609 let field_mode = serializer.struct_field_mode();
610
611 for (field_item, field_value) in fields {
612 serializer
613 .field_metadata(&field_item)
614 .map_err(SerializeError::Backend)?;
615 if field_mode == StructFieldMode::Named {
616 serializer
617 .field_key(&field_item.name)
618 .map_err(SerializeError::Backend)?;
619 }
620 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
622 serialize_via_proxy(serializer, field_value, proxy_def)?;
623 } else {
624 shared_serialize(serializer, field_value)?;
625 }
626 }
627 serializer.end_struct().map_err(SerializeError::Backend)?;
628 }
629 return Ok(());
630 }
631
632 if let Ok(enum_) = value.into_enum() {
633 let variant = enum_.active_variant().map_err(|_| {
634 SerializeError::Unsupported(Cow::Borrowed("opaque enum layout is unsupported"))
635 })?;
636
637 serializer
639 .variant_metadata(variant)
640 .map_err(SerializeError::Backend)?;
641
642 if serializer.enum_variant_encoding() == EnumVariantEncoding::Index {
643 let variant_index = enum_.variant_index().map_err(|_| {
644 SerializeError::Unsupported(Cow::Borrowed("opaque enum layout is unsupported"))
645 })?;
646 serializer
647 .begin_enum_variant(variant_index, variant.name)
648 .map_err(SerializeError::Backend)?;
649
650 match variant.data.kind {
651 StructKind::Unit => return Ok(()),
652 StructKind::TupleStruct | StructKind::Tuple | StructKind::Struct => {
653 for (field_item, field_value) in enum_.fields_for_serialize() {
654 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
655 serialize_via_proxy(serializer, field_value, proxy_def)?;
656 } else {
657 shared_serialize(serializer, field_value)?;
658 }
659 }
660 return Ok(());
661 }
662 }
663 }
664
665 let numeric = value.shape().is_numeric();
666 let untagged = value.shape().is_untagged();
667 let tag = value.shape().get_tag_attr();
668 let content = value.shape().get_content_attr();
669
670 if numeric {
671 return serialize_numeric_enum(serializer, variant);
672 }
673 if untagged {
674 return serialize_untagged_enum(serializer, enum_, variant);
675 }
676
677 match (tag, content) {
678 (Some(tag_key), None) => {
679 serializer.begin_struct().map_err(SerializeError::Backend)?;
681 serializer
682 .field_key(tag_key)
683 .map_err(SerializeError::Backend)?;
684 serializer
685 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
686 .map_err(SerializeError::Backend)?;
687
688 match variant.data.kind {
689 StructKind::Unit => {}
690 StructKind::Struct => {
691 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
692 sort_fields_if_needed(serializer, &mut fields);
693 let field_mode = serializer.struct_field_mode();
694 for (field_item, field_value) in fields {
695 serializer
696 .field_metadata(&field_item)
697 .map_err(SerializeError::Backend)?;
698 if field_mode == StructFieldMode::Named {
699 serializer
700 .field_key(&field_item.name)
701 .map_err(SerializeError::Backend)?;
702 }
703 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
705 serialize_via_proxy(serializer, field_value, proxy_def)?;
706 } else {
707 shared_serialize(serializer, field_value)?;
708 }
709 }
710 }
711 StructKind::TupleStruct | StructKind::Tuple => {
712 return Err(SerializeError::Unsupported(Cow::Borrowed(
713 "internally tagged tuple variants are not supported",
714 )));
715 }
716 }
717
718 serializer.end_struct().map_err(SerializeError::Backend)?;
719 return Ok(());
720 }
721 (Some(tag_key), Some(content_key)) => {
722 serializer.begin_struct().map_err(SerializeError::Backend)?;
724 serializer
725 .field_key(tag_key)
726 .map_err(SerializeError::Backend)?;
727 serializer
728 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
729 .map_err(SerializeError::Backend)?;
730
731 match variant.data.kind {
732 StructKind::Unit => {
733 }
735 StructKind::Struct => {
736 serializer
737 .field_key(content_key)
738 .map_err(SerializeError::Backend)?;
739 serializer.begin_struct().map_err(SerializeError::Backend)?;
740 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
741 sort_fields_if_needed(serializer, &mut fields);
742 let field_mode = serializer.struct_field_mode();
743 for (field_item, field_value) in fields {
744 serializer
745 .field_metadata(&field_item)
746 .map_err(SerializeError::Backend)?;
747 if field_mode == StructFieldMode::Named {
748 serializer
749 .field_key(&field_item.name)
750 .map_err(SerializeError::Backend)?;
751 }
752 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
754 serialize_via_proxy(serializer, field_value, proxy_def)?;
755 } else {
756 shared_serialize(serializer, field_value)?;
757 }
758 }
759 serializer.end_struct().map_err(SerializeError::Backend)?;
760 }
761 StructKind::TupleStruct | StructKind::Tuple => {
762 serializer
763 .field_key(content_key)
764 .map_err(SerializeError::Backend)?;
765
766 let field_count = variant.data.fields.len();
767 if field_count == 1 {
768 let inner = enum_
769 .field(0)
770 .map_err(|_| {
771 SerializeError::Internal(Cow::Borrowed(
772 "variant field lookup failed",
773 ))
774 })?
775 .ok_or(SerializeError::Internal(Cow::Borrowed(
776 "variant reported 1 field but field(0) returned None",
777 )))?;
778 shared_serialize(serializer, inner)?;
779 } else {
780 serializer.begin_seq().map_err(SerializeError::Backend)?;
781 for idx in 0..field_count {
782 let inner = enum_
783 .field(idx)
784 .map_err(|_| {
785 SerializeError::Internal(Cow::Borrowed(
786 "variant field lookup failed",
787 ))
788 })?
789 .ok_or(SerializeError::Internal(Cow::Borrowed(
790 "variant field missing while iterating tuple fields",
791 )))?;
792 shared_serialize(serializer, inner)?;
793 }
794 serializer.end_seq().map_err(SerializeError::Backend)?;
795 }
796 }
797 }
798
799 serializer.end_struct().map_err(SerializeError::Backend)?;
800 return Ok(());
801 }
802 (None, Some(_)) => {
803 return Err(SerializeError::Unsupported(Cow::Borrowed(
804 "adjacent content key set without tag key",
805 )));
806 }
807 (None, None) => {}
808 }
809
810 return match variant.data.kind {
812 StructKind::Unit => {
813 serializer
814 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
815 .map_err(SerializeError::Backend)?;
816 Ok(())
817 }
818 StructKind::TupleStruct | StructKind::Tuple => {
819 serializer.begin_struct().map_err(SerializeError::Backend)?;
820 serializer
821 .field_key(variant.name)
822 .map_err(SerializeError::Backend)?;
823
824 let field_count = variant.data.fields.len();
825 if field_count == 1 {
826 let inner = enum_
827 .field(0)
828 .map_err(|_| {
829 SerializeError::Internal(Cow::Borrowed("variant field lookup failed"))
830 })?
831 .ok_or(SerializeError::Internal(Cow::Borrowed(
832 "variant reported 1 field but field(0) returned None",
833 )))?;
834 shared_serialize(serializer, inner)?;
835 } else {
836 serializer.begin_seq().map_err(SerializeError::Backend)?;
837 for idx in 0..field_count {
838 let inner = enum_
839 .field(idx)
840 .map_err(|_| {
841 SerializeError::Internal(Cow::Borrowed(
842 "variant field lookup failed",
843 ))
844 })?
845 .ok_or(SerializeError::Internal(Cow::Borrowed(
846 "variant field missing while iterating tuple fields",
847 )))?;
848 shared_serialize(serializer, inner)?;
849 }
850 serializer.end_seq().map_err(SerializeError::Backend)?;
851 }
852
853 serializer.end_struct().map_err(SerializeError::Backend)?;
854 Ok(())
855 }
856 StructKind::Struct => {
857 serializer.begin_struct().map_err(SerializeError::Backend)?;
858 serializer
859 .field_key(variant.name)
860 .map_err(SerializeError::Backend)?;
861
862 serializer.begin_struct().map_err(SerializeError::Backend)?;
863 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
864 sort_fields_if_needed(serializer, &mut fields);
865 let field_mode = serializer.struct_field_mode();
866 for (field_item, field_value) in fields {
867 serializer
868 .field_metadata(&field_item)
869 .map_err(SerializeError::Backend)?;
870 if field_mode == StructFieldMode::Named {
871 serializer
872 .field_key(&field_item.name)
873 .map_err(SerializeError::Backend)?;
874 }
875 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
877 serialize_via_proxy(serializer, field_value, proxy_def)?;
878 } else {
879 shared_serialize(serializer, field_value)?;
880 }
881 }
882 serializer.end_struct().map_err(SerializeError::Backend)?;
883
884 serializer.end_struct().map_err(SerializeError::Backend)?;
885 Ok(())
886 }
887 };
888 }
889
890 Err(SerializeError::Unsupported(Cow::Borrowed(
891 "unsupported value kind for serialization",
892 )))
893}
894
895fn serialize_dynamic_value<'mem, 'facet, S>(
896 serializer: &mut S,
897 dynamic: facet_reflect::PeekDynamicValue<'mem, 'facet>,
898) -> Result<(), SerializeError<S::Error>>
899where
900 S: FormatSerializer,
901{
902 let tagged = serializer.dynamic_value_encoding() == DynamicValueEncoding::Tagged;
903
904 match dynamic.kind() {
905 DynValueKind::Null => {
906 if tagged {
907 serializer
908 .dynamic_value_tag(DynamicValueTag::Null)
909 .map_err(SerializeError::Backend)?;
910 }
911 serializer
912 .scalar(ScalarValue::Null)
913 .map_err(SerializeError::Backend)
914 }
915 DynValueKind::Bool => {
916 let value = dynamic.as_bool().ok_or_else(|| {
917 SerializeError::Internal(Cow::Borrowed("dynamic bool missing value"))
918 })?;
919 if tagged {
920 serializer
921 .dynamic_value_tag(DynamicValueTag::Bool)
922 .map_err(SerializeError::Backend)?;
923 }
924 serializer
925 .scalar(ScalarValue::Bool(value))
926 .map_err(SerializeError::Backend)
927 }
928 DynValueKind::Number => {
929 if let Some(n) = dynamic.as_i64() {
930 if tagged {
931 serializer
932 .dynamic_value_tag(DynamicValueTag::I64)
933 .map_err(SerializeError::Backend)?;
934 }
935 serializer
936 .scalar(ScalarValue::I64(n))
937 .map_err(SerializeError::Backend)
938 } else if let Some(n) = dynamic.as_u64() {
939 if tagged {
940 serializer
941 .dynamic_value_tag(DynamicValueTag::U64)
942 .map_err(SerializeError::Backend)?;
943 }
944 serializer
945 .scalar(ScalarValue::U64(n))
946 .map_err(SerializeError::Backend)
947 } else if let Some(n) = dynamic.as_f64() {
948 if tagged {
949 serializer
950 .dynamic_value_tag(DynamicValueTag::F64)
951 .map_err(SerializeError::Backend)?;
952 }
953 serializer
954 .scalar(ScalarValue::F64(n))
955 .map_err(SerializeError::Backend)
956 } else {
957 Err(SerializeError::Unsupported(Cow::Borrowed(
958 "dynamic number not representable",
959 )))
960 }
961 }
962 DynValueKind::String => {
963 let value = dynamic.as_str().ok_or_else(|| {
964 SerializeError::Internal(Cow::Borrowed("dynamic string missing value"))
965 })?;
966 if tagged {
967 serializer
968 .dynamic_value_tag(DynamicValueTag::String)
969 .map_err(SerializeError::Backend)?;
970 }
971 serializer
972 .scalar(ScalarValue::Str(Cow::Borrowed(value)))
973 .map_err(SerializeError::Backend)
974 }
975 DynValueKind::Bytes => {
976 let value = dynamic.as_bytes().ok_or_else(|| {
977 SerializeError::Internal(Cow::Borrowed("dynamic bytes missing value"))
978 })?;
979 if tagged {
980 serializer
981 .dynamic_value_tag(DynamicValueTag::Bytes)
982 .map_err(SerializeError::Backend)?;
983 }
984 serializer
985 .scalar(ScalarValue::Bytes(Cow::Borrowed(value)))
986 .map_err(SerializeError::Backend)
987 }
988 DynValueKind::Array => {
989 let len = dynamic.array_len().ok_or_else(|| {
990 SerializeError::Internal(Cow::Borrowed("dynamic array missing length"))
991 })?;
992 if tagged {
993 serializer
994 .dynamic_value_tag(DynamicValueTag::Array)
995 .map_err(SerializeError::Backend)?;
996 }
997 serializer
998 .begin_seq_with_len(len)
999 .map_err(SerializeError::Backend)?;
1000 if let Some(iter) = dynamic.array_iter() {
1001 for item in iter {
1002 shared_serialize(serializer, item)?;
1003 }
1004 }
1005 serializer.end_seq().map_err(SerializeError::Backend)
1006 }
1007 DynValueKind::Object => {
1008 let len = dynamic.object_len().ok_or_else(|| {
1009 SerializeError::Internal(Cow::Borrowed("dynamic object missing length"))
1010 })?;
1011 if tagged {
1012 serializer
1013 .dynamic_value_tag(DynamicValueTag::Object)
1014 .map_err(SerializeError::Backend)?;
1015 }
1016 match serializer.map_encoding() {
1017 MapEncoding::Pairs => {
1018 serializer
1019 .begin_map_with_len(len)
1020 .map_err(SerializeError::Backend)?;
1021 if let Some(iter) = dynamic.object_iter() {
1022 for (key, value) in iter {
1023 serializer
1024 .scalar(ScalarValue::Str(Cow::Borrowed(key)))
1025 .map_err(SerializeError::Backend)?;
1026 shared_serialize(serializer, value)?;
1027 }
1028 }
1029 serializer.end_map().map_err(SerializeError::Backend)
1030 }
1031 MapEncoding::Struct => {
1032 serializer.begin_struct().map_err(SerializeError::Backend)?;
1033 if let Some(iter) = dynamic.object_iter() {
1034 for (key, value) in iter {
1035 serializer.field_key(key).map_err(SerializeError::Backend)?;
1036 shared_serialize(serializer, value)?;
1037 }
1038 }
1039 serializer.end_struct().map_err(SerializeError::Backend)
1040 }
1041 }
1042 }
1043 DynValueKind::DateTime => {
1044 let dt = dynamic.as_datetime().ok_or_else(|| {
1045 SerializeError::Internal(Cow::Borrowed("dynamic datetime missing value"))
1046 })?;
1047 if tagged {
1048 serializer
1049 .dynamic_value_tag(DynamicValueTag::DateTime)
1050 .map_err(SerializeError::Backend)?;
1051 }
1052 let s = format_dyn_datetime(dt);
1053 serializer
1054 .scalar(ScalarValue::Str(Cow::Owned(s)))
1055 .map_err(SerializeError::Backend)
1056 }
1057 DynValueKind::QName | DynValueKind::Uuid => Err(SerializeError::Unsupported(
1058 Cow::Borrowed("dynamic QName/Uuid serialization is not supported"),
1059 )),
1060 }
1061}
1062
1063fn format_dyn_datetime(
1064 (year, month, day, hour, minute, second, nanos, kind): (
1065 i32,
1066 u8,
1067 u8,
1068 u8,
1069 u8,
1070 u8,
1071 u32,
1072 DynDateTimeKind,
1073 ),
1074) -> String {
1075 let mut out = String::new();
1076 match kind {
1077 DynDateTimeKind::Offset { offset_minutes } => {
1078 let _ = write!(
1079 out,
1080 "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}",
1081 year, month, day, hour, minute, second
1082 );
1083 if nanos > 0 {
1084 let _ = write!(out, ".{:09}", nanos);
1085 }
1086 if offset_minutes == 0 {
1087 out.push('Z');
1088 } else {
1089 let sign = if offset_minutes >= 0 { '+' } else { '-' };
1090 let abs = offset_minutes.unsigned_abs();
1091 let _ = write!(out, "{}{:02}:{:02}", sign, abs / 60, abs % 60);
1092 }
1093 }
1094 DynDateTimeKind::LocalDateTime => {
1095 let _ = write!(
1096 out,
1097 "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}",
1098 year, month, day, hour, minute, second
1099 );
1100 if nanos > 0 {
1101 let _ = write!(out, ".{:09}", nanos);
1102 }
1103 }
1104 DynDateTimeKind::LocalDate => {
1105 let _ = write!(out, "{:04}-{:02}-{:02}", year, month, day);
1106 }
1107 DynDateTimeKind::LocalTime => {
1108 let _ = write!(out, "{:02}:{:02}:{:02}", hour, minute, second);
1109 if nanos > 0 {
1110 let _ = write!(out, ".{:09}", nanos);
1111 }
1112 }
1113 }
1114 out
1115}
1116
1117fn serialize_numeric_enum<S>(
1118 serializer: &mut S,
1119 variant: &'static facet_core::Variant,
1120) -> Result<(), SerializeError<S::Error>>
1121where
1122 S: FormatSerializer,
1123{
1124 let discriminant = variant
1125 .discriminant
1126 .ok_or(SerializeError::Unsupported(Cow::Borrowed(
1127 "Enum without a discriminant",
1128 )))?;
1129 serializer
1130 .scalar(ScalarValue::I64(discriminant))
1131 .map_err(SerializeError::Backend)
1132}
1133
1134fn serialize_untagged_enum<'mem, 'facet, S>(
1135 serializer: &mut S,
1136 enum_: facet_reflect::PeekEnum<'mem, 'facet>,
1137 variant: &'static facet_core::Variant,
1138) -> Result<(), SerializeError<S::Error>>
1139where
1140 S: FormatSerializer,
1141{
1142 match variant.data.kind {
1143 StructKind::Unit => {
1144 if variant.name.eq_ignore_ascii_case("null") {
1148 return serializer
1149 .scalar(ScalarValue::Null)
1150 .map_err(SerializeError::Backend);
1151 }
1152 serializer
1153 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
1154 .map_err(SerializeError::Backend)
1155 }
1156 StructKind::TupleStruct | StructKind::Tuple => {
1157 let field_count = variant.data.fields.len();
1158 if field_count == 1 {
1159 let inner = enum_
1160 .field(0)
1161 .map_err(|_| {
1162 SerializeError::Internal(Cow::Borrowed("variant field lookup failed"))
1163 })?
1164 .ok_or(SerializeError::Internal(Cow::Borrowed(
1165 "variant reported 1 field but field(0) returned None",
1166 )))?;
1167 shared_serialize(serializer, inner)
1168 } else {
1169 serializer.begin_seq().map_err(SerializeError::Backend)?;
1170 for idx in 0..field_count {
1171 let inner = enum_
1172 .field(idx)
1173 .map_err(|_| {
1174 SerializeError::Internal(Cow::Borrowed("variant field lookup failed"))
1175 })?
1176 .ok_or(SerializeError::Internal(Cow::Borrowed(
1177 "variant field missing while iterating tuple fields",
1178 )))?;
1179 shared_serialize(serializer, inner)?;
1180 }
1181 serializer.end_seq().map_err(SerializeError::Backend)?;
1182 Ok(())
1183 }
1184 }
1185 StructKind::Struct => {
1186 serializer.begin_struct().map_err(SerializeError::Backend)?;
1187 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
1188 sort_fields_if_needed(serializer, &mut fields);
1189 for (field_item, field_value) in fields {
1190 serializer
1191 .field_metadata(&field_item)
1192 .map_err(SerializeError::Backend)?;
1193 serializer
1194 .field_key(&field_item.name)
1195 .map_err(SerializeError::Backend)?;
1196 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
1198 serialize_via_proxy(serializer, field_value, proxy_def)?;
1199 } else {
1200 shared_serialize(serializer, field_value)?;
1201 }
1202 }
1203 serializer.end_struct().map_err(SerializeError::Backend)?;
1204 Ok(())
1205 }
1206 }
1207}
1208
1209fn deref_if_pointer<'mem, 'facet>(peek: Peek<'mem, 'facet>) -> Peek<'mem, 'facet> {
1211 if let Ok(ptr) = peek.into_pointer()
1212 && let Some(target) = ptr.borrow_inner()
1213 {
1214 return deref_if_pointer(target);
1215 }
1216 peek
1217}
1218
1219#[allow(unsafe_code)]
1227fn serialize_via_proxy<'mem, 'facet, S>(
1228 serializer: &mut S,
1229 value: Peek<'mem, 'facet>,
1230 proxy_def: &'static facet_core::ProxyDef,
1231) -> Result<(), SerializeError<S::Error>>
1232where
1233 S: FormatSerializer,
1234{
1235 use facet_core::PtrUninit;
1236
1237 let proxy_shape = proxy_def.shape;
1238 let proxy_layout = proxy_shape.layout.sized_layout().map_err(|_| {
1239 SerializeError::Unsupported(Cow::Borrowed("proxy type must be sized for serialization"))
1240 })?;
1241
1242 let proxy_mem = unsafe { alloc::alloc::alloc(proxy_layout) };
1244 if proxy_mem.is_null() {
1245 return Err(SerializeError::Internal(Cow::Borrowed(
1246 "failed to allocate proxy memory",
1247 )));
1248 }
1249
1250 let proxy_uninit = PtrUninit::new(proxy_mem);
1252 let convert_result = unsafe { (proxy_def.convert_out)(value.data(), proxy_uninit) };
1253
1254 let proxy_ptr = match convert_result {
1255 Ok(ptr) => ptr,
1256 Err(msg) => {
1257 unsafe { alloc::alloc::dealloc(proxy_mem, proxy_layout) };
1258 return Err(SerializeError::Unsupported(Cow::Owned(msg)));
1259 }
1260 };
1261
1262 let proxy_peek = unsafe { Peek::unchecked_new(proxy_ptr.as_const(), proxy_shape) };
1264 let result = shared_serialize(serializer, proxy_peek);
1265
1266 unsafe {
1268 let _ = proxy_shape.call_drop_in_place(proxy_ptr);
1269 alloc::alloc::dealloc(proxy_mem, proxy_layout);
1270 }
1271
1272 result
1273}