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