1mod write_scalar;
7
8pub use write_scalar::{ScalarBuffer, WriteScalar};
9
10extern crate alloc;
11
12use std::io::Write;
13
14pub type FloatFormatter = fn(f64, &mut dyn Write) -> std::io::Result<()>;
20
21use alloc::borrow::Cow;
22use alloc::string::String;
23use alloc::vec::Vec;
24use core::fmt::Debug;
25
26use facet_core::{Def, StructKind};
27use facet_reflect::{HasFields as _, Peek, ReflectError};
28
29use crate::naming::to_element_name;
30use crate::trace;
31
32pub trait DomSerializer {
37 type Error: Debug;
39
40 fn element_start(&mut self, tag: &str, namespace: Option<&str>) -> Result<(), Self::Error>;
44
45 fn attribute(
51 &mut self,
52 name: &str,
53 value: Peek<'_, '_>,
54 namespace: Option<&str>,
55 ) -> Result<(), Self::Error>;
56
57 fn children_start(&mut self) -> Result<(), Self::Error>;
59
60 fn children_end(&mut self) -> Result<(), Self::Error>;
62
63 fn element_end(&mut self, tag: &str) -> Result<(), Self::Error>;
65
66 fn text(&mut self, content: &str) -> Result<(), Self::Error>;
68
69 fn comment(&mut self, _content: &str) -> Result<(), Self::Error> {
71 Ok(())
72 }
73
74 fn doctype(&mut self, _content: &str) -> Result<(), Self::Error> {
79 Ok(())
80 }
81
82 fn struct_metadata(&mut self, _shape: &facet_core::Shape) -> Result<(), Self::Error> {
90 Ok(())
91 }
92
93 fn field_metadata(&mut self, _field: &facet_reflect::FieldItem) -> Result<(), Self::Error> {
98 Ok(())
99 }
100
101 fn variant_metadata(
103 &mut self,
104 _variant: &'static facet_core::Variant,
105 ) -> Result<(), Self::Error> {
106 Ok(())
107 }
108
109 fn is_attribute_field(&self) -> bool {
115 false
116 }
117
118 fn is_text_field(&self) -> bool {
120 false
121 }
122
123 fn is_elements_field(&self) -> bool {
125 false
126 }
127
128 fn is_tag_field(&self) -> bool {
130 false
131 }
132
133 fn is_doctype_field(&self) -> bool {
135 false
136 }
137
138 fn clear_field_state(&mut self) {}
140
141 fn format_float(&self, value: f64) -> String {
151 value.to_string()
152 }
153
154 fn serialize_none(&mut self) -> Result<(), Self::Error> {
160 Ok(())
161 }
162
163 fn format_namespace(&self) -> Option<&'static str> {
170 None
171 }
172}
173
174#[derive(Debug)]
176pub enum DomSerializeError<E: Debug> {
177 Backend(E),
179 Reflect(ReflectError),
181 Unsupported(Cow<'static, str>),
183}
184
185impl<E: Debug> core::fmt::Display for DomSerializeError<E> {
186 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
187 match self {
188 DomSerializeError::Backend(_) => f.write_str("DOM serializer error"),
189 DomSerializeError::Reflect(err) => write!(f, "{err}"),
190 DomSerializeError::Unsupported(msg) => f.write_str(msg.as_ref()),
191 }
192 }
193}
194
195impl<E: Debug + 'static> std::error::Error for DomSerializeError<E> {}
196
197pub fn serialize<S>(
199 serializer: &mut S,
200 value: Peek<'_, '_>,
201) -> Result<(), DomSerializeError<S::Error>>
202where
203 S: DomSerializer,
204{
205 serialize_value(serializer, value, None)
206}
207
208fn serialize_value<S>(
210 serializer: &mut S,
211 value: Peek<'_, '_>,
212 element_name: Option<&str>,
213) -> Result<(), DomSerializeError<S::Error>>
214where
215 S: DomSerializer,
216{
217 let value = deref_if_pointer(value);
219 let value = value.innermost_peek();
220
221 if value
223 .shape()
224 .effective_proxy(serializer.format_namespace())
225 .is_some()
226 {
227 return serialize_via_proxy(serializer, value, element_name);
228 }
229
230 if let Some(s) = value_to_string(value, serializer) {
232 if let Some(tag) = element_name {
233 serializer
234 .element_start(tag, None)
235 .map_err(DomSerializeError::Backend)?;
236 serializer
237 .children_start()
238 .map_err(DomSerializeError::Backend)?;
239 serializer.text(&s).map_err(DomSerializeError::Backend)?;
240 serializer
241 .children_end()
242 .map_err(DomSerializeError::Backend)?;
243 serializer
244 .element_end(tag)
245 .map_err(DomSerializeError::Backend)?;
246 } else {
247 serializer.text(&s).map_err(DomSerializeError::Backend)?;
248 }
249 return Ok(());
250 }
251
252 if let Ok(opt) = value.into_option() {
254 return match opt.value() {
255 Some(inner) => serialize_value(serializer, inner, element_name),
256 None => serializer
257 .serialize_none()
258 .map_err(DomSerializeError::Backend),
259 };
260 }
261
262 if let Def::List(_) | Def::Array(_) | Def::Slice(_) = value.shape().def {
265 let list = value.into_list_like().map_err(DomSerializeError::Reflect)?;
266
267 for item in list.iter() {
268 serialize_value(serializer, item, element_name)?;
270 }
271
272 return Ok(());
273 }
274
275 if let Ok(map) = value.into_map() {
277 if let Some(tag) = element_name {
278 serializer
279 .element_start(tag, None)
280 .map_err(DomSerializeError::Backend)?;
281 serializer
282 .children_start()
283 .map_err(DomSerializeError::Backend)?;
284 }
285
286 for (key, val) in map.iter() {
287 let key_str = if let Some(s) = key.as_str() {
288 Cow::Borrowed(s)
289 } else {
290 Cow::Owned(alloc::format!("{}", key))
291 };
292 serialize_value(serializer, val, Some(&key_str))?;
293 }
294
295 if let Some(tag) = element_name {
296 serializer
297 .children_end()
298 .map_err(DomSerializeError::Backend)?;
299 serializer
300 .element_end(tag)
301 .map_err(DomSerializeError::Backend)?;
302 }
303
304 return Ok(());
305 }
306
307 if let Ok(set) = value.into_set() {
311 for item in set.iter() {
312 serialize_value(serializer, item, element_name)?;
314 }
315
316 return Ok(());
317 }
318
319 if let Ok(struct_) = value.into_struct() {
321 let kind = struct_.ty().kind;
322
323 if kind == StructKind::Tuple || kind == StructKind::TupleStruct {
326 for (_field_item, field_value) in struct_.fields_for_serialize() {
327 serialize_value(serializer, field_value, element_name)?;
328 }
329 return Ok(());
330 }
331
332 trace!(type_id = %value.shape().type_identifier, "serializing struct");
334 serializer
335 .struct_metadata(value.shape())
336 .map_err(DomSerializeError::Backend)?;
337
338 let fields: Vec<_> = struct_.fields_for_serialize().collect();
340
341 let (tag_field_value, doctype_field_value): (Option<String>, Option<String>) = {
344 let mut tag_result = None;
345 let mut doctype_result = None;
346 for (field_item, field_value) in &fields {
347 serializer
348 .field_metadata(field_item)
349 .map_err(DomSerializeError::Backend)?;
350 if serializer.is_tag_field() {
351 if let Some(s) = field_value.as_str() {
353 tag_result = Some(s.to_string());
354 } else if let Some(s) = value_to_string(*field_value, serializer) {
355 tag_result = Some(s);
356 }
357 } else if serializer.is_doctype_field() {
358 if let Some(s) = field_value.as_str() {
360 doctype_result = Some(s.to_string());
361 } else if let Some(s) = value_to_string(*field_value, serializer) {
362 doctype_result = Some(s);
363 }
364 }
365 serializer.clear_field_state();
366 }
367 (tag_result, doctype_result)
368 };
369
370 let tag: Cow<'_, str> = if let Some(ref tag_value) = tag_field_value {
372 Cow::Owned(tag_value.clone())
373 } else if let Some(name) = element_name {
374 Cow::Borrowed(name)
375 } else if let Some(rename) = value.shape().get_builtin_attr_value::<&str>("rename") {
376 Cow::Borrowed(rename)
377 } else {
378 to_element_name(value.shape().type_identifier)
380 };
381 trace!(tag = %tag, "element_start");
382
383 if let Some(ref doctype_value) = doctype_field_value {
385 trace!(doctype = %doctype_value, "emitting doctype");
386 serializer
387 .doctype(doctype_value)
388 .map_err(DomSerializeError::Backend)?;
389 }
390
391 serializer
392 .element_start(&tag, None)
393 .map_err(DomSerializeError::Backend)?;
394
395 trace!(field_count = fields.len(), "collected fields for serialize");
397
398 for (field_item, field_value) in &fields {
400 trace!(field_name = %field_item.name, "processing field for attributes");
401 serializer
402 .field_metadata(field_item)
403 .map_err(DomSerializeError::Backend)?;
404
405 let is_attr = serializer.is_attribute_field();
406 trace!(field_name = %field_item.name, is_attribute = is_attr, "field_metadata result");
407
408 if is_attr {
409 trace!(field_name = %field_item.name, "attribute field");
410 let attr_name = if let Some(field) = field_item.field {
413 field
414 .rename
415 .map(Cow::Borrowed)
416 .unwrap_or_else(|| to_element_name(&field_item.name))
417 } else {
418 field_item.name.clone()
420 };
421
422 let format_ns = serializer.format_namespace();
424 let proxy_def = field_item
425 .field
426 .and_then(|f| f.effective_proxy(format_ns))
427 .or_else(|| field_value.shape().effective_proxy(format_ns));
428
429 if let Some(proxy_def) = proxy_def {
430 match field_value.custom_serialization_with_proxy(proxy_def) {
431 Ok(proxy_peek) => {
432 serializer
433 .attribute(&attr_name, proxy_peek.as_peek(), None)
434 .map_err(DomSerializeError::Backend)?;
435 }
436 Err(e) => {
437 return Err(DomSerializeError::Reflect(e));
438 }
439 }
440 } else {
441 serializer
442 .attribute(&attr_name, *field_value, None)
443 .map_err(DomSerializeError::Backend)?;
444 }
445 serializer.clear_field_state();
446 }
447 }
448
449 trace!("children_start");
450 serializer
451 .children_start()
452 .map_err(DomSerializeError::Backend)?;
453
454 for (field_item, field_value) in &fields {
456 serializer
457 .field_metadata(field_item)
458 .map_err(DomSerializeError::Backend)?;
459
460 if serializer.is_attribute_field() {
461 serializer.clear_field_state();
462 continue;
463 }
464
465 if serializer.is_tag_field() {
467 serializer.clear_field_state();
468 continue;
469 }
470
471 if serializer.is_doctype_field() {
473 serializer.clear_field_state();
474 continue;
475 }
476
477 if serializer.is_text_field() {
478 if let Some(s) = value_to_string(*field_value, serializer) {
479 serializer.text(&s).map_err(DomSerializeError::Backend)?;
480 }
481 serializer.clear_field_state();
482 continue;
483 }
484
485 let is_elements = serializer.is_elements_field();
488 let explicit_rename = field_item.field.and_then(|f| f.rename);
489
490 let is_flattened = field_item.flattened;
494
495 if field_item.is_text_variant {
498 if let Some(s) = value_to_string(*field_value, serializer) {
499 serializer.text(&s).map_err(DomSerializeError::Backend)?;
500 }
501 serializer.clear_field_state();
502 continue;
503 }
504
505 let field_element_name: Option<Cow<'_, str>> =
507 if is_elements && explicit_rename.is_none() {
508 None } else if is_flattened {
510 Some(to_element_name(field_item.effective_name()))
514 } else if let Some(rename) = explicit_rename {
515 Some(Cow::Borrowed(rename))
517 } else {
518 Some(to_element_name(&field_item.name))
520 };
521
522 let format_ns = serializer.format_namespace();
524 let proxy_def = field_item
525 .field
526 .and_then(|f| f.effective_proxy(format_ns))
527 .or_else(|| field_value.shape().effective_proxy(format_ns));
528
529 if let Some(proxy_def) = proxy_def {
530 match field_value.custom_serialization_with_proxy(proxy_def) {
532 Ok(proxy_peek) => {
533 serialize_value(
534 serializer,
535 proxy_peek.as_peek(),
536 field_element_name.as_deref(),
537 )?;
538 }
539 Err(e) => {
540 return Err(DomSerializeError::Reflect(e));
541 }
542 }
543 } else {
544 serialize_value(serializer, *field_value, field_element_name.as_deref())?;
545 }
546
547 serializer.clear_field_state();
548 }
549
550 serializer
551 .children_end()
552 .map_err(DomSerializeError::Backend)?;
553 serializer
554 .element_end(&tag)
555 .map_err(DomSerializeError::Backend)?;
556
557 return Ok(());
558 }
559
560 if let Ok(enum_) = value.into_enum() {
562 let variant = enum_.active_variant().map_err(|_| {
563 DomSerializeError::Unsupported(Cow::Borrowed("opaque enum layout is unsupported"))
564 })?;
565
566 serializer
567 .variant_metadata(variant)
568 .map_err(DomSerializeError::Backend)?;
569
570 let untagged = value.shape().is_untagged();
571 let tag_attr = value.shape().get_tag_attr();
572 let content_attr = value.shape().get_content_attr();
573
574 if variant.data.kind == StructKind::Unit {
576 let variant_name: Cow<'_, str> = variant
577 .get_builtin_attr("rename")
578 .and_then(|a| a.get_as::<&str>().copied())
579 .map(Cow::Borrowed)
580 .unwrap_or_else(|| to_element_name(variant.name));
581
582 if untagged {
583 serializer
584 .text(&variant_name)
585 .map_err(DomSerializeError::Backend)?;
586 } else if let Some(tag) = element_name {
587 serializer
588 .element_start(tag, None)
589 .map_err(DomSerializeError::Backend)?;
590 serializer
591 .children_start()
592 .map_err(DomSerializeError::Backend)?;
593 serializer
594 .text(&variant_name)
595 .map_err(DomSerializeError::Backend)?;
596 serializer
597 .children_end()
598 .map_err(DomSerializeError::Backend)?;
599 serializer
600 .element_end(tag)
601 .map_err(DomSerializeError::Backend)?;
602 } else {
603 serializer
604 .text(&variant_name)
605 .map_err(DomSerializeError::Backend)?;
606 }
607 return Ok(());
608 }
609
610 if variant.data.kind == StructKind::TupleStruct && variant.data.fields.len() == 1 {
612 let inner = enum_
613 .fields_for_serialize()
614 .next()
615 .map(|(_, v)| v)
616 .ok_or_else(|| {
617 DomSerializeError::Unsupported(Cow::Borrowed("newtype variant missing field"))
618 })?;
619
620 if variant.is_text() {
622 if let Some(s) = value_to_string(inner, serializer) {
623 serializer.text(&s).map_err(DomSerializeError::Backend)?;
624 }
625 return Ok(());
626 }
627
628 if untagged {
629 return serialize_value(serializer, inner, element_name);
630 }
631
632 let variant_name: Cow<'_, str> = variant
633 .get_builtin_attr("rename")
634 .and_then(|a| a.get_as::<&str>().copied())
635 .map(Cow::Borrowed)
636 .unwrap_or_else(|| to_element_name(variant.name));
637
638 if let Some(outer_tag) = element_name {
640 serializer
641 .element_start(outer_tag, None)
642 .map_err(DomSerializeError::Backend)?;
643 serializer
644 .children_start()
645 .map_err(DomSerializeError::Backend)?;
646 }
647
648 serialize_value(serializer, inner, Some(&variant_name))?;
649
650 if let Some(outer_tag) = element_name {
651 serializer
652 .children_end()
653 .map_err(DomSerializeError::Backend)?;
654 serializer
655 .element_end(outer_tag)
656 .map_err(DomSerializeError::Backend)?;
657 }
658
659 return Ok(());
660 }
661
662 let variant_name: Cow<'_, str> = variant
664 .get_builtin_attr("rename")
665 .and_then(|a| a.get_as::<&str>().copied())
666 .map(Cow::Borrowed)
667 .unwrap_or_else(|| to_element_name(variant.name));
668
669 match (tag_attr, content_attr) {
670 (Some(tag_key), None) => {
672 let tag = element_name.unwrap_or("value");
673 serializer
674 .element_start(tag, None)
675 .map_err(DomSerializeError::Backend)?;
676 serializer
677 .children_start()
678 .map_err(DomSerializeError::Backend)?;
679
680 serializer
682 .element_start(tag_key, None)
683 .map_err(DomSerializeError::Backend)?;
684 serializer
685 .children_start()
686 .map_err(DomSerializeError::Backend)?;
687 serializer
688 .text(&variant_name)
689 .map_err(DomSerializeError::Backend)?;
690 serializer
691 .children_end()
692 .map_err(DomSerializeError::Backend)?;
693 serializer
694 .element_end(tag_key)
695 .map_err(DomSerializeError::Backend)?;
696
697 serialize_enum_variant_fields(serializer, enum_)?;
699
700 serializer
701 .children_end()
702 .map_err(DomSerializeError::Backend)?;
703 serializer
704 .element_end(tag)
705 .map_err(DomSerializeError::Backend)?;
706 }
707
708 (Some(tag_key), Some(content_key)) => {
710 let tag = element_name.unwrap_or("value");
711 serializer
712 .element_start(tag, None)
713 .map_err(DomSerializeError::Backend)?;
714 serializer
715 .children_start()
716 .map_err(DomSerializeError::Backend)?;
717
718 serializer
720 .element_start(tag_key, None)
721 .map_err(DomSerializeError::Backend)?;
722 serializer
723 .children_start()
724 .map_err(DomSerializeError::Backend)?;
725 serializer
726 .text(&variant_name)
727 .map_err(DomSerializeError::Backend)?;
728 serializer
729 .children_end()
730 .map_err(DomSerializeError::Backend)?;
731 serializer
732 .element_end(tag_key)
733 .map_err(DomSerializeError::Backend)?;
734
735 serializer
737 .element_start(content_key, None)
738 .map_err(DomSerializeError::Backend)?;
739 serializer
740 .children_start()
741 .map_err(DomSerializeError::Backend)?;
742 serialize_enum_variant_fields(serializer, enum_)?;
743 serializer
744 .children_end()
745 .map_err(DomSerializeError::Backend)?;
746 serializer
747 .element_end(content_key)
748 .map_err(DomSerializeError::Backend)?;
749
750 serializer
751 .children_end()
752 .map_err(DomSerializeError::Backend)?;
753 serializer
754 .element_end(tag)
755 .map_err(DomSerializeError::Backend)?;
756 }
757
758 _ => {
760 if untagged {
761 let tag = element_name.unwrap_or("value");
763 serializer
764 .element_start(tag, None)
765 .map_err(DomSerializeError::Backend)?;
766 serialize_enum_variant_fields(serializer, enum_)?;
767 serializer
768 .children_end()
769 .map_err(DomSerializeError::Backend)?;
770 serializer
771 .element_end(tag)
772 .map_err(DomSerializeError::Backend)?;
773 } else {
774 if let Some(outer_tag) = element_name {
776 serializer
777 .element_start(outer_tag, None)
778 .map_err(DomSerializeError::Backend)?;
779 serializer
780 .children_start()
781 .map_err(DomSerializeError::Backend)?;
782 }
783
784 serializer
785 .element_start(&variant_name, None)
786 .map_err(DomSerializeError::Backend)?;
787 serialize_enum_variant_fields(serializer, enum_)?;
788 serializer
789 .children_end()
790 .map_err(DomSerializeError::Backend)?;
791 serializer
792 .element_end(&variant_name)
793 .map_err(DomSerializeError::Backend)?;
794
795 if let Some(outer_tag) = element_name {
796 serializer
797 .children_end()
798 .map_err(DomSerializeError::Backend)?;
799 serializer
800 .element_end(outer_tag)
801 .map_err(DomSerializeError::Backend)?;
802 }
803 }
804 }
805 }
806
807 return Ok(());
808 }
809
810 Err(DomSerializeError::Unsupported(Cow::Owned(alloc::format!(
811 "unsupported type: {:?}",
812 value.shape().def
813 ))))
814}
815
816fn serialize_enum_variant_fields<S>(
822 serializer: &mut S,
823 enum_: facet_reflect::PeekEnum<'_, '_>,
824) -> Result<(), DomSerializeError<S::Error>>
825where
826 S: DomSerializer,
827{
828 let fields: Vec<_> = enum_.fields_for_serialize().collect();
830
831 for (field_item, field_value) in &fields {
833 serializer
834 .field_metadata(field_item)
835 .map_err(DomSerializeError::Backend)?;
836
837 if serializer.is_attribute_field() {
838 let attr_name = if let Some(field) = field_item.field {
840 field
841 .rename
842 .map(Cow::Borrowed)
843 .unwrap_or_else(|| to_element_name(&field_item.name))
844 } else {
845 field_item.name.clone()
846 };
847
848 let format_ns = serializer.format_namespace();
850 let proxy_def = field_item
851 .field
852 .and_then(|f| f.effective_proxy(format_ns))
853 .or_else(|| field_value.shape().effective_proxy(format_ns));
854
855 if let Some(proxy_def) = proxy_def {
856 match field_value.custom_serialization_with_proxy(proxy_def) {
857 Ok(proxy_peek) => {
858 serializer
859 .attribute(&attr_name, proxy_peek.as_peek(), None)
860 .map_err(DomSerializeError::Backend)?;
861 }
862 Err(e) => {
863 return Err(DomSerializeError::Reflect(e));
864 }
865 }
866 } else {
867 serializer
868 .attribute(&attr_name, *field_value, None)
869 .map_err(DomSerializeError::Backend)?;
870 }
871 }
872 serializer.clear_field_state();
873 }
874
875 serializer
877 .children_start()
878 .map_err(DomSerializeError::Backend)?;
879
880 for (field_item, field_value) in &fields {
882 serializer
883 .field_metadata(field_item)
884 .map_err(DomSerializeError::Backend)?;
885
886 if serializer.is_attribute_field() {
888 serializer.clear_field_state();
889 continue;
890 }
891
892 if serializer.is_tag_field() {
894 serializer.clear_field_state();
895 continue;
896 }
897
898 if serializer.is_doctype_field() {
900 serializer.clear_field_state();
901 continue;
902 }
903
904 if serializer.is_text_field() {
906 if let Some(s) = value_to_string(*field_value, serializer) {
907 serializer.text(&s).map_err(DomSerializeError::Backend)?;
908 }
909 serializer.clear_field_state();
910 continue;
911 }
912
913 if field_item.is_text_variant {
915 if let Some(s) = value_to_string(*field_value, serializer) {
916 serializer.text(&s).map_err(DomSerializeError::Backend)?;
917 }
918 serializer.clear_field_state();
919 continue;
920 }
921
922 let is_elements = serializer.is_elements_field();
924 let explicit_rename = field_item.field.and_then(|f| f.rename);
925 let is_flattened = field_item.flattened;
926
927 let field_element_name: Option<Cow<'_, str>> = if is_elements && explicit_rename.is_none() {
928 None } else if is_flattened {
930 None
932 } else if let Some(rename) = explicit_rename {
933 Some(Cow::Borrowed(rename))
934 } else {
935 Some(to_element_name(&field_item.name))
936 };
937
938 let format_ns = serializer.format_namespace();
940 let proxy_def = field_item
941 .field
942 .and_then(|f| f.effective_proxy(format_ns))
943 .or_else(|| field_value.shape().effective_proxy(format_ns));
944
945 if let Some(proxy_def) = proxy_def {
946 match field_value.custom_serialization_with_proxy(proxy_def) {
947 Ok(proxy_peek) => {
948 serialize_value(
949 serializer,
950 proxy_peek.as_peek(),
951 field_element_name.as_deref(),
952 )?;
953 }
954 Err(e) => {
955 return Err(DomSerializeError::Reflect(e));
956 }
957 }
958 } else {
959 serialize_value(serializer, *field_value, field_element_name.as_deref())?;
960 }
961
962 serializer.clear_field_state();
963 }
964
965 Ok(())
966}
967
968fn serialize_via_proxy<S>(
970 serializer: &mut S,
971 value: Peek<'_, '_>,
972 element_name: Option<&str>,
973) -> Result<(), DomSerializeError<S::Error>>
974where
975 S: DomSerializer,
976{
977 let owned_peek = value
980 .custom_serialization_from_shape_with_format(serializer.format_namespace())
981 .map_err(DomSerializeError::Reflect)?;
982
983 match owned_peek {
984 Some(proxy_peek) => {
985 serialize_value(serializer, proxy_peek.as_peek(), element_name)
987 }
988 None => {
989 Err(DomSerializeError::Unsupported(Cow::Borrowed(
991 "proxy serialization failed: no proxy on shape",
992 )))
993 }
994 }
995}
996
997fn deref_if_pointer<'mem, 'facet>(value: Peek<'mem, 'facet>) -> Peek<'mem, 'facet> {
999 if let Ok(ptr) = value.into_pointer()
1000 && let Some(inner) = ptr.borrow_inner()
1001 {
1002 return deref_if_pointer(inner);
1003 }
1004 value
1005}
1006
1007fn value_to_string<S: DomSerializer>(value: Peek<'_, '_>, serializer: &S) -> Option<String> {
1009 use facet_core::ScalarType;
1010
1011 if let Def::Option(_) = &value.shape().def
1013 && let Ok(opt) = value.into_option()
1014 {
1015 return match opt.value() {
1016 Some(inner) => value_to_string(inner, serializer),
1017 None => None,
1018 };
1019 }
1020
1021 if let Some(scalar_type) = value.scalar_type() {
1022 let s = match scalar_type {
1023 ScalarType::Unit => return Some("null".into()),
1024 ScalarType::Bool => if *value.get::<bool>().ok()? {
1025 "true"
1026 } else {
1027 "false"
1028 }
1029 .into(),
1030 ScalarType::Char => value.get::<char>().ok()?.to_string(),
1031 ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
1032 value.as_str()?.to_string()
1033 }
1034 ScalarType::F32 => serializer.format_float(*value.get::<f32>().ok()? as f64),
1035 ScalarType::F64 => serializer.format_float(*value.get::<f64>().ok()?),
1036 ScalarType::U8 => value.get::<u8>().ok()?.to_string(),
1037 ScalarType::U16 => value.get::<u16>().ok()?.to_string(),
1038 ScalarType::U32 => value.get::<u32>().ok()?.to_string(),
1039 ScalarType::U64 => value.get::<u64>().ok()?.to_string(),
1040 ScalarType::U128 => value.get::<u128>().ok()?.to_string(),
1041 ScalarType::USize => value.get::<usize>().ok()?.to_string(),
1042 ScalarType::I8 => value.get::<i8>().ok()?.to_string(),
1043 ScalarType::I16 => value.get::<i16>().ok()?.to_string(),
1044 ScalarType::I32 => value.get::<i32>().ok()?.to_string(),
1045 ScalarType::I64 => value.get::<i64>().ok()?.to_string(),
1046 ScalarType::I128 => value.get::<i128>().ok()?.to_string(),
1047 ScalarType::ISize => value.get::<isize>().ok()?.to_string(),
1048 #[cfg(feature = "net")]
1049 ScalarType::IpAddr => value.get::<core::net::IpAddr>().ok()?.to_string(),
1050 #[cfg(feature = "net")]
1051 ScalarType::Ipv4Addr => value.get::<core::net::Ipv4Addr>().ok()?.to_string(),
1052 #[cfg(feature = "net")]
1053 ScalarType::Ipv6Addr => value.get::<core::net::Ipv6Addr>().ok()?.to_string(),
1054 #[cfg(feature = "net")]
1055 ScalarType::SocketAddr => value.get::<core::net::SocketAddr>().ok()?.to_string(),
1056 _ => return None,
1057 };
1058 return Some(s);
1059 }
1060
1061 if matches!(value.shape().def, Def::Scalar) && value.shape().vtable.has_display() {
1063 return Some(alloc::format!("{}", value));
1064 }
1065
1066 None
1067}