facet_serialize/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![warn(missing_docs)]
3#![warn(clippy::std_instead_of_core)]
4#![warn(clippy::std_instead_of_alloc)]
5#![deny(unsafe_code)]
6#![doc = include_str!("../README.md")]
7
8extern crate alloc;
9
10use alloc::string::String;
11use alloc::vec::Vec;
12
13use facet_core::{
14    Def, Facet, Field, PointerType, SequenceType, ShapeAttribute, StructKind, Type, UserType,
15};
16use facet_reflect::{HasFields, Peek, PeekListLike, PeekMap, PeekStruct, PeekTuple, ScalarType};
17use log::{debug, trace};
18
19mod debug_serializer;
20
21fn variant_is_newtype_like(variant: &facet_core::Variant) -> bool {
22    variant.data.kind == facet_core::StructKind::Tuple && variant.data.fields.len() == 1
23}
24
25// --- Serializer Trait Definition ---
26
27/// A trait for implementing format-specific serialization logic.
28/// The core iterative serializer uses this trait to output data.
29pub trait Serializer {
30    /// The error type returned by serialization methods
31    type Error;
32
33    /// Serialize an unsigned 64-bit integer.
34    fn serialize_u64(&mut self, value: u64) -> Result<(), Self::Error>;
35
36    /// Serialize an unsigned 128-bit integer.
37    fn serialize_u128(&mut self, value: u128) -> Result<(), Self::Error>;
38
39    /// Serialize a signed 64-bit integer.
40    fn serialize_i64(&mut self, value: i64) -> Result<(), Self::Error>;
41
42    /// Serialize a signed 128-bit integer.
43    fn serialize_i128(&mut self, value: i128) -> Result<(), Self::Error>;
44
45    /// Serialize a double-precision floating-point value.
46    fn serialize_f64(&mut self, value: f64) -> Result<(), Self::Error>;
47
48    /// Serialize a boolean value.
49    fn serialize_bool(&mut self, value: bool) -> Result<(), Self::Error>;
50
51    /// Serialize a character.
52    fn serialize_char(&mut self, value: char) -> Result<(), Self::Error>;
53
54    /// Serialize a UTF-8 string slice.
55    fn serialize_str(&mut self, value: &str) -> Result<(), Self::Error>;
56
57    /// Serialize a raw byte slice.
58    fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error>;
59
60    // Special values
61
62    /// Serialize a `None` variant of an Option type.
63    fn serialize_none(&mut self) -> Result<(), Self::Error>;
64
65    /// Serialize a unit value `()`.
66    fn serialize_unit(&mut self) -> Result<(), Self::Error>;
67
68    // Enum specific values
69
70    /// Serialize a unit variant of an enum (no data).
71    ///
72    /// # Arguments
73    ///
74    /// * `variant_index` - The index of the variant.
75    /// * `variant_name` - The name of the variant.
76    fn serialize_unit_variant(
77        &mut self,
78        variant_index: usize,
79        variant_name: &'static str,
80    ) -> Result<(), Self::Error>;
81
82    /// Begin serializing an object/map-like value.
83    ///
84    /// # Arguments
85    ///
86    /// * `len` - The number of fields, if known.
87    fn start_object(&mut self, len: Option<usize>) -> Result<(), Self::Error>;
88
89    /// Serialize a field name (for objects and maps).
90    ///
91    /// # Arguments
92    ///
93    /// * `name` - The field or key name to serialize.
94    fn serialize_field_name(&mut self, name: &'static str) -> Result<(), Self::Error>;
95
96    /// Begin serializing an array/sequence-like value.
97    ///
98    /// # Arguments
99    ///
100    /// * `len` - The number of elements, if known.
101    fn start_array(&mut self, len: Option<usize>) -> Result<(), Self::Error>;
102
103    /// Begin serializing a map/dictionary-like value.
104    ///
105    /// # Arguments
106    ///
107    /// * `len` - The number of entries, if known.
108    fn start_map(&mut self, len: Option<usize>) -> Result<(), Self::Error>;
109
110    /// Serialize an unsigned 8-bit integer.
111    #[inline(always)]
112    fn serialize_u8(&mut self, value: u8) -> Result<(), Self::Error> {
113        self.serialize_u64(value as u64)
114    }
115
116    /// Serialize an unsigned 16-bit integer.
117    #[inline(always)]
118    fn serialize_u16(&mut self, value: u16) -> Result<(), Self::Error> {
119        self.serialize_u64(value as u64)
120    }
121
122    /// Serialize an unsigned 32-bit integer.
123    #[inline(always)]
124    fn serialize_u32(&mut self, value: u32) -> Result<(), Self::Error> {
125        self.serialize_u64(value as u64)
126    }
127
128    /// Serialize a `usize` integer.
129    #[inline(always)]
130    fn serialize_usize(&mut self, value: usize) -> Result<(), Self::Error> {
131        // We assume `usize` will never be >64 bits
132        self.serialize_u64(value as u64)
133    }
134
135    /// Serialize a signed 8-bit integer.
136    #[inline(always)]
137    fn serialize_i8(&mut self, value: i8) -> Result<(), Self::Error> {
138        self.serialize_i64(value as i64)
139    }
140
141    /// Serialize a signed 16-bit integer.
142    #[inline(always)]
143    fn serialize_i16(&mut self, value: i16) -> Result<(), Self::Error> {
144        self.serialize_i64(value as i64)
145    }
146
147    /// Serialize a signed 32-bit integer.
148    #[inline(always)]
149    fn serialize_i32(&mut self, value: i32) -> Result<(), Self::Error> {
150        self.serialize_i64(value as i64)
151    }
152
153    /// Serialize an `isize` integer.
154    #[inline(always)]
155    fn serialize_isize(&mut self, value: isize) -> Result<(), Self::Error> {
156        // We assume `isize` will never be >64 bits
157        self.serialize_i64(value as i64)
158    }
159
160    /// Serialize a single-precision floating-point value.
161    #[inline(always)]
162    fn serialize_f32(&mut self, value: f32) -> Result<(), Self::Error> {
163        self.serialize_f64(value as f64)
164    }
165
166    /// Begin serializing a map key value.
167    #[inline(always)]
168    fn begin_map_key(&mut self) -> Result<(), Self::Error> {
169        Ok(())
170    }
171
172    /// Signal the end of serializing a map key value.
173    #[inline(always)]
174    fn end_map_key(&mut self) -> Result<(), Self::Error> {
175        Ok(())
176    }
177
178    /// Begin serializing a map value.
179    #[inline(always)]
180    fn begin_map_value(&mut self) -> Result<(), Self::Error> {
181        Ok(())
182    }
183
184    /// Signal the end of serializing a map value.
185    #[inline(always)]
186    fn end_map_value(&mut self) -> Result<(), Self::Error> {
187        Ok(())
188    }
189
190    /// Signal the end of serializing an object/map-like value.
191    #[inline(always)]
192    fn end_object(&mut self) -> Result<(), Self::Error> {
193        Ok(())
194    }
195
196    /// Signal the end of serializing an array/sequence-like value.
197    #[inline(always)]
198    fn end_array(&mut self) -> Result<(), Self::Error> {
199        Ok(())
200    }
201
202    /// Signal the end of serializing a map/dictionary-like value.
203    #[inline(always)]
204    fn end_map(&mut self) -> Result<(), Self::Error> {
205        Ok(())
206    }
207
208    /// Signal the end of serializing a field.
209    #[inline(always)]
210    fn end_field(&mut self) -> Result<(), Self::Error> {
211        Ok(())
212    }
213}
214
215// --- Iterative Serialization Logic ---
216
217/// Task items for the serialization stack.
218#[derive(Debug)]
219enum SerializeTask<'mem, 'facet> {
220    Value(Peek<'mem, 'facet>, Option<Field>),
221    // End markers
222    EndObject,
223    EndArray,
224    EndMap,
225    EndMapKey,
226    EndMapValue,
227    EndField,
228    // Tasks to push sub-elements onto the stack
229    ObjectFields(PeekStruct<'mem, 'facet>),
230    ArrayItems(PeekListLike<'mem, 'facet>),
231    TupleStructFields(PeekStruct<'mem, 'facet>),
232    TupleFields(PeekTuple<'mem, 'facet>),
233    MapEntries(PeekMap<'mem, 'facet>),
234    // Field-related tasks
235    SerializeFieldName(&'static str),
236    SerializeMapKey(Peek<'mem, 'facet>),
237    SerializeMapValue(Peek<'mem, 'facet>),
238}
239
240/// Serializes a `Peek` value using the provided `Serializer`.
241///
242/// This function uses an iterative approach with a stack to avoid recursion depth limits.
243pub fn serialize_iterative<S>(peek: Peek<'_, '_>, serializer: &mut S) -> Result<(), S::Error>
244where
245    S: Serializer,
246{
247    let mut stack = Vec::new();
248    stack.push(SerializeTask::Value(peek, None));
249
250    while let Some(task) = stack.pop() {
251        match task {
252            SerializeTask::Value(mut cpeek, maybe_field) => {
253                debug!("Serializing a value, shape is {}", cpeek.shape(),);
254
255                if cpeek
256                    .shape()
257                    .attributes
258                    .iter()
259                    .any(|attr| *attr == ShapeAttribute::Transparent)
260                {
261                    let old_shape = cpeek.shape();
262
263                    // then serialize the inner shape instead
264                    let ps = cpeek.into_struct().unwrap();
265                    cpeek = ps.field(0).unwrap();
266
267                    let new_shape = cpeek.shape();
268                    debug!(
269                        "{old_shape} is transparent, let's serialize the inner {new_shape} instead"
270                    );
271                }
272
273                match (cpeek.shape().def, cpeek.shape().ty) {
274                    (Def::Scalar(_), _) => {
275                        let cpeek = cpeek.innermost_peek();
276
277                        // Dispatch to appropriate scalar serialization method based on type
278                        match cpeek.scalar_type() {
279                            Some(ScalarType::Unit) => serializer.serialize_unit()?,
280                            Some(ScalarType::Bool) => {
281                                serializer.serialize_bool(*cpeek.get::<bool>().unwrap())?
282                            }
283                            Some(ScalarType::Char) => {
284                                serializer.serialize_char(*cpeek.get::<char>().unwrap())?
285                            }
286
287                            // String types
288                            Some(ScalarType::Str) => {
289                                serializer.serialize_str(cpeek.get::<&str>().unwrap())?
290                            }
291                            Some(ScalarType::String) => {
292                                serializer.serialize_str(cpeek.get::<String>().unwrap())?
293                            }
294                            Some(ScalarType::CowStr) => serializer.serialize_str(
295                                cpeek.get::<alloc::borrow::Cow<'_, str>>().unwrap().as_ref(),
296                            )?,
297
298                            // Float types
299                            Some(ScalarType::F32) => {
300                                serializer.serialize_f32(*cpeek.get::<f32>().unwrap())?
301                            }
302                            Some(ScalarType::F64) => {
303                                serializer.serialize_f64(*cpeek.get::<f64>().unwrap())?
304                            }
305
306                            // Integer types
307                            Some(ScalarType::U8) => {
308                                serializer.serialize_u8(*cpeek.get::<u8>().unwrap())?
309                            }
310                            Some(ScalarType::U16) => {
311                                serializer.serialize_u16(*cpeek.get::<u16>().unwrap())?
312                            }
313                            Some(ScalarType::U32) => {
314                                serializer.serialize_u32(*cpeek.get::<u32>().unwrap())?
315                            }
316                            Some(ScalarType::U64) => {
317                                serializer.serialize_u64(*cpeek.get::<u64>().unwrap())?
318                            }
319                            Some(ScalarType::U128) => {
320                                serializer.serialize_u128(*cpeek.get::<u128>().unwrap())?
321                            }
322                            Some(ScalarType::USize) => {
323                                serializer.serialize_usize(*cpeek.get::<usize>().unwrap())?
324                            }
325                            Some(ScalarType::I8) => {
326                                serializer.serialize_i8(*cpeek.get::<i8>().unwrap())?
327                            }
328                            Some(ScalarType::I16) => {
329                                serializer.serialize_i16(*cpeek.get::<i16>().unwrap())?
330                            }
331                            Some(ScalarType::I32) => {
332                                serializer.serialize_i32(*cpeek.get::<i32>().unwrap())?
333                            }
334                            Some(ScalarType::I64) => {
335                                serializer.serialize_i64(*cpeek.get::<i64>().unwrap())?
336                            }
337                            Some(ScalarType::I128) => {
338                                serializer.serialize_i128(*cpeek.get::<i128>().unwrap())?
339                            }
340                            Some(ScalarType::ISize) => {
341                                serializer.serialize_isize(*cpeek.get::<isize>().unwrap())?
342                            }
343                            Some(unsupported) => panic!("Unsupported scalar type: {unsupported:?}"),
344                            None => panic!("Unsupported shape: {}", cpeek.shape()),
345                        }
346                    }
347                    (Def::List(_), _) | (Def::Array(_), _) | (Def::Slice(_), _) => {
348                        let peek_list = cpeek.into_list_like().unwrap();
349                        let len = peek_list.len();
350                        serializer.start_array(Some(len))?;
351                        stack.push(SerializeTask::EndArray);
352                        stack.push(SerializeTask::ArrayItems(peek_list));
353                    }
354                    (Def::Map(_), _) => {
355                        let peek_map = cpeek.into_map().unwrap();
356                        let len = peek_map.len();
357                        serializer.start_map(Some(len))?;
358                        stack.push(SerializeTask::EndMap);
359                        stack.push(SerializeTask::MapEntries(peek_map));
360                    }
361                    (Def::Option(_), _) => {
362                        let opt = cpeek.into_option().unwrap();
363                        if let Some(inner_peek) = opt.value() {
364                            stack.push(SerializeTask::Value(inner_peek, None));
365                        } else {
366                            serializer.serialize_none()?;
367                        }
368                    }
369                    (Def::SmartPointer(_), _) => {
370                        let _sp = cpeek.into_smart_pointer().unwrap();
371                        panic!("TODO: Implement serialization for smart pointers");
372                    }
373                    (_, Type::User(UserType::Struct(sd))) => {
374                        debug!("Serializing struct: shape={}", cpeek.shape(),);
375                        debug!(
376                            "  Struct details: kind={:?}, field_count={}",
377                            sd.kind,
378                            sd.fields.len()
379                        );
380
381                        match sd.kind {
382                            StructKind::Unit => {
383                                debug!("  Handling unit struct (no fields)");
384                                // Correctly handle unit struct type when encountered as a value
385                                serializer.serialize_unit()?;
386                            }
387                            StructKind::Tuple | StructKind::TupleStruct => {
388                                debug!("  Handling tuple struct with {:?} kind", sd.kind);
389                                let peek_struct = cpeek.into_struct().unwrap();
390                                let fields = peek_struct.fields_for_serialize().count();
391                                debug!("  Serializing {} fields as array", fields);
392
393                                serializer.start_array(Some(fields))?;
394                                stack.push(SerializeTask::EndArray);
395                                stack.push(SerializeTask::TupleStructFields(peek_struct));
396                                trace!(
397                                    "  Pushed TupleStructFields to stack, will handle {} fields",
398                                    fields
399                                );
400                            }
401                            StructKind::Struct => {
402                                debug!("  Handling record struct");
403                                let peek_struct = cpeek.into_struct().unwrap();
404                                let fields = peek_struct.fields_for_serialize().count();
405                                debug!("  Serializing {} fields as object", fields);
406
407                                serializer.start_object(Some(fields))?;
408                                stack.push(SerializeTask::EndObject);
409                                stack.push(SerializeTask::ObjectFields(peek_struct));
410                                trace!(
411                                    "  Pushed ObjectFields to stack, will handle {} fields",
412                                    fields
413                                );
414                            }
415                            _ => {
416                                unreachable!()
417                            }
418                        }
419                    }
420                    (_, Type::Sequence(SequenceType::Tuple(_))) => {
421                        debug!("Serializing tuple: shape={}", cpeek.shape(),);
422
423                        // Now we can use our dedicated PeekTuple type
424                        if let Ok(peek_tuple) = cpeek.into_tuple() {
425                            let count = peek_tuple.len();
426                            debug!("  Tuple fields count: {}", count);
427
428                            serializer.start_array(Some(count))?;
429                            stack.push(SerializeTask::EndArray);
430                            stack.push(SerializeTask::TupleFields(peek_tuple));
431                            trace!(
432                                "  Pushed TupleFields to stack for tuple, will handle {} fields",
433                                count
434                            );
435                        } else {
436                            // This shouldn't happen if into_tuple is implemented correctly,
437                            // but we'll handle it as a fallback
438                            debug!(
439                                "  Could not convert to PeekTuple, falling back to list_like approach"
440                            );
441
442                            if let Ok(peek_list_like) = cpeek.into_list_like() {
443                                let count = peek_list_like.len();
444                                serializer.start_array(Some(count))?;
445                                stack.push(SerializeTask::EndArray);
446                                stack.push(SerializeTask::ArrayItems(peek_list_like));
447                                trace!("  Pushed ArrayItems to stack for tuple serialization",);
448                            } else {
449                                // Final fallback - create an empty array
450                                debug!(
451                                    "  Could not convert tuple to list-like either, using empty array"
452                                );
453                                serializer.start_array(Some(0))?;
454                                stack.push(SerializeTask::EndArray);
455                                trace!("  Warning: Tuple serialization fallback to empty array");
456                            }
457                        }
458                    }
459                    (_, Type::User(UserType::Enum(_))) => {
460                        let peek_enum = cpeek.into_enum().unwrap();
461                        let variant = peek_enum
462                            .active_variant()
463                            .expect("Failed to get active variant");
464                        let variant_index = peek_enum
465                            .variant_index()
466                            .expect("Failed to get variant index");
467                        trace!(
468                            "Active variant index is {}, variant is {:?}",
469                            variant_index, variant
470                        );
471                        let flattened = maybe_field.map(|f| f.flattened).unwrap_or_default();
472
473                        if variant.data.fields.is_empty() {
474                            // Unit variant
475                            serializer.serialize_unit_variant(variant_index, variant.name)?;
476                        } else {
477                            if !flattened {
478                                // For now, treat all enum variants with data as objects
479                                serializer.start_object(Some(1))?;
480                                stack.push(SerializeTask::EndObject);
481
482                                // Serialize variant name as field name
483                                serializer.serialize_field_name(variant.name)?;
484                            }
485
486                            if variant_is_newtype_like(variant) {
487                                // Newtype variant - serialize the inner value directly
488                                let fields = peek_enum.fields_for_serialize().collect::<Vec<_>>();
489                                let (field, field_peek) = fields[0];
490                                // TODO: error if `skip_serialize` is set?
491                                stack.push(SerializeTask::Value(field_peek, Some(field)));
492                            } else if variant.data.kind == StructKind::Tuple
493                                || variant.data.kind == StructKind::TupleStruct
494                            {
495                                // Tuple variant - serialize as array
496                                let fields = peek_enum.fields_for_serialize().count();
497                                serializer.start_array(Some(fields))?;
498                                stack.push(SerializeTask::EndArray);
499
500                                // Push fields in reverse order for tuple variant
501                                for (field, field_peek) in peek_enum.fields_for_serialize().rev() {
502                                    stack.push(SerializeTask::Value(field_peek, Some(field)));
503                                }
504                            } else {
505                                // Struct variant - serialize as object
506                                let fields = peek_enum.fields_for_serialize().count();
507                                serializer.start_object(Some(fields))?;
508                                stack.push(SerializeTask::EndObject);
509
510                                // Push fields in reverse order for struct variant
511                                for (field, field_peek) in peek_enum.fields_for_serialize().rev() {
512                                    stack.push(SerializeTask::EndField);
513                                    stack.push(SerializeTask::Value(field_peek, Some(field)));
514                                    stack.push(SerializeTask::SerializeFieldName(field.name));
515                                }
516                            }
517                        }
518                    }
519                    (_, Type::Pointer(pointer_type)) => {
520                        // Handle pointer types using our new safe abstraction
521                        if let Some(str_value) = cpeek.as_str() {
522                            // We have a string value, serialize it
523                            serializer.serialize_str(str_value)?;
524                        } else if let PointerType::Function(_) = pointer_type {
525                            // Serialize function pointers as units
526                            serializer.serialize_unit()?;
527                        } else {
528                            // Handle other pointer types with innermost_peek which is safe
529                            let innermost = cpeek.innermost_peek();
530                            if innermost.shape() != cpeek.shape() {
531                                // We got a different inner value, serialize it
532                                stack.push(SerializeTask::Value(innermost, None));
533                            } else {
534                                // Couldn't access inner value safely, fall back to unit
535                                serializer.serialize_unit()?;
536                            }
537                        }
538                    }
539                    _ => {
540                        // Default case for any other definitions
541                        debug!(
542                            "Unhandled type: {:?}, falling back to unit",
543                            cpeek.shape().ty
544                        );
545                        serializer.serialize_unit()?;
546                    }
547                }
548            }
549
550            // --- Pushing sub-elements onto the stack ---
551            SerializeTask::ObjectFields(peek_struct) => {
552                // Push fields in reverse order for stack processing
553                for (field, field_peek) in peek_struct.fields_for_serialize().rev() {
554                    stack.push(SerializeTask::EndField);
555                    stack.push(SerializeTask::Value(field_peek, Some(field)));
556                    stack.push(SerializeTask::SerializeFieldName(field.name));
557                }
558            }
559            SerializeTask::TupleStructFields(peek_struct) => {
560                // Push fields in reverse order
561                for (field, field_peek) in peek_struct.fields_for_serialize().rev() {
562                    stack.push(SerializeTask::Value(field_peek, Some(field)));
563                }
564            }
565            SerializeTask::TupleFields(peek_tuple) => {
566                // Push fields in reverse order
567                for (_, field_peek) in peek_tuple.fields().rev() {
568                    // Get the innermost peek value - this is essential for proper serialization
569                    // to unwrap transparent wrappers and get to the actual value
570                    let innermost_peek = field_peek.innermost_peek();
571
572                    // Push the innermost peek to the stack
573                    stack.push(SerializeTask::Value(innermost_peek, None));
574                }
575                trace!("  Pushed {} tuple fields to stack", peek_tuple.len());
576            }
577            SerializeTask::ArrayItems(peek_list) => {
578                // Push items in reverse order
579                let items: Vec<_> = peek_list.iter().collect();
580                for item_peek in items.into_iter().rev() {
581                    stack.push(SerializeTask::Value(item_peek, None));
582                }
583            }
584            SerializeTask::MapEntries(peek_map) => {
585                // Push entries in reverse order (key, value pairs)
586                let entries = peek_map.iter().collect::<Vec<_>>();
587                for (key_peek, value_peek) in entries.into_iter().rev() {
588                    stack.push(SerializeTask::SerializeMapValue(value_peek));
589                    stack.push(SerializeTask::SerializeMapKey(key_peek));
590                }
591            }
592
593            // --- Field name and map key/value handling ---
594            SerializeTask::SerializeFieldName(name) => {
595                serializer.serialize_field_name(name)?;
596            }
597            SerializeTask::SerializeMapKey(key_peek) => {
598                stack.push(SerializeTask::EndMapKey);
599                stack.push(SerializeTask::Value(key_peek, None));
600                serializer.begin_map_key()?;
601            }
602            SerializeTask::SerializeMapValue(value_peek) => {
603                stack.push(SerializeTask::EndMapValue);
604                stack.push(SerializeTask::Value(value_peek, None));
605                serializer.begin_map_value()?;
606            }
607
608            // --- End composite type tasks ---
609            SerializeTask::EndObject => {
610                serializer.end_object()?;
611            }
612            SerializeTask::EndArray => {
613                serializer.end_array()?;
614            }
615            SerializeTask::EndMap => {
616                serializer.end_map()?;
617            }
618            SerializeTask::EndMapKey => {
619                serializer.end_map_key()?;
620            }
621            SerializeTask::EndMapValue => {
622                serializer.end_map_value()?;
623            }
624            SerializeTask::EndField => {
625                serializer.end_field()?;
626            }
627        }
628    }
629
630    // Successful completion
631    Ok(())
632}
633
634// --- Helper Trait for Ergonomics ---
635
636/// Extension trait to simplify calling the generic serializer.
637pub trait Serialize<'a>: Facet<'a> {
638    /// Serialize this value using the provided `Serializer`.
639    fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error>;
640}
641
642impl<'a, T> Serialize<'a> for T
643where
644    T: Facet<'a>,
645{
646    /// Serialize this value using the provided `Serializer`.
647    fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
648        let peek = Peek::new(self);
649        serialize_iterative(peek, serializer)
650    }
651}