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 {
328 for (_field_item, field_value) in struct_.fields_for_serialize() {
329 serialize_value(serializer, field_value, element_name)?;
330 }
331 return Ok(());
332 }
333
334 trace!(type_id = %value.shape().type_identifier, "serializing struct");
336 serializer
337 .struct_metadata(value.shape())
338 .map_err(DomSerializeError::Backend)?;
339
340 let fields: Vec<_> = struct_.fields_for_serialize().collect();
342
343 let (tag_field_value, doctype_field_value): (Option<String>, Option<String>) = {
346 let mut tag_result = None;
347 let mut doctype_result = None;
348 for (field_item, field_value) in &fields {
349 serializer
350 .field_metadata(field_item)
351 .map_err(DomSerializeError::Backend)?;
352 if serializer.is_tag_field() {
353 if let Some(s) = field_value.as_str() {
355 tag_result = Some(s.to_string());
356 } else if let Some(s) = value_to_string(*field_value, serializer) {
357 tag_result = Some(s);
358 }
359 } else if serializer.is_doctype_field() {
360 if let Some(s) = field_value.as_str() {
362 doctype_result = Some(s.to_string());
363 } else if let Some(s) = value_to_string(*field_value, serializer) {
364 doctype_result = Some(s);
365 }
366 }
367 serializer.clear_field_state();
368 }
369 (tag_result, doctype_result)
370 };
371
372 let tag: Cow<'_, str> = if let Some(ref tag_value) = tag_field_value {
374 Cow::Owned(tag_value.clone())
375 } else if let Some(name) = element_name {
376 Cow::Borrowed(name)
377 } else if let Some(rename) = value.shape().get_builtin_attr_value::<&str>("rename") {
378 Cow::Borrowed(rename)
379 } else if let Some(rename_all) = value.shape().get_builtin_attr_value::<&str>("rename_all")
380 {
381 Cow::Owned(crate::naming::apply_rename_all(
382 value.shape().type_identifier,
383 rename_all,
384 ))
385 } else {
386 to_element_name(value.shape().type_identifier)
388 };
389 trace!(tag = %tag, "element_start");
390
391 if let Some(ref doctype_value) = doctype_field_value {
393 trace!(doctype = %doctype_value, "emitting doctype");
394 serializer
395 .doctype(doctype_value)
396 .map_err(DomSerializeError::Backend)?;
397 }
398
399 serializer
400 .element_start(&tag, None)
401 .map_err(DomSerializeError::Backend)?;
402
403 trace!(field_count = fields.len(), "collected fields for serialize");
405
406 for (field_item, field_value) in &fields {
408 trace!(field_name = %field_item.name, "processing field for attributes");
409 serializer
410 .field_metadata(field_item)
411 .map_err(DomSerializeError::Backend)?;
412
413 let is_attr = serializer.is_attribute_field();
414 trace!(field_name = %field_item.name, is_attribute = is_attr, "field_metadata result");
415
416 if is_attr {
417 trace!(field_name = %field_item.name, "attribute field");
418 let attr_name = if let Some(field) = field_item.field {
421 field
422 .rename
423 .map(Cow::Borrowed)
424 .unwrap_or_else(|| to_element_name(&field_item.name))
425 } else {
426 field_item.name.clone()
428 };
429
430 let format_ns = serializer.format_namespace();
432 let proxy_def = field_item
433 .field
434 .and_then(|f| f.effective_proxy(format_ns))
435 .or_else(|| field_value.shape().effective_proxy(format_ns));
436
437 if let Some(proxy_def) = proxy_def {
438 match field_value.custom_serialization_with_proxy(proxy_def) {
439 Ok(proxy_peek) => {
440 serializer
441 .attribute(&attr_name, proxy_peek.as_peek(), None)
442 .map_err(DomSerializeError::Backend)?;
443 }
444 Err(e) => {
445 return Err(DomSerializeError::Reflect(e));
446 }
447 }
448 } else {
449 serializer
450 .attribute(&attr_name, *field_value, None)
451 .map_err(DomSerializeError::Backend)?;
452 }
453 serializer.clear_field_state();
454 }
455 }
456
457 trace!("children_start");
458 serializer
459 .children_start()
460 .map_err(DomSerializeError::Backend)?;
461
462 for (field_item, field_value) in &fields {
464 serializer
465 .field_metadata(field_item)
466 .map_err(DomSerializeError::Backend)?;
467
468 if serializer.is_attribute_field() {
469 serializer.clear_field_state();
470 continue;
471 }
472
473 if serializer.is_tag_field() {
475 serializer.clear_field_state();
476 continue;
477 }
478
479 if serializer.is_doctype_field() {
481 serializer.clear_field_state();
482 continue;
483 }
484
485 if serializer.is_text_field() {
486 if let Some(s) = value_to_string(*field_value, serializer) {
487 serializer.text(&s).map_err(DomSerializeError::Backend)?;
488 }
489 serializer.clear_field_state();
490 continue;
491 }
492
493 let is_elements = serializer.is_elements_field();
496 let explicit_rename = field_item.field.and_then(|f| f.rename);
497
498 let is_flattened = field_item.flattened;
502
503 if field_item.is_text_variant {
506 if let Some(s) = value_to_string(*field_value, serializer) {
507 serializer.text(&s).map_err(DomSerializeError::Backend)?;
508 }
509 serializer.clear_field_state();
510 continue;
511 }
512
513 let field_element_name: Option<Cow<'_, str>> =
515 if is_elements && explicit_rename.is_none() {
516 None } else if is_flattened {
518 Some(to_element_name(field_item.effective_name()))
522 } else if let Some(rename) = explicit_rename {
523 Some(Cow::Borrowed(rename))
525 } else {
526 Some(to_element_name(&field_item.name))
528 };
529
530 let format_ns = serializer.format_namespace();
532 let proxy_def = field_item
533 .field
534 .and_then(|f| f.effective_proxy(format_ns))
535 .or_else(|| field_value.shape().effective_proxy(format_ns));
536
537 if let Some(proxy_def) = proxy_def {
538 match field_value.custom_serialization_with_proxy(proxy_def) {
540 Ok(proxy_peek) => {
541 serialize_value(
542 serializer,
543 proxy_peek.as_peek(),
544 field_element_name.as_deref(),
545 )?;
546 }
547 Err(e) => {
548 return Err(DomSerializeError::Reflect(e));
549 }
550 }
551 } else {
552 serialize_value(serializer, *field_value, field_element_name.as_deref())?;
553 }
554
555 serializer.clear_field_state();
556 }
557
558 serializer
559 .children_end()
560 .map_err(DomSerializeError::Backend)?;
561 serializer
562 .element_end(&tag)
563 .map_err(DomSerializeError::Backend)?;
564
565 return Ok(());
566 }
567
568 if let Ok(enum_) = value.into_enum() {
570 let variant = enum_.active_variant().map_err(|_| {
571 DomSerializeError::Unsupported(Cow::Borrowed("opaque enum layout is unsupported"))
572 })?;
573
574 serializer
575 .variant_metadata(variant)
576 .map_err(DomSerializeError::Backend)?;
577
578 let untagged = value.shape().is_untagged();
579 let tag_attr = value.shape().get_tag_attr();
580 let content_attr = value.shape().get_content_attr();
581
582 if variant.data.kind == StructKind::Unit {
584 let variant_name: Cow<'_, str> = if variant.rename.is_some() {
586 Cow::Borrowed(variant.effective_name())
587 } else {
588 to_element_name(variant.name)
589 };
590
591 if untagged {
592 serializer
593 .text(&variant_name)
594 .map_err(DomSerializeError::Backend)?;
595 } else if let Some(tag) = element_name {
596 serializer
597 .element_start(tag, None)
598 .map_err(DomSerializeError::Backend)?;
599 serializer
600 .children_start()
601 .map_err(DomSerializeError::Backend)?;
602 serializer
603 .text(&variant_name)
604 .map_err(DomSerializeError::Backend)?;
605 serializer
606 .children_end()
607 .map_err(DomSerializeError::Backend)?;
608 serializer
609 .element_end(tag)
610 .map_err(DomSerializeError::Backend)?;
611 } else {
612 serializer
613 .text(&variant_name)
614 .map_err(DomSerializeError::Backend)?;
615 }
616 return Ok(());
617 }
618
619 if variant.data.kind == StructKind::TupleStruct && variant.data.fields.len() == 1 {
621 let inner = enum_
622 .fields_for_serialize()
623 .next()
624 .map(|(_, v)| v)
625 .ok_or_else(|| {
626 DomSerializeError::Unsupported(Cow::Borrowed("newtype variant missing field"))
627 })?;
628
629 if variant.is_text() {
631 if let Some(s) = value_to_string(inner, serializer) {
632 serializer.text(&s).map_err(DomSerializeError::Backend)?;
633 }
634 return Ok(());
635 }
636
637 if untagged {
638 return serialize_value(serializer, inner, element_name);
639 }
640
641 let variant_name: Cow<'_, str> = if variant.rename.is_some() {
643 Cow::Borrowed(variant.effective_name())
644 } else {
645 to_element_name(variant.name)
646 };
647
648 if let Some(outer_tag) = element_name {
650 serializer
651 .element_start(outer_tag, None)
652 .map_err(DomSerializeError::Backend)?;
653 serializer
654 .children_start()
655 .map_err(DomSerializeError::Backend)?;
656 }
657
658 serialize_value(serializer, inner, Some(&variant_name))?;
659
660 if let Some(outer_tag) = element_name {
661 serializer
662 .children_end()
663 .map_err(DomSerializeError::Backend)?;
664 serializer
665 .element_end(outer_tag)
666 .map_err(DomSerializeError::Backend)?;
667 }
668
669 return Ok(());
670 }
671
672 let variant_name: Cow<'_, str> = if variant.rename.is_some() {
675 Cow::Borrowed(variant.effective_name())
676 } else {
677 to_element_name(variant.name)
678 };
679
680 match (tag_attr, content_attr) {
681 (Some(tag_key), None) => {
683 let tag = element_name.unwrap_or("value");
684 serializer
685 .element_start(tag, None)
686 .map_err(DomSerializeError::Backend)?;
687 serializer
688 .children_start()
689 .map_err(DomSerializeError::Backend)?;
690
691 serializer
693 .element_start(tag_key, None)
694 .map_err(DomSerializeError::Backend)?;
695 serializer
696 .children_start()
697 .map_err(DomSerializeError::Backend)?;
698 serializer
699 .text(&variant_name)
700 .map_err(DomSerializeError::Backend)?;
701 serializer
702 .children_end()
703 .map_err(DomSerializeError::Backend)?;
704 serializer
705 .element_end(tag_key)
706 .map_err(DomSerializeError::Backend)?;
707
708 serialize_enum_variant_fields(serializer, enum_)?;
710
711 serializer
712 .children_end()
713 .map_err(DomSerializeError::Backend)?;
714 serializer
715 .element_end(tag)
716 .map_err(DomSerializeError::Backend)?;
717 }
718
719 (Some(tag_key), Some(content_key)) => {
721 let tag = element_name.unwrap_or("value");
722 serializer
723 .element_start(tag, None)
724 .map_err(DomSerializeError::Backend)?;
725 serializer
726 .children_start()
727 .map_err(DomSerializeError::Backend)?;
728
729 serializer
731 .element_start(tag_key, None)
732 .map_err(DomSerializeError::Backend)?;
733 serializer
734 .children_start()
735 .map_err(DomSerializeError::Backend)?;
736 serializer
737 .text(&variant_name)
738 .map_err(DomSerializeError::Backend)?;
739 serializer
740 .children_end()
741 .map_err(DomSerializeError::Backend)?;
742 serializer
743 .element_end(tag_key)
744 .map_err(DomSerializeError::Backend)?;
745
746 serializer
748 .element_start(content_key, None)
749 .map_err(DomSerializeError::Backend)?;
750 serializer
751 .children_start()
752 .map_err(DomSerializeError::Backend)?;
753 serialize_enum_variant_fields(serializer, enum_)?;
754 serializer
755 .children_end()
756 .map_err(DomSerializeError::Backend)?;
757 serializer
758 .element_end(content_key)
759 .map_err(DomSerializeError::Backend)?;
760
761 serializer
762 .children_end()
763 .map_err(DomSerializeError::Backend)?;
764 serializer
765 .element_end(tag)
766 .map_err(DomSerializeError::Backend)?;
767 }
768
769 _ => {
771 if untagged {
772 let tag = element_name.unwrap_or("value");
774 serializer
775 .element_start(tag, None)
776 .map_err(DomSerializeError::Backend)?;
777 serialize_enum_variant_fields(serializer, enum_)?;
778 serializer
779 .children_end()
780 .map_err(DomSerializeError::Backend)?;
781 serializer
782 .element_end(tag)
783 .map_err(DomSerializeError::Backend)?;
784 } else {
785 if let Some(outer_tag) = element_name {
787 serializer
788 .element_start(outer_tag, None)
789 .map_err(DomSerializeError::Backend)?;
790 serializer
791 .children_start()
792 .map_err(DomSerializeError::Backend)?;
793 }
794
795 serializer
796 .element_start(&variant_name, None)
797 .map_err(DomSerializeError::Backend)?;
798 serialize_enum_variant_fields(serializer, enum_)?;
799 serializer
800 .children_end()
801 .map_err(DomSerializeError::Backend)?;
802 serializer
803 .element_end(&variant_name)
804 .map_err(DomSerializeError::Backend)?;
805
806 if let Some(outer_tag) = element_name {
807 serializer
808 .children_end()
809 .map_err(DomSerializeError::Backend)?;
810 serializer
811 .element_end(outer_tag)
812 .map_err(DomSerializeError::Backend)?;
813 }
814 }
815 }
816 }
817
818 return Ok(());
819 }
820
821 Err(DomSerializeError::Unsupported(Cow::Owned(alloc::format!(
822 "unsupported type: {:?}",
823 value.shape().def
824 ))))
825}
826
827fn serialize_enum_variant_fields<S>(
833 serializer: &mut S,
834 enum_: facet_reflect::PeekEnum<'_, '_>,
835) -> Result<(), DomSerializeError<S::Error>>
836where
837 S: DomSerializer,
838{
839 let fields: Vec<_> = enum_.fields_for_serialize().collect();
841
842 for (field_item, field_value) in &fields {
844 serializer
845 .field_metadata(field_item)
846 .map_err(DomSerializeError::Backend)?;
847
848 if serializer.is_attribute_field() {
849 let attr_name = if let Some(field) = field_item.field {
851 field
852 .rename
853 .map(Cow::Borrowed)
854 .unwrap_or_else(|| to_element_name(&field_item.name))
855 } else {
856 field_item.name.clone()
857 };
858
859 let format_ns = serializer.format_namespace();
861 let proxy_def = field_item
862 .field
863 .and_then(|f| f.effective_proxy(format_ns))
864 .or_else(|| field_value.shape().effective_proxy(format_ns));
865
866 if let Some(proxy_def) = proxy_def {
867 match field_value.custom_serialization_with_proxy(proxy_def) {
868 Ok(proxy_peek) => {
869 serializer
870 .attribute(&attr_name, proxy_peek.as_peek(), None)
871 .map_err(DomSerializeError::Backend)?;
872 }
873 Err(e) => {
874 return Err(DomSerializeError::Reflect(e));
875 }
876 }
877 } else {
878 serializer
879 .attribute(&attr_name, *field_value, None)
880 .map_err(DomSerializeError::Backend)?;
881 }
882 }
883 serializer.clear_field_state();
884 }
885
886 serializer
888 .children_start()
889 .map_err(DomSerializeError::Backend)?;
890
891 for (field_item, field_value) in &fields {
893 serializer
894 .field_metadata(field_item)
895 .map_err(DomSerializeError::Backend)?;
896
897 if serializer.is_attribute_field() {
899 serializer.clear_field_state();
900 continue;
901 }
902
903 if serializer.is_tag_field() {
905 serializer.clear_field_state();
906 continue;
907 }
908
909 if serializer.is_doctype_field() {
911 serializer.clear_field_state();
912 continue;
913 }
914
915 if serializer.is_text_field() {
917 if let Some(s) = value_to_string(*field_value, serializer) {
918 serializer.text(&s).map_err(DomSerializeError::Backend)?;
919 }
920 serializer.clear_field_state();
921 continue;
922 }
923
924 if field_item.is_text_variant {
926 if let Some(s) = value_to_string(*field_value, serializer) {
927 serializer.text(&s).map_err(DomSerializeError::Backend)?;
928 }
929 serializer.clear_field_state();
930 continue;
931 }
932
933 let is_elements = serializer.is_elements_field();
935 let explicit_rename = field_item.field.and_then(|f| f.rename);
936 let is_flattened = field_item.flattened;
937
938 let field_element_name: Option<Cow<'_, str>> = if is_elements && explicit_rename.is_none() {
939 None } else if is_flattened {
941 None
943 } else if let Some(rename) = explicit_rename {
944 Some(Cow::Borrowed(rename))
945 } else {
946 Some(to_element_name(&field_item.name))
947 };
948
949 let format_ns = serializer.format_namespace();
951 let proxy_def = field_item
952 .field
953 .and_then(|f| f.effective_proxy(format_ns))
954 .or_else(|| field_value.shape().effective_proxy(format_ns));
955
956 if let Some(proxy_def) = proxy_def {
957 match field_value.custom_serialization_with_proxy(proxy_def) {
958 Ok(proxy_peek) => {
959 serialize_value(
960 serializer,
961 proxy_peek.as_peek(),
962 field_element_name.as_deref(),
963 )?;
964 }
965 Err(e) => {
966 return Err(DomSerializeError::Reflect(e));
967 }
968 }
969 } else {
970 serialize_value(serializer, *field_value, field_element_name.as_deref())?;
971 }
972
973 serializer.clear_field_state();
974 }
975
976 Ok(())
977}
978
979fn serialize_via_proxy<S>(
981 serializer: &mut S,
982 value: Peek<'_, '_>,
983 element_name: Option<&str>,
984) -> Result<(), DomSerializeError<S::Error>>
985where
986 S: DomSerializer,
987{
988 let owned_peek = value
991 .custom_serialization_from_shape_with_format(serializer.format_namespace())
992 .map_err(DomSerializeError::Reflect)?;
993
994 match owned_peek {
995 Some(proxy_peek) => {
996 serialize_value(serializer, proxy_peek.as_peek(), element_name)
998 }
999 None => {
1000 Err(DomSerializeError::Unsupported(Cow::Borrowed(
1002 "proxy serialization failed: no proxy on shape",
1003 )))
1004 }
1005 }
1006}
1007
1008fn deref_if_pointer<'mem, 'facet>(value: Peek<'mem, 'facet>) -> Peek<'mem, 'facet> {
1010 if let Ok(ptr) = value.into_pointer()
1011 && let Some(inner) = ptr.borrow_inner()
1012 {
1013 return deref_if_pointer(inner);
1014 }
1015 value
1016}
1017
1018fn value_to_string<S: DomSerializer>(value: Peek<'_, '_>, serializer: &S) -> Option<String> {
1020 use facet_core::ScalarType;
1021
1022 if let Def::Option(_) = &value.shape().def
1024 && let Ok(opt) = value.into_option()
1025 {
1026 return match opt.value() {
1027 Some(inner) => value_to_string(inner, serializer),
1028 None => None,
1029 };
1030 }
1031
1032 if let Some(scalar_type) = value.scalar_type() {
1033 let s = match scalar_type {
1034 ScalarType::Unit => return Some("null".into()),
1035 ScalarType::Bool => if *value.get::<bool>().ok()? {
1036 "true"
1037 } else {
1038 "false"
1039 }
1040 .into(),
1041 ScalarType::Char => value.get::<char>().ok()?.to_string(),
1042 ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
1043 value.as_str()?.to_string()
1044 }
1045 ScalarType::F32 => serializer.format_float(*value.get::<f32>().ok()? as f64),
1046 ScalarType::F64 => serializer.format_float(*value.get::<f64>().ok()?),
1047 ScalarType::U8 => value.get::<u8>().ok()?.to_string(),
1048 ScalarType::U16 => value.get::<u16>().ok()?.to_string(),
1049 ScalarType::U32 => value.get::<u32>().ok()?.to_string(),
1050 ScalarType::U64 => value.get::<u64>().ok()?.to_string(),
1051 ScalarType::U128 => value.get::<u128>().ok()?.to_string(),
1052 ScalarType::USize => value.get::<usize>().ok()?.to_string(),
1053 ScalarType::I8 => value.get::<i8>().ok()?.to_string(),
1054 ScalarType::I16 => value.get::<i16>().ok()?.to_string(),
1055 ScalarType::I32 => value.get::<i32>().ok()?.to_string(),
1056 ScalarType::I64 => value.get::<i64>().ok()?.to_string(),
1057 ScalarType::I128 => value.get::<i128>().ok()?.to_string(),
1058 ScalarType::ISize => value.get::<isize>().ok()?.to_string(),
1059 #[cfg(feature = "net")]
1060 ScalarType::IpAddr => value.get::<core::net::IpAddr>().ok()?.to_string(),
1061 #[cfg(feature = "net")]
1062 ScalarType::Ipv4Addr => value.get::<core::net::Ipv4Addr>().ok()?.to_string(),
1063 #[cfg(feature = "net")]
1064 ScalarType::Ipv6Addr => value.get::<core::net::Ipv6Addr>().ok()?.to_string(),
1065 #[cfg(feature = "net")]
1066 ScalarType::SocketAddr => value.get::<core::net::SocketAddr>().ok()?.to_string(),
1067 _ => return None,
1068 };
1069 return Some(s);
1070 }
1071
1072 if matches!(value.shape().def, Def::Scalar) && value.shape().vtable.has_display() {
1074 return Some(alloc::format!("{}", value));
1075 }
1076
1077 None
1078}