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 preferred_field_order(&self) -> FieldOrdering {
62 FieldOrdering::Declaration
63 }
64
65 fn raw_serialize_shape(&self) -> Option<&'static facet_core::Shape> {
71 None
72 }
73
74 fn raw_scalar(&mut self, content: &str) -> Result<(), Self::Error> {
79 self.scalar(ScalarValue::Str(Cow::Borrowed(content)))
81 }
82}
83
84#[derive(Debug)]
86pub enum SerializeError<E: Debug> {
87 Backend(E),
89 Reflect(ReflectError),
91 Unsupported(&'static str),
93 Internal(&'static str),
95}
96
97impl<E: Debug> core::fmt::Display for SerializeError<E> {
98 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
99 match self {
100 SerializeError::Backend(_) => f.write_str("format serializer error"),
101 SerializeError::Reflect(err) => write!(f, "{err}"),
102 SerializeError::Unsupported(msg) => f.write_str(msg),
103 SerializeError::Internal(msg) => f.write_str(msg),
104 }
105 }
106}
107
108impl<E: Debug> std::error::Error for SerializeError<E> {}
109
110pub fn serialize_root<'mem, 'facet, S>(
112 serializer: &mut S,
113 value: Peek<'mem, 'facet>,
114) -> Result<(), SerializeError<S::Error>>
115where
116 S: FormatSerializer,
117{
118 shared_serialize(serializer, value)
119}
120
121fn sort_fields_if_needed<'mem, 'facet, S>(
123 serializer: &S,
124 fields: &mut alloc::vec::Vec<(facet_reflect::FieldItem, Peek<'mem, 'facet>)>,
125) where
126 S: FormatSerializer,
127{
128 if serializer.preferred_field_order() == FieldOrdering::AttributesFirst {
129 fields.sort_by_key(|(field_item, _)| {
130 if field_item
132 .field
133 .get_attr(Some("xml"), "attribute")
134 .is_some()
135 {
136 0 } else if field_item.field.get_attr(Some("xml"), "text").is_some() {
138 2 } else {
140 1 }
142 });
143 }
144}
145
146fn shared_serialize<'mem, 'facet, S>(
147 serializer: &mut S,
148 value: Peek<'mem, 'facet>,
149) -> Result<(), SerializeError<S::Error>>
150where
151 S: FormatSerializer,
152{
153 let value = deref_if_pointer(value);
155
156 if serializer.raw_serialize_shape() == Some(value.shape()) {
159 if let Ok(struct_) = value.into_struct()
162 && let Some((_field_item, inner_value)) = struct_.fields_for_serialize().next()
163 && let Some(s) = inner_value.as_str()
164 {
165 return serializer.raw_scalar(s).map_err(SerializeError::Backend);
166 }
167 return Err(SerializeError::Unsupported(
170 "raw capture type matched but could not extract inner string",
171 ));
172 }
173
174 let value = value.innermost_peek();
175
176 if let Some(proxy_def) = value.shape().proxy {
178 return serialize_via_proxy(serializer, value, proxy_def);
179 }
180
181 if let Some(scalar) = scalar_from_peek(value)? {
182 return serializer.scalar(scalar).map_err(SerializeError::Backend);
183 }
184
185 if let Ok(opt) = value.into_option() {
187 return match opt.value() {
188 Some(inner) => shared_serialize(serializer, inner),
189 None => serializer
190 .scalar(ScalarValue::Null)
191 .map_err(SerializeError::Backend),
192 };
193 }
194
195 if let Ok(list) = value.into_list_like() {
196 serializer.begin_seq().map_err(SerializeError::Backend)?;
197 for item in list.iter() {
198 shared_serialize(serializer, item)?;
199 }
200 serializer.end_seq().map_err(SerializeError::Backend)?;
201 return Ok(());
202 }
203
204 if let Ok(map) = value.into_map() {
205 serializer.begin_struct().map_err(SerializeError::Backend)?;
206 for (key, val) in map.iter() {
207 let key_str = if let Some(s) = key.as_str() {
209 Cow::Borrowed(s)
210 } else {
211 Cow::Owned(alloc::format!("{:?}", key))
213 };
214 serializer
215 .field_key(&key_str)
216 .map_err(SerializeError::Backend)?;
217 shared_serialize(serializer, val)?;
218 }
219 serializer.end_struct().map_err(SerializeError::Backend)?;
220 return Ok(());
221 }
222
223 if let Ok(set) = value.into_set() {
224 serializer.begin_seq().map_err(SerializeError::Backend)?;
225 for item in set.iter() {
226 shared_serialize(serializer, item)?;
227 }
228 serializer.end_seq().map_err(SerializeError::Backend)?;
229 return Ok(());
230 }
231
232 if let Ok(struct_) = value.into_struct() {
233 let kind = struct_.ty().kind;
234 if kind == StructKind::Tuple || kind == StructKind::TupleStruct {
235 serializer.begin_seq().map_err(SerializeError::Backend)?;
237 for (_field_item, field_value) in struct_.fields_for_serialize() {
238 shared_serialize(serializer, field_value)?;
239 }
240 serializer.end_seq().map_err(SerializeError::Backend)?;
241 } else {
242 serializer
244 .struct_metadata(value.shape())
245 .map_err(SerializeError::Backend)?;
246 serializer.begin_struct().map_err(SerializeError::Backend)?;
247
248 let mut fields: alloc::vec::Vec<_> = struct_.fields_for_serialize().collect();
250 sort_fields_if_needed(serializer, &mut fields);
251
252 for (field_item, field_value) in fields {
253 serializer
254 .field_metadata(&field_item)
255 .map_err(SerializeError::Backend)?;
256 serializer
257 .field_key(field_item.name)
258 .map_err(SerializeError::Backend)?;
259 shared_serialize(serializer, field_value)?;
260 }
261 serializer.end_struct().map_err(SerializeError::Backend)?;
262 }
263 return Ok(());
264 }
265
266 if let Ok(enum_) = value.into_enum() {
267 let variant = enum_
268 .active_variant()
269 .map_err(|_| SerializeError::Unsupported("opaque enum layout is unsupported"))?;
270
271 let untagged = value.shape().is_untagged();
272 let tag = value.shape().get_tag_attr();
273 let content = value.shape().get_content_attr();
274
275 if untagged {
276 return serialize_untagged_enum(serializer, enum_, variant);
277 }
278
279 match (tag, content) {
280 (Some(tag_key), None) => {
281 serializer.begin_struct().map_err(SerializeError::Backend)?;
283 serializer
284 .field_key(tag_key)
285 .map_err(SerializeError::Backend)?;
286 serializer
287 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
288 .map_err(SerializeError::Backend)?;
289
290 match variant.data.kind {
291 StructKind::Unit => {}
292 StructKind::Struct => {
293 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
294 sort_fields_if_needed(serializer, &mut fields);
295 for (field_item, field_value) in fields {
296 serializer
297 .field_metadata(&field_item)
298 .map_err(SerializeError::Backend)?;
299 serializer
300 .field_key(field_item.name)
301 .map_err(SerializeError::Backend)?;
302 shared_serialize(serializer, field_value)?;
303 }
304 }
305 StructKind::TupleStruct | StructKind::Tuple => {
306 return Err(SerializeError::Unsupported(
307 "internally tagged tuple variants are not supported",
308 ));
309 }
310 }
311
312 serializer.end_struct().map_err(SerializeError::Backend)?;
313 return Ok(());
314 }
315 (Some(tag_key), Some(content_key)) => {
316 serializer.begin_struct().map_err(SerializeError::Backend)?;
318 serializer
319 .field_key(tag_key)
320 .map_err(SerializeError::Backend)?;
321 serializer
322 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
323 .map_err(SerializeError::Backend)?;
324
325 match variant.data.kind {
326 StructKind::Unit => {
327 }
329 StructKind::Struct => {
330 serializer
331 .field_key(content_key)
332 .map_err(SerializeError::Backend)?;
333 serializer.begin_struct().map_err(SerializeError::Backend)?;
334 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
335 sort_fields_if_needed(serializer, &mut fields);
336 for (field_item, field_value) in fields {
337 serializer
338 .field_metadata(&field_item)
339 .map_err(SerializeError::Backend)?;
340 serializer
341 .field_key(field_item.name)
342 .map_err(SerializeError::Backend)?;
343 shared_serialize(serializer, field_value)?;
344 }
345 serializer.end_struct().map_err(SerializeError::Backend)?;
346 }
347 StructKind::TupleStruct | StructKind::Tuple => {
348 serializer
349 .field_key(content_key)
350 .map_err(SerializeError::Backend)?;
351
352 let field_count = variant.data.fields.len();
353 if field_count == 1 {
354 let inner = enum_
355 .field(0)
356 .map_err(|_| {
357 SerializeError::Internal("variant field lookup failed")
358 })?
359 .ok_or(SerializeError::Internal(
360 "variant reported 1 field but field(0) returned None",
361 ))?;
362 shared_serialize(serializer, inner)?;
363 } else {
364 serializer.begin_seq().map_err(SerializeError::Backend)?;
365 for idx in 0..field_count {
366 let inner = enum_
367 .field(idx)
368 .map_err(|_| {
369 SerializeError::Internal("variant field lookup failed")
370 })?
371 .ok_or(SerializeError::Internal(
372 "variant field missing while iterating tuple fields",
373 ))?;
374 shared_serialize(serializer, inner)?;
375 }
376 serializer.end_seq().map_err(SerializeError::Backend)?;
377 }
378 }
379 }
380
381 serializer.end_struct().map_err(SerializeError::Backend)?;
382 return Ok(());
383 }
384 (None, Some(_)) => {
385 return Err(SerializeError::Unsupported(
386 "adjacent content key set without tag key",
387 ));
388 }
389 (None, None) => {}
390 }
391
392 return match variant.data.kind {
394 StructKind::Unit => {
395 serializer
396 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
397 .map_err(SerializeError::Backend)?;
398 Ok(())
399 }
400 StructKind::TupleStruct | StructKind::Tuple => {
401 serializer.begin_struct().map_err(SerializeError::Backend)?;
402 serializer
403 .field_key(variant.name)
404 .map_err(SerializeError::Backend)?;
405
406 let field_count = variant.data.fields.len();
407 if field_count == 1 {
408 let inner = enum_
409 .field(0)
410 .map_err(|_| SerializeError::Internal("variant field lookup failed"))?
411 .ok_or(SerializeError::Internal(
412 "variant reported 1 field but field(0) returned None",
413 ))?;
414 shared_serialize(serializer, inner)?;
415 } else {
416 serializer.begin_seq().map_err(SerializeError::Backend)?;
417 for idx in 0..field_count {
418 let inner = enum_
419 .field(idx)
420 .map_err(|_| SerializeError::Internal("variant field lookup failed"))?
421 .ok_or(SerializeError::Internal(
422 "variant field missing while iterating tuple fields",
423 ))?;
424 shared_serialize(serializer, inner)?;
425 }
426 serializer.end_seq().map_err(SerializeError::Backend)?;
427 }
428
429 serializer.end_struct().map_err(SerializeError::Backend)?;
430 Ok(())
431 }
432 StructKind::Struct => {
433 serializer.begin_struct().map_err(SerializeError::Backend)?;
434 serializer
435 .field_key(variant.name)
436 .map_err(SerializeError::Backend)?;
437
438 serializer.begin_struct().map_err(SerializeError::Backend)?;
439 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
440 sort_fields_if_needed(serializer, &mut fields);
441 for (field_item, field_value) in fields {
442 serializer
443 .field_metadata(&field_item)
444 .map_err(SerializeError::Backend)?;
445 serializer
446 .field_key(field_item.name)
447 .map_err(SerializeError::Backend)?;
448 shared_serialize(serializer, field_value)?;
449 }
450 serializer.end_struct().map_err(SerializeError::Backend)?;
451
452 serializer.end_struct().map_err(SerializeError::Backend)?;
453 Ok(())
454 }
455 };
456 }
457
458 Err(SerializeError::Unsupported(
459 "unsupported value kind for serialization",
460 ))
461}
462
463fn serialize_untagged_enum<'mem, 'facet, S>(
464 serializer: &mut S,
465 enum_: facet_reflect::PeekEnum<'mem, 'facet>,
466 variant: &'static facet_core::Variant,
467) -> Result<(), SerializeError<S::Error>>
468where
469 S: FormatSerializer,
470{
471 match variant.data.kind {
472 StructKind::Unit => {
473 if variant.name.eq_ignore_ascii_case("null") {
477 return serializer
478 .scalar(ScalarValue::Null)
479 .map_err(SerializeError::Backend);
480 }
481 serializer
482 .scalar(ScalarValue::Str(Cow::Borrowed(variant.name)))
483 .map_err(SerializeError::Backend)
484 }
485 StructKind::TupleStruct | StructKind::Tuple => {
486 let field_count = variant.data.fields.len();
487 if field_count == 1 {
488 let inner = enum_
489 .field(0)
490 .map_err(|_| SerializeError::Internal("variant field lookup failed"))?
491 .ok_or(SerializeError::Internal(
492 "variant reported 1 field but field(0) returned None",
493 ))?;
494 shared_serialize(serializer, inner)
495 } else {
496 serializer.begin_seq().map_err(SerializeError::Backend)?;
497 for idx in 0..field_count {
498 let inner = enum_
499 .field(idx)
500 .map_err(|_| SerializeError::Internal("variant field lookup failed"))?
501 .ok_or(SerializeError::Internal(
502 "variant field missing while iterating tuple fields",
503 ))?;
504 shared_serialize(serializer, inner)?;
505 }
506 serializer.end_seq().map_err(SerializeError::Backend)?;
507 Ok(())
508 }
509 }
510 StructKind::Struct => {
511 serializer.begin_struct().map_err(SerializeError::Backend)?;
512 let mut fields: alloc::vec::Vec<_> = enum_.fields_for_serialize().collect();
513 sort_fields_if_needed(serializer, &mut fields);
514 for (field_item, field_value) in fields {
515 serializer
516 .field_metadata(&field_item)
517 .map_err(SerializeError::Backend)?;
518 serializer
519 .field_key(field_item.name)
520 .map_err(SerializeError::Backend)?;
521 shared_serialize(serializer, field_value)?;
522 }
523 serializer.end_struct().map_err(SerializeError::Backend)?;
524 Ok(())
525 }
526 }
527}
528
529fn deref_if_pointer<'mem, 'facet>(peek: Peek<'mem, 'facet>) -> Peek<'mem, 'facet> {
531 if let Ok(ptr) = peek.into_pointer()
532 && let Some(target) = ptr.borrow_inner()
533 {
534 return deref_if_pointer(target);
535 }
536 peek
537}
538
539#[allow(unsafe_code)]
547fn serialize_via_proxy<'mem, 'facet, S>(
548 serializer: &mut S,
549 value: Peek<'mem, 'facet>,
550 proxy_def: &'static facet_core::ProxyDef,
551) -> Result<(), SerializeError<S::Error>>
552where
553 S: FormatSerializer,
554{
555 use facet_core::PtrUninit;
556
557 let proxy_shape = proxy_def.shape;
558 let proxy_layout = proxy_shape
559 .layout
560 .sized_layout()
561 .map_err(|_| SerializeError::Unsupported("proxy type must be sized for serialization"))?;
562
563 let proxy_mem = unsafe { alloc::alloc::alloc(proxy_layout) };
565 if proxy_mem.is_null() {
566 return Err(SerializeError::Internal("failed to allocate proxy memory"));
567 }
568
569 let proxy_uninit = PtrUninit::new(proxy_mem);
571 let convert_result = unsafe { (proxy_def.convert_out)(value.data(), proxy_uninit) };
572
573 let proxy_ptr = match convert_result {
574 Ok(ptr) => ptr,
575 Err(msg) => {
576 unsafe { alloc::alloc::dealloc(proxy_mem, proxy_layout) };
577 return Err(SerializeError::Unsupported(
578 alloc::boxed::Box::leak(msg.into_boxed_str()),
580 ));
581 }
582 };
583
584 let proxy_peek = unsafe { Peek::unchecked_new(proxy_ptr.as_const(), proxy_shape) };
586 let result = shared_serialize(serializer, proxy_peek);
587
588 unsafe {
590 let _ = proxy_shape.call_drop_in_place(proxy_ptr);
591 alloc::alloc::dealloc(proxy_mem, proxy_layout);
592 }
593
594 result
595}
596
597fn scalar_from_peek<'mem, 'facet, E: Debug>(
598 value: Peek<'mem, 'facet>,
599) -> Result<Option<ScalarValue<'mem>>, SerializeError<E>> {
600 let Some(scalar_type) = value.scalar_type() else {
601 return Ok(None);
602 };
603
604 let scalar = match scalar_type {
605 ScalarType::Unit => ScalarValue::Null,
606 ScalarType::Bool => {
607 ScalarValue::Bool(*value.get::<bool>().map_err(SerializeError::Reflect)?)
608 }
609 ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
610 let Some(text) = value.as_str() else {
611 return Err(SerializeError::Internal(
612 "scalar_type indicated string but as_str returned None",
613 ));
614 };
615 ScalarValue::Str(Cow::Borrowed(text))
616 }
617 ScalarType::F32 => {
618 ScalarValue::F64(*value.get::<f32>().map_err(SerializeError::Reflect)? as f64)
619 }
620 ScalarType::F64 => ScalarValue::F64(*value.get::<f64>().map_err(SerializeError::Reflect)?),
621 ScalarType::U8 => {
622 ScalarValue::U64(*value.get::<u8>().map_err(SerializeError::Reflect)? as u64)
623 }
624 ScalarType::U16 => {
625 ScalarValue::U64(*value.get::<u16>().map_err(SerializeError::Reflect)? as u64)
626 }
627 ScalarType::U32 => {
628 ScalarValue::U64(*value.get::<u32>().map_err(SerializeError::Reflect)? as u64)
629 }
630 ScalarType::U64 => ScalarValue::U64(*value.get::<u64>().map_err(SerializeError::Reflect)?),
631 ScalarType::U128 => {
632 let n = *value.get::<u128>().map_err(SerializeError::Reflect)?;
633 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&n)))
634 }
635 ScalarType::USize => {
636 ScalarValue::U64(*value.get::<usize>().map_err(SerializeError::Reflect)? as u64)
637 }
638 ScalarType::I8 => {
639 ScalarValue::I64(*value.get::<i8>().map_err(SerializeError::Reflect)? as i64)
640 }
641 ScalarType::I16 => {
642 ScalarValue::I64(*value.get::<i16>().map_err(SerializeError::Reflect)? as i64)
643 }
644 ScalarType::I32 => {
645 ScalarValue::I64(*value.get::<i32>().map_err(SerializeError::Reflect)? as i64)
646 }
647 ScalarType::I64 => ScalarValue::I64(*value.get::<i64>().map_err(SerializeError::Reflect)?),
648 ScalarType::I128 => {
649 let n = *value.get::<i128>().map_err(SerializeError::Reflect)?;
650 ScalarValue::Str(Cow::Owned(alloc::string::ToString::to_string(&n)))
651 }
652 ScalarType::ISize => {
653 ScalarValue::I64(*value.get::<isize>().map_err(SerializeError::Reflect)? as i64)
654 }
655 other => {
656 let _ = other;
657 return Ok(None);
658 }
659 };
660
661 Ok(Some(scalar))
662}