1extern crate alloc;
2
3use alloc::borrow::Cow;
4use core::fmt::Debug;
5
6use facet_core::{ScalarType, StructKind};
7use facet_reflect::{HasFields as _, Peek, ReflectError};
8
9use crate::ScalarValue;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
13pub enum FieldOrdering {
14 #[default]
16 Declaration,
17 AttributesFirst,
19}
20
21pub trait FormatSerializer {
26 type Error: Debug;
28
29 fn begin_struct(&mut self) -> Result<(), Self::Error>;
31 fn field_key(&mut self, key: &str) -> Result<(), Self::Error>;
33 fn end_struct(&mut self) -> Result<(), Self::Error>;
35
36 fn begin_seq(&mut self) -> Result<(), Self::Error>;
38 fn end_seq(&mut self) -> Result<(), Self::Error>;
40
41 fn scalar(&mut self, scalar: ScalarValue<'_>) -> Result<(), Self::Error>;
43
44 fn field_metadata(&mut self, _field: &facet_reflect::FieldItem) -> Result<(), Self::Error> {
48 Ok(())
49 }
50
51 fn struct_metadata(&mut self, _shape: &facet_core::Shape) -> Result<(), Self::Error> {
55 Ok(())
56 }
57
58 fn variant_metadata(
63 &mut self,
64 _variant: &'static facet_core::Variant,
65 ) -> Result<(), Self::Error> {
66 Ok(())
67 }
68
69 fn preferred_field_order(&self) -> FieldOrdering {
73 FieldOrdering::Declaration
74 }
75
76 fn raw_serialize_shape(&self) -> Option<&'static facet_core::Shape> {
82 None
83 }
84
85 fn raw_scalar(&mut self, content: &str) -> Result<(), Self::Error> {
90 self.scalar(ScalarValue::Str(Cow::Borrowed(content)))
92 }
93
94 fn begin_seq_with_len(&mut self, _len: usize) -> Result<(), Self::Error> {
111 self.begin_seq()
112 }
113
114 fn typed_scalar(
124 &mut self,
125 scalar_type: ScalarType,
126 value: Peek<'_, '_>,
127 ) -> Result<(), Self::Error> {
128 let scalar = match scalar_type {
130 ScalarType::Unit => ScalarValue::Null,
131 ScalarType::Bool => ScalarValue::Bool(*value.get::<bool>().unwrap()),
132 ScalarType::Char => {
133 let c = *value.get::<char>().unwrap();
134 let mut buf = [0u8; 4];
135 ScalarValue::Str(Cow::Owned(c.encode_utf8(&mut buf).to_string()))
136 }
137 ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
138 ScalarValue::Str(Cow::Borrowed(value.as_str().unwrap()))
139 }
140 ScalarType::F32 => ScalarValue::F64(*value.get::<f32>().unwrap() as f64),
141 ScalarType::F64 => ScalarValue::F64(*value.get::<f64>().unwrap()),
142 ScalarType::U8 => ScalarValue::U64(*value.get::<u8>().unwrap() as u64),
143 ScalarType::U16 => ScalarValue::U64(*value.get::<u16>().unwrap() as u64),
144 ScalarType::U32 => ScalarValue::U64(*value.get::<u32>().unwrap() as u64),
145 ScalarType::U64 => ScalarValue::U64(*value.get::<u64>().unwrap()),
146 ScalarType::U128 => {
147 let n = *value.get::<u128>().unwrap();
148 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&n)))
149 }
150 ScalarType::USize => ScalarValue::U64(*value.get::<usize>().unwrap() as u64),
151 ScalarType::I8 => ScalarValue::I64(*value.get::<i8>().unwrap() as i64),
152 ScalarType::I16 => ScalarValue::I64(*value.get::<i16>().unwrap() as i64),
153 ScalarType::I32 => ScalarValue::I64(*value.get::<i32>().unwrap() as i64),
154 ScalarType::I64 => ScalarValue::I64(*value.get::<i64>().unwrap()),
155 ScalarType::I128 => {
156 let n = *value.get::<i128>().unwrap();
157 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&n)))
158 }
159 ScalarType::ISize => ScalarValue::I64(*value.get::<isize>().unwrap() as i64),
160 _ => {
161 if let Some(s) = value.as_str() {
163 ScalarValue::Str(Cow::Borrowed(s))
164 } else {
165 ScalarValue::Null
166 }
167 }
168 };
169 self.scalar(scalar)
170 }
171
172 fn begin_option_some(&mut self) -> Result<(), Self::Error> {
179 Ok(())
180 }
181
182 fn serialize_none(&mut self) -> Result<(), Self::Error> {
189 self.scalar(ScalarValue::Null)
190 }
191
192 fn begin_enum_variant(
202 &mut self,
203 _variant_index: usize,
204 _variant_name: &'static str,
205 ) -> Result<(), Self::Error> {
206 Ok(())
207 }
208}
209
210#[derive(Debug)]
212pub enum SerializeError<E: Debug> {
213 Backend(E),
215 Reflect(ReflectError),
217 Unsupported(Cow<'static, str>),
219 Internal(Cow<'static, str>),
221}
222
223impl<E: Debug> core::fmt::Display for SerializeError<E> {
224 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
225 match self {
226 SerializeError::Backend(_) => f.write_str("format serializer error"),
227 SerializeError::Reflect(err) => write!(f, "{err}"),
228 SerializeError::Unsupported(msg) => f.write_str(msg.as_ref()),
229 SerializeError::Internal(msg) => f.write_str(msg.as_ref()),
230 }
231 }
232}
233
234impl<E: Debug> std::error::Error for SerializeError<E> {}
235
236pub fn serialize_root<'mem, 'facet, S>(
238 serializer: &mut S,
239 value: Peek<'mem, 'facet>,
240) -> Result<(), SerializeError<S::Error>>
241where
242 S: FormatSerializer,
243{
244 shared_serialize(serializer, value)
245}
246
247fn sort_fields_if_needed<'mem, 'facet, S>(
249 serializer: &S,
250 fields: &mut alloc::vec::Vec<(facet_reflect::FieldItem, Peek<'mem, 'facet>)>,
251) where
252 S: FormatSerializer,
253{
254 if serializer.preferred_field_order() == FieldOrdering::AttributesFirst {
255 fields.sort_by_key(|(field_item, _)| {
256 match &field_item.field {
259 Some(field) if field.is_attribute() => 0, Some(field) if field.is_text() => 2, None => 0, _ => 1, }
264 });
265 }
266}
267
268fn shared_serialize<'mem, 'facet, S>(
269 serializer: &mut S,
270 value: Peek<'mem, 'facet>,
271) -> Result<(), SerializeError<S::Error>>
272where
273 S: FormatSerializer,
274{
275 let value = deref_if_pointer(value);
277
278 if serializer.raw_serialize_shape() == Some(value.shape()) {
281 if let Ok(struct_) = value.into_struct()
284 && let Some((_field_item, inner_value)) = struct_.fields_for_serialize().next()
285 && let Some(s) = inner_value.as_str()
286 {
287 return serializer.raw_scalar(s).map_err(SerializeError::Backend);
288 }
289 return Err(SerializeError::Unsupported(Cow::Borrowed(
292 "raw capture type matched but could not extract inner string",
293 )));
294 }
295
296 let value = value.innermost_peek();
297
298 if let Some(proxy_def) = value.shape().proxy {
300 return serialize_via_proxy(serializer, value, proxy_def);
301 }
302
303 if let Some(scalar_type) = value.scalar_type() {
305 return serializer
306 .typed_scalar(scalar_type, value)
307 .map_err(SerializeError::Backend);
308 }
309
310 if let Ok(opt) = value.into_option() {
312 return match opt.value() {
313 Some(inner) => {
314 serializer
315 .begin_option_some()
316 .map_err(SerializeError::Backend)?;
317 shared_serialize(serializer, inner)
318 }
319 None => serializer.serialize_none().map_err(SerializeError::Backend),
320 };
321 }
322
323 if let Ok(list) = value.into_list_like() {
324 let items: alloc::vec::Vec<_> = list.iter().collect();
326 serializer
327 .begin_seq_with_len(items.len())
328 .map_err(SerializeError::Backend)?;
329 for item in items {
330 shared_serialize(serializer, item)?;
331 }
332 serializer.end_seq().map_err(SerializeError::Backend)?;
333 return Ok(());
334 }
335
336 if let Ok(map) = value.into_map() {
337 serializer.begin_struct().map_err(SerializeError::Backend)?;
338 for (key, val) in map.iter() {
339 let key_str = if let Some(s) = key.as_str() {
341 Cow::Borrowed(s)
342 } else {
343 Cow::Owned(alloc::format!("{:?}", key))
345 };
346 serializer
347 .field_key(&key_str)
348 .map_err(SerializeError::Backend)?;
349 shared_serialize(serializer, val)?;
350 }
351 serializer.end_struct().map_err(SerializeError::Backend)?;
352 return Ok(());
353 }
354
355 if let Ok(set) = value.into_set() {
356 let items: alloc::vec::Vec<_> = set.iter().collect();
358 serializer
359 .begin_seq_with_len(items.len())
360 .map_err(SerializeError::Backend)?;
361 for item in items {
362 shared_serialize(serializer, item)?;
363 }
364 serializer.end_seq().map_err(SerializeError::Backend)?;
365 return Ok(());
366 }
367
368 if let Ok(struct_) = value.into_struct() {
369 let kind = struct_.ty().kind;
370 if kind == StructKind::Tuple || kind == StructKind::TupleStruct {
371 let fields: alloc::vec::Vec<_> = struct_.fields_for_serialize().collect();
373 serializer
374 .begin_seq_with_len(fields.len())
375 .map_err(SerializeError::Backend)?;
376 for (field_item, field_value) in fields {
377 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
379 serialize_via_proxy(serializer, field_value, proxy_def)?;
380 } else {
381 shared_serialize(serializer, field_value)?;
382 }
383 }
384 serializer.end_seq().map_err(SerializeError::Backend)?;
385 } else {
386 serializer
388 .struct_metadata(value.shape())
389 .map_err(SerializeError::Backend)?;
390 serializer.begin_struct().map_err(SerializeError::Backend)?;
391
392 let mut fields: alloc::vec::Vec<_> = struct_.fields_for_serialize().collect();
394 sort_fields_if_needed(serializer, &mut fields);
395
396 for (field_item, field_value) in fields {
397 serializer
398 .field_metadata(&field_item)
399 .map_err(SerializeError::Backend)?;
400 serializer
401 .field_key(&field_item.name)
402 .map_err(SerializeError::Backend)?;
403 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
405 serialize_via_proxy(serializer, field_value, proxy_def)?;
406 } else {
407 shared_serialize(serializer, field_value)?;
408 }
409 }
410 serializer.end_struct().map_err(SerializeError::Backend)?;
411 }
412 return Ok(());
413 }
414
415 if let Ok(enum_) = value.into_enum() {
416 let variant = enum_.active_variant().map_err(|_| {
417 SerializeError::Unsupported(Cow::Borrowed("opaque enum layout is unsupported"))
418 })?;
419
420 serializer
422 .variant_metadata(variant)
423 .map_err(SerializeError::Backend)?;
424
425 let numeric = value.shape().is_numeric();
426 let untagged = value.shape().is_untagged();
427 let tag = value.shape().get_tag_attr();
428 let content = value.shape().get_content_attr();
429
430 if numeric {
431 return serialize_numeric_enum(serializer, variant);
432 }
433 if untagged {
434 return serialize_untagged_enum(serializer, enum_, variant);
435 }
436
437 match (tag, content) {
438 (Some(tag_key), None) => {
439 serializer.begin_struct().map_err(SerializeError::Backend)?;
441 serializer
442 .field_key(tag_key)
443 .map_err(SerializeError::Backend)?;
444 serializer
445 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
446 .map_err(SerializeError::Backend)?;
447
448 match variant.data.kind {
449 StructKind::Unit => {}
450 StructKind::Struct => {
451 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
452 sort_fields_if_needed(serializer, &mut fields);
453 for (field_item, field_value) in fields {
454 serializer
455 .field_metadata(&field_item)
456 .map_err(SerializeError::Backend)?;
457 serializer
458 .field_key(&field_item.name)
459 .map_err(SerializeError::Backend)?;
460 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
462 serialize_via_proxy(serializer, field_value, proxy_def)?;
463 } else {
464 shared_serialize(serializer, field_value)?;
465 }
466 }
467 }
468 StructKind::TupleStruct | StructKind::Tuple => {
469 return Err(SerializeError::Unsupported(Cow::Borrowed(
470 "internally tagged tuple variants are not supported",
471 )));
472 }
473 }
474
475 serializer.end_struct().map_err(SerializeError::Backend)?;
476 return Ok(());
477 }
478 (Some(tag_key), Some(content_key)) => {
479 serializer.begin_struct().map_err(SerializeError::Backend)?;
481 serializer
482 .field_key(tag_key)
483 .map_err(SerializeError::Backend)?;
484 serializer
485 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
486 .map_err(SerializeError::Backend)?;
487
488 match variant.data.kind {
489 StructKind::Unit => {
490 }
492 StructKind::Struct => {
493 serializer
494 .field_key(content_key)
495 .map_err(SerializeError::Backend)?;
496 serializer.begin_struct().map_err(SerializeError::Backend)?;
497 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
498 sort_fields_if_needed(serializer, &mut fields);
499 for (field_item, field_value) in fields {
500 serializer
501 .field_metadata(&field_item)
502 .map_err(SerializeError::Backend)?;
503 serializer
504 .field_key(&field_item.name)
505 .map_err(SerializeError::Backend)?;
506 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
508 serialize_via_proxy(serializer, field_value, proxy_def)?;
509 } else {
510 shared_serialize(serializer, field_value)?;
511 }
512 }
513 serializer.end_struct().map_err(SerializeError::Backend)?;
514 }
515 StructKind::TupleStruct | StructKind::Tuple => {
516 serializer
517 .field_key(content_key)
518 .map_err(SerializeError::Backend)?;
519
520 let field_count = variant.data.fields.len();
521 if field_count == 1 {
522 let inner = enum_
523 .field(0)
524 .map_err(|_| {
525 SerializeError::Internal(Cow::Borrowed(
526 "variant field lookup failed",
527 ))
528 })?
529 .ok_or(SerializeError::Internal(Cow::Borrowed(
530 "variant reported 1 field but field(0) returned None",
531 )))?;
532 shared_serialize(serializer, inner)?;
533 } else {
534 serializer.begin_seq().map_err(SerializeError::Backend)?;
535 for idx in 0..field_count {
536 let inner = enum_
537 .field(idx)
538 .map_err(|_| {
539 SerializeError::Internal(Cow::Borrowed(
540 "variant field lookup failed",
541 ))
542 })?
543 .ok_or(SerializeError::Internal(Cow::Borrowed(
544 "variant field missing while iterating tuple fields",
545 )))?;
546 shared_serialize(serializer, inner)?;
547 }
548 serializer.end_seq().map_err(SerializeError::Backend)?;
549 }
550 }
551 }
552
553 serializer.end_struct().map_err(SerializeError::Backend)?;
554 return Ok(());
555 }
556 (None, Some(_)) => {
557 return Err(SerializeError::Unsupported(Cow::Borrowed(
558 "adjacent content key set without tag key",
559 )));
560 }
561 (None, None) => {}
562 }
563
564 return match variant.data.kind {
566 StructKind::Unit => {
567 serializer
568 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
569 .map_err(SerializeError::Backend)?;
570 Ok(())
571 }
572 StructKind::TupleStruct | StructKind::Tuple => {
573 serializer.begin_struct().map_err(SerializeError::Backend)?;
574 serializer
575 .field_key(variant.name)
576 .map_err(SerializeError::Backend)?;
577
578 let field_count = variant.data.fields.len();
579 if field_count == 1 {
580 let inner = enum_
581 .field(0)
582 .map_err(|_| {
583 SerializeError::Internal(Cow::Borrowed("variant field lookup failed"))
584 })?
585 .ok_or(SerializeError::Internal(Cow::Borrowed(
586 "variant reported 1 field but field(0) returned None",
587 )))?;
588 shared_serialize(serializer, inner)?;
589 } else {
590 serializer.begin_seq().map_err(SerializeError::Backend)?;
591 for idx in 0..field_count {
592 let inner = enum_
593 .field(idx)
594 .map_err(|_| {
595 SerializeError::Internal(Cow::Borrowed(
596 "variant field lookup failed",
597 ))
598 })?
599 .ok_or(SerializeError::Internal(Cow::Borrowed(
600 "variant field missing while iterating tuple fields",
601 )))?;
602 shared_serialize(serializer, inner)?;
603 }
604 serializer.end_seq().map_err(SerializeError::Backend)?;
605 }
606
607 serializer.end_struct().map_err(SerializeError::Backend)?;
608 Ok(())
609 }
610 StructKind::Struct => {
611 serializer.begin_struct().map_err(SerializeError::Backend)?;
612 serializer
613 .field_key(variant.name)
614 .map_err(SerializeError::Backend)?;
615
616 serializer.begin_struct().map_err(SerializeError::Backend)?;
617 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
618 sort_fields_if_needed(serializer, &mut fields);
619 for (field_item, field_value) in fields {
620 serializer
621 .field_metadata(&field_item)
622 .map_err(SerializeError::Backend)?;
623 serializer
624 .field_key(&field_item.name)
625 .map_err(SerializeError::Backend)?;
626 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
628 serialize_via_proxy(serializer, field_value, proxy_def)?;
629 } else {
630 shared_serialize(serializer, field_value)?;
631 }
632 }
633 serializer.end_struct().map_err(SerializeError::Backend)?;
634
635 serializer.end_struct().map_err(SerializeError::Backend)?;
636 Ok(())
637 }
638 };
639 }
640
641 Err(SerializeError::Unsupported(Cow::Borrowed(
642 "unsupported value kind for serialization",
643 )))
644}
645
646fn serialize_numeric_enum<S>(
647 serializer: &mut S,
648 variant: &'static facet_core::Variant,
649) -> Result<(), SerializeError<S::Error>>
650where
651 S: FormatSerializer,
652{
653 let discriminant = variant
654 .discriminant
655 .ok_or(SerializeError::Unsupported(Cow::Borrowed(
656 "Enum without a discriminant",
657 )))?;
658 serializer
659 .scalar(ScalarValue::I64(discriminant))
660 .map_err(SerializeError::Backend)
661}
662
663fn serialize_untagged_enum<'mem, 'facet, S>(
664 serializer: &mut S,
665 enum_: facet_reflect::PeekEnum<'mem, 'facet>,
666 variant: &'static facet_core::Variant,
667) -> Result<(), SerializeError<S::Error>>
668where
669 S: FormatSerializer,
670{
671 match variant.data.kind {
672 StructKind::Unit => {
673 if variant.name.eq_ignore_ascii_case("null") {
677 return serializer
678 .scalar(ScalarValue::Null)
679 .map_err(SerializeError::Backend);
680 }
681 serializer
682 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
683 .map_err(SerializeError::Backend)
684 }
685 StructKind::TupleStruct | StructKind::Tuple => {
686 let field_count = variant.data.fields.len();
687 if field_count == 1 {
688 let inner = enum_
689 .field(0)
690 .map_err(|_| {
691 SerializeError::Internal(Cow::Borrowed("variant field lookup failed"))
692 })?
693 .ok_or(SerializeError::Internal(Cow::Borrowed(
694 "variant reported 1 field but field(0) returned None",
695 )))?;
696 shared_serialize(serializer, inner)
697 } else {
698 serializer.begin_seq().map_err(SerializeError::Backend)?;
699 for idx in 0..field_count {
700 let inner = enum_
701 .field(idx)
702 .map_err(|_| {
703 SerializeError::Internal(Cow::Borrowed("variant field lookup failed"))
704 })?
705 .ok_or(SerializeError::Internal(Cow::Borrowed(
706 "variant field missing while iterating tuple fields",
707 )))?;
708 shared_serialize(serializer, inner)?;
709 }
710 serializer.end_seq().map_err(SerializeError::Backend)?;
711 Ok(())
712 }
713 }
714 StructKind::Struct => {
715 serializer.begin_struct().map_err(SerializeError::Backend)?;
716 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
717 sort_fields_if_needed(serializer, &mut fields);
718 for (field_item, field_value) in fields {
719 serializer
720 .field_metadata(&field_item)
721 .map_err(SerializeError::Backend)?;
722 serializer
723 .field_key(&field_item.name)
724 .map_err(SerializeError::Backend)?;
725 if let Some(proxy_def) = field_item.field.and_then(|f| f.proxy()) {
727 serialize_via_proxy(serializer, field_value, proxy_def)?;
728 } else {
729 shared_serialize(serializer, field_value)?;
730 }
731 }
732 serializer.end_struct().map_err(SerializeError::Backend)?;
733 Ok(())
734 }
735 }
736}
737
738fn deref_if_pointer<'mem, 'facet>(peek: Peek<'mem, 'facet>) -> Peek<'mem, 'facet> {
740 if let Ok(ptr) = peek.into_pointer()
741 && let Some(target) = ptr.borrow_inner()
742 {
743 return deref_if_pointer(target);
744 }
745 peek
746}
747
748#[allow(unsafe_code)]
756fn serialize_via_proxy<'mem, 'facet, S>(
757 serializer: &mut S,
758 value: Peek<'mem, 'facet>,
759 proxy_def: &'static facet_core::ProxyDef,
760) -> Result<(), SerializeError<S::Error>>
761where
762 S: FormatSerializer,
763{
764 use facet_core::PtrUninit;
765
766 let proxy_shape = proxy_def.shape;
767 let proxy_layout = proxy_shape.layout.sized_layout().map_err(|_| {
768 SerializeError::Unsupported(Cow::Borrowed("proxy type must be sized for serialization"))
769 })?;
770
771 let proxy_mem = unsafe { alloc::alloc::alloc(proxy_layout) };
773 if proxy_mem.is_null() {
774 return Err(SerializeError::Internal(Cow::Borrowed(
775 "failed to allocate proxy memory",
776 )));
777 }
778
779 let proxy_uninit = PtrUninit::new(proxy_mem);
781 let convert_result = unsafe { (proxy_def.convert_out)(value.data(), proxy_uninit) };
782
783 let proxy_ptr = match convert_result {
784 Ok(ptr) => ptr,
785 Err(msg) => {
786 unsafe { alloc::alloc::dealloc(proxy_mem, proxy_layout) };
787 return Err(SerializeError::Unsupported(Cow::Owned(msg)));
788 }
789 };
790
791 let proxy_peek = unsafe { Peek::unchecked_new(proxy_ptr.as_const(), proxy_shape) };
793 let result = shared_serialize(serializer, proxy_peek);
794
795 unsafe {
797 let _ = proxy_shape.call_drop_in_place(proxy_ptr);
798 alloc::alloc::dealloc(proxy_mem, proxy_layout);
799 }
800
801 result
802}