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