Skip to main content

facet_postcard/
serialize.rs

1//! Serialization support for postcard format.
2//!
3//! This module provides serialization functions using custom traversal logic
4//! optimized for binary formats. Unlike text formats (JSON, YAML), postcard
5//! needs:
6//! - No struct delimiters or field names
7//! - Variant indices instead of variant names
8//! - Type-precise integer encoding (u8 raw, larger varint, signed zigzag)
9//! - Length prefixes before sequences
10
11extern crate alloc;
12
13use alloc::borrow::Cow;
14use alloc::vec::Vec;
15use core::marker::PhantomData;
16
17use facet_core::{Def, ScalarType, Shape};
18use facet_format::{
19    DynamicValueEncoding, DynamicValueTag, EnumVariantEncoding, FormatSerializer, MapEncoding,
20    SerializeError as FormatSerializeError, StructFieldMode, serialize_root,
21    serialize_value_with_shape,
22};
23use facet_reflect::Peek;
24
25use crate::error::SerializeError;
26
27/// A trait for writing bytes during serialization with error handling.
28///
29/// This trait enables custom serialization targets that can report errors,
30/// such as buffer overflow. It's designed to support use cases like buffer
31/// pooling where you need to detect when a fixed-size buffer is too small.
32///
33/// # Example
34///
35/// ```
36/// use facet_postcard::{Writer, SerializeError};
37///
38/// struct PooledWriter {
39///     buf: Vec<u8>,  // In practice, this would be from a buffer pool
40///     overflow: Option<Vec<u8>>,
41/// }
42///
43/// impl Writer for PooledWriter {
44///     fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
45///         // Try pooled buffer first, fall back to Vec on overflow
46///         if let Some(ref mut overflow) = self.overflow {
47///             overflow.push(byte);
48///         } else if self.buf.len() < self.buf.capacity() {
49///             self.buf.push(byte);
50///         } else {
51///             // Overflow - allocate Vec and transfer contents
52///             let mut overflow = Vec::new();
53///             overflow.extend_from_slice(&self.buf);
54///             overflow.push(byte);
55///             self.overflow = Some(overflow);
56///         }
57///         Ok(())
58///     }
59///
60///     fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
61///         if let Some(ref mut overflow) = self.overflow {
62///             overflow.extend_from_slice(bytes);
63///         } else if self.buf.len() + bytes.len() <= self.buf.capacity() {
64///             self.buf.extend_from_slice(bytes);
65///         } else {
66///             // Overflow - allocate Vec and transfer contents
67///             let mut overflow = Vec::new();
68///             overflow.extend_from_slice(&self.buf);
69///             overflow.extend_from_slice(bytes);
70///             self.overflow = Some(overflow);
71///         }
72///         Ok(())
73///     }
74/// }
75/// ```
76pub trait Writer {
77    /// Write a single byte to the writer.
78    fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError>;
79
80    /// Write a slice of bytes to the writer.
81    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError>;
82}
83
84impl Writer for Vec<u8> {
85    fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
86        self.push(byte);
87        Ok(())
88    }
89
90    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
91        self.extend_from_slice(bytes);
92        Ok(())
93    }
94}
95
96/// A segment in a postcard scatter plan.
97#[derive(Debug, Clone, PartialEq, Eq)]
98pub enum Segment<'a> {
99    /// Bytes stored in [`ScatterPlan::staging`].
100    Staged { offset: usize, len: usize },
101    /// Bytes borrowed directly from the source value memory.
102    Reference { bytes: &'a [u8] },
103}
104
105/// A scatter/gather postcard serialization plan.
106#[derive(Debug, Clone)]
107pub struct ScatterPlan<'a> {
108    staging: Vec<u8>,
109    segments: Vec<Segment<'a>>,
110    total_size: usize,
111}
112
113impl<'a> ScatterPlan<'a> {
114    /// Returns the exact serialized size in bytes.
115    pub const fn total_size(&self) -> usize {
116        self.total_size
117    }
118
119    /// Returns the staged structural bytes.
120    pub fn staging(&self) -> &[u8] {
121        &self.staging
122    }
123
124    /// Returns the ordered segments that form the serialized output.
125    pub fn segments(&self) -> &[Segment<'a>] {
126        &self.segments
127    }
128
129    /// Writes the full serialized output into `dest`.
130    ///
131    /// `dest` must be exactly [`Self::total_size`] bytes long.
132    pub fn write_into(&self, dest: &mut [u8]) -> Result<(), SerializeError> {
133        if dest.len() != self.total_size {
134            return Err(SerializeError::Custom(alloc::format!(
135                "destination length mismatch: expected {}, got {}",
136                self.total_size,
137                dest.len()
138            )));
139        }
140
141        let mut cursor = 0usize;
142        for segment in &self.segments {
143            match segment {
144                Segment::Staged { offset, len } => {
145                    let src = &self.staging[*offset..*offset + *len];
146                    dest[cursor..cursor + *len].copy_from_slice(src);
147                    cursor += *len;
148                }
149                Segment::Reference { bytes } => {
150                    dest[cursor..cursor + bytes.len()].copy_from_slice(bytes);
151                    cursor += bytes.len();
152                }
153            }
154        }
155
156        debug_assert_eq!(cursor, self.total_size);
157        Ok(())
158    }
159}
160
161struct ScatterBuilder<'a> {
162    staging: Vec<u8>,
163    segments: Vec<Segment<'a>>,
164    total_size: usize,
165}
166
167impl<'a> ScatterBuilder<'a> {
168    const fn new() -> Self {
169        Self {
170            staging: Vec::new(),
171            segments: Vec::new(),
172            total_size: 0,
173        }
174    }
175
176    fn finish(self) -> ScatterPlan<'a> {
177        ScatterPlan {
178            staging: self.staging,
179            segments: self.segments,
180            total_size: self.total_size,
181        }
182    }
183
184    fn push_staged_segment(&mut self, offset: usize, len: usize) {
185        if len == 0 {
186            return;
187        }
188
189        if let Some(Segment::Staged {
190            offset: prev_offset,
191            len: prev_len,
192        }) = self.segments.last_mut()
193            && *prev_offset + *prev_len == offset
194        {
195            *prev_len += len;
196            return;
197        }
198
199        self.segments.push(Segment::Staged { offset, len });
200    }
201
202    fn push_reference_segment(&mut self, bytes: &[u8]) {
203        if bytes.is_empty() {
204            return;
205        }
206
207        // SAFETY: All calls to `write_referenced_bytes` are restricted to paths that
208        // receive bytes borrowed from the source value (`Peek` traversal inputs),
209        // never temporary buffers created during formatting.
210        #[allow(unsafe_code)]
211        let bytes: &'a [u8] = unsafe { core::mem::transmute(bytes) };
212        self.total_size += bytes.len();
213        self.segments.push(Segment::Reference { bytes });
214    }
215}
216
217impl Writer for ScatterBuilder<'_> {
218    fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
219        let offset = self.staging.len();
220        self.staging.push(byte);
221        self.total_size += 1;
222        self.push_staged_segment(offset, 1);
223        Ok(())
224    }
225
226    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
227        if bytes.is_empty() {
228            return Ok(());
229        }
230        let offset = self.staging.len();
231        self.staging.extend_from_slice(bytes);
232        self.total_size += bytes.len();
233        self.push_staged_segment(offset, bytes.len());
234        Ok(())
235    }
236}
237
238struct CopyWriter<'a, W: Writer + ?Sized> {
239    inner: &'a mut W,
240}
241
242impl<'a, W: Writer + ?Sized> CopyWriter<'a, W> {
243    const fn new(inner: &'a mut W) -> Self {
244        Self { inner }
245    }
246}
247
248impl<W: Writer + ?Sized> Writer for CopyWriter<'_, W> {
249    fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
250        self.inner.write_byte(byte)
251    }
252
253    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
254        self.inner.write_bytes(bytes)
255    }
256}
257
258trait PostcardWriter<'a>: Writer {
259    fn write_referenced_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError>;
260}
261
262impl<'a, W: Writer + ?Sized> PostcardWriter<'a> for CopyWriter<'_, W> {
263    fn write_referenced_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
264        self.inner.write_bytes(bytes)
265    }
266}
267
268impl<'a> PostcardWriter<'a> for ScatterBuilder<'a> {
269    fn write_referenced_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
270        self.push_reference_segment(bytes);
271        Ok(())
272    }
273}
274
275/// Serializes any Facet type to postcard bytes.
276///
277/// # Example
278/// ```
279/// use facet::Facet;
280/// use facet_postcard::to_vec;
281///
282/// #[derive(Debug, Facet)]
283/// struct Point {
284///     x: i32,
285///     y: i32,
286/// }
287///
288/// let point = Point { x: 10, y: 20 };
289/// let bytes = to_vec(&point).unwrap();
290/// ```
291pub fn to_vec<'facet, T>(value: &T) -> Result<Vec<u8>, SerializeError>
292where
293    T: facet_core::Facet<'facet>,
294{
295    let mut buffer = Vec::new();
296    to_writer_fallible(value, &mut buffer)?;
297    Ok(buffer)
298}
299
300/// Serializes any Facet type to a custom writer implementing the fallible `Writer` trait.
301///
302/// This function allows external crates to implement custom serialization targets
303/// that can report errors, such as buffer overflow. This is useful for use cases
304/// like buffer pooling where you need to detect when a fixed-size buffer is too
305/// small and transparently fall back to heap allocation.
306///
307/// # Example
308/// ```
309/// use facet::Facet;
310/// use facet_postcard::{to_writer_fallible, Writer, SerializeError};
311///
312/// #[derive(Debug, Facet)]
313/// struct Point {
314///     x: i32,
315///     y: i32,
316/// }
317///
318/// struct CustomWriter {
319///     buffer: Vec<u8>,
320/// }
321///
322/// impl Writer for CustomWriter {
323///     fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
324///         self.buffer.push(byte);
325///         Ok(())
326///     }
327///
328///     fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
329///         self.buffer.extend_from_slice(bytes);
330///         Ok(())
331///     }
332/// }
333///
334/// let point = Point { x: 10, y: 20 };
335/// let mut writer = CustomWriter { buffer: Vec::new() };
336/// to_writer_fallible(&point, &mut writer).unwrap();
337/// ```
338pub fn to_writer_fallible<'facet, T, W>(value: &T, writer: &mut W) -> Result<(), SerializeError>
339where
340    T: facet_core::Facet<'facet>,
341    W: Writer,
342{
343    let peek = Peek::new(value);
344    let mut serializer = PostcardSerializer::new(CopyWriter::new(writer));
345    serialize_root(&mut serializer, peek).map_err(map_format_error)
346}
347
348/// Serializes a [`Peek`] reference to postcard bytes.
349///
350/// This is useful when you have a type-erased reference via reflection
351/// and need to serialize it without knowing the concrete type at compile time.
352///
353/// # Example
354/// ```
355/// use facet::Facet;
356/// use facet_reflect::Peek;
357/// use facet_postcard::peek_to_vec;
358///
359/// #[derive(Debug, Facet)]
360/// struct Point {
361///     x: i32,
362///     y: i32,
363/// }
364///
365/// let point = Point { x: 10, y: 20 };
366/// let peek = Peek::new(&point);
367/// let bytes = peek_to_vec(peek).unwrap();
368/// ```
369pub fn peek_to_vec(peek: Peek<'_, '_>) -> Result<Vec<u8>, SerializeError> {
370    let mut buffer = Vec::new();
371    let mut serializer = PostcardSerializer::new(CopyWriter::new(&mut buffer));
372    serialize_root(&mut serializer, peek).map_err(map_format_error)?;
373    Ok(buffer)
374}
375
376/// Serializes a value into a scatter plan.
377///
378/// Structural bytes are staged in an internal buffer while blob payloads are
379/// referenced directly from the source value memory.
380pub fn to_scatter_plan<'a, T>(value: &'a T) -> Result<ScatterPlan<'a>, SerializeError>
381where
382    T: facet_core::Facet<'a> + ?Sized,
383{
384    peek_to_scatter_plan(Peek::new(value))
385}
386
387/// Serializes a [`Peek`] into a scatter plan.
388pub fn peek_to_scatter_plan<'input, 'facet>(
389    peek: Peek<'input, 'facet>,
390) -> Result<ScatterPlan<'input>, SerializeError> {
391    let mut serializer = PostcardSerializer::new(ScatterBuilder::new());
392    serialize_root(&mut serializer, peek).map_err(map_format_error)?;
393    Ok(serializer.into_writer().finish())
394}
395
396/// Serializes a dynamic value (like `facet_value::Value`) to postcard bytes using
397/// a target shape to guide the serialization.
398///
399/// This is the inverse of [`from_slice_with_shape`](crate::from_slice_with_shape).
400/// It allows you to serialize a `Value` as if it were a typed value matching the
401/// target shape, without the `Value` type discriminants.
402///
403/// This is useful for scenarios where you need to:
404/// 1. Parse JSON/YAML into a `Value`
405/// 2. Serialize it to postcard bytes matching a specific typed schema
406///
407/// # Example
408/// ```
409/// use facet::Facet;
410/// use facet_value::Value;
411/// use facet_postcard::{to_vec_with_shape, from_slice_with_shape};
412///
413/// #[derive(Debug, Facet, PartialEq)]
414/// struct Point { x: i32, y: i32 }
415///
416/// // Parse JSON into a Value
417/// let value: Value = facet_json::from_str(r#"{"x": 10, "y": 20}"#).unwrap();
418///
419/// // Serialize using Point's shape - produces postcard bytes for Point, not Value
420/// let bytes = to_vec_with_shape(&value, Point::SHAPE).unwrap();
421///
422/// // Deserialize back into a typed Point
423/// let point: Point = facet_postcard::from_slice(&bytes).unwrap();
424/// assert_eq!(point, Point { x: 10, y: 20 });
425/// ```
426///
427/// # Arguments
428///
429/// * `value` - A reference to a dynamic value type (like `facet_value::Value`)
430/// * `target_shape` - The shape describing the expected wire format
431///
432/// # Errors
433///
434/// Returns an error if:
435/// - The value is not a dynamic value type
436/// - The value's structure doesn't match the target shape
437pub fn to_vec_with_shape<'facet, T>(
438    value: &T,
439    target_shape: &'static Shape,
440) -> Result<Vec<u8>, SerializeError>
441where
442    T: facet_core::Facet<'facet>,
443{
444    let mut buffer = Vec::new();
445    let peek = Peek::new(value);
446    let mut serializer = PostcardSerializer::new(CopyWriter::new(&mut buffer));
447    serialize_value_with_shape(&mut serializer, peek, target_shape).map_err(map_format_error)?;
448    Ok(buffer)
449}
450
451fn map_format_error(error: FormatSerializeError<SerializeError>) -> SerializeError {
452    match error {
453        FormatSerializeError::Backend(err) => err,
454        FormatSerializeError::Reflect(err) => SerializeError::Custom(alloc::format!("{err}")),
455        FormatSerializeError::Unsupported(message) => SerializeError::Custom(message.into_owned()),
456        FormatSerializeError::Internal(message) => SerializeError::Custom(message.into_owned()),
457    }
458}
459
460fn has_trailing_attr(field: Option<&facet_core::Field>) -> bool {
461    field.is_some_and(|f| f.has_builtin_attr("trailing"))
462}
463
464struct PostcardSerializer<'a, W> {
465    writer: W,
466    _marker: PhantomData<&'a ()>,
467}
468
469impl<'a, W> PostcardSerializer<'a, W> {
470    const fn new(writer: W) -> Self {
471        Self {
472            writer,
473            _marker: PhantomData,
474        }
475    }
476
477    fn into_writer(self) -> W {
478        self.writer
479    }
480
481    fn write_str(&mut self, s: &str) -> Result<(), SerializeError>
482    where
483        W: Writer,
484    {
485        write_varint(s.len() as u64, &mut self.writer)?;
486        self.writer.write_bytes(s.as_bytes())
487    }
488
489    fn write_str_borrowed(&mut self, s: &str) -> Result<(), SerializeError>
490    where
491        W: PostcardWriter<'a>,
492    {
493        write_varint(s.len() as u64, &mut self.writer)?;
494        self.writer.write_referenced_bytes(s.as_bytes())
495    }
496
497    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError>
498    where
499        W: Writer,
500    {
501        write_varint(bytes.len() as u64, &mut self.writer)?;
502        self.writer.write_bytes(bytes)
503    }
504
505    fn write_bytes_borrowed(&mut self, bytes: &[u8]) -> Result<(), SerializeError>
506    where
507        W: PostcardWriter<'a>,
508    {
509        write_varint(bytes.len() as u64, &mut self.writer)?;
510        self.writer.write_referenced_bytes(bytes)
511    }
512
513    fn write_byte_array_borrowed(&mut self, bytes: &[u8]) -> Result<(), SerializeError>
514    where
515        W: PostcardWriter<'a>,
516    {
517        self.writer.write_referenced_bytes(bytes)
518    }
519
520    fn write_dynamic_tag(&mut self, tag: DynamicValueTag) -> Result<(), SerializeError>
521    where
522        W: Writer,
523    {
524        let byte = match tag {
525            DynamicValueTag::Null => 0,
526            DynamicValueTag::Bool => 1,
527            DynamicValueTag::I64 => 2,
528            DynamicValueTag::U64 => 3,
529            DynamicValueTag::F64 => 4,
530            DynamicValueTag::String => 5,
531            DynamicValueTag::Bytes => 6,
532            DynamicValueTag::Array => 7,
533            DynamicValueTag::Object => 8,
534            DynamicValueTag::DateTime => 9,
535        };
536        self.writer.write_byte(byte)
537    }
538}
539
540impl<'a, W: PostcardWriter<'a>> FormatSerializer for PostcardSerializer<'a, W> {
541    type Error = SerializeError;
542
543    fn begin_struct(&mut self) -> Result<(), Self::Error> {
544        Ok(())
545    }
546
547    fn field_key(&mut self, _key: &str) -> Result<(), Self::Error> {
548        Err(SerializeError::Custom(
549            "postcard does not support named fields".into(),
550        ))
551    }
552
553    fn end_struct(&mut self) -> Result<(), Self::Error> {
554        Ok(())
555    }
556
557    fn begin_seq(&mut self) -> Result<(), Self::Error> {
558        Ok(())
559    }
560
561    fn end_seq(&mut self) -> Result<(), Self::Error> {
562        Ok(())
563    }
564
565    fn scalar(&mut self, scalar: facet_format::ScalarValue<'_>) -> Result<(), Self::Error> {
566        match scalar {
567            facet_format::ScalarValue::Null | facet_format::ScalarValue::Unit => Ok(()),
568            facet_format::ScalarValue::Bool(v) => self.writer.write_byte(if v { 1 } else { 0 }),
569            facet_format::ScalarValue::Char(c) => {
570                // Postcard encodes char as UTF-8
571                let mut buf = [0u8; 4];
572                let s = c.encode_utf8(&mut buf);
573                self.write_str(s)
574            }
575            facet_format::ScalarValue::I64(n) => write_varint_signed(n, &mut self.writer),
576            facet_format::ScalarValue::U64(n) => write_varint(n, &mut self.writer),
577            facet_format::ScalarValue::I128(n) => write_varint_signed_i128(n, &mut self.writer),
578            facet_format::ScalarValue::U128(n) => write_varint_u128(n, &mut self.writer),
579            facet_format::ScalarValue::F64(n) => self.writer.write_bytes(&n.to_le_bytes()),
580            facet_format::ScalarValue::Str(s) => match s {
581                Cow::Borrowed(s) => self.write_str_borrowed(s),
582                Cow::Owned(s) => self.write_str(&s),
583            },
584            facet_format::ScalarValue::Bytes(bytes) => match bytes {
585                Cow::Borrowed(bytes) => self.write_bytes_borrowed(bytes),
586                Cow::Owned(bytes) => self.write_bytes(&bytes),
587            },
588        }
589    }
590
591    fn struct_field_mode(&self) -> StructFieldMode {
592        StructFieldMode::Unnamed
593    }
594
595    fn map_encoding(&self) -> MapEncoding {
596        MapEncoding::Pairs
597    }
598
599    fn enum_variant_encoding(&self) -> EnumVariantEncoding {
600        EnumVariantEncoding::Index
601    }
602
603    fn is_self_describing(&self) -> bool {
604        false
605    }
606
607    fn dynamic_value_encoding(&self) -> DynamicValueEncoding {
608        DynamicValueEncoding::Tagged
609    }
610
611    fn dynamic_value_tag(&mut self, tag: DynamicValueTag) -> Result<(), Self::Error> {
612        self.write_dynamic_tag(tag)
613    }
614
615    fn begin_seq_with_len(&mut self, len: usize) -> Result<(), Self::Error> {
616        write_varint(len as u64, &mut self.writer)
617    }
618
619    fn begin_map_with_len(&mut self, len: usize) -> Result<(), Self::Error> {
620        write_varint(len as u64, &mut self.writer)
621    }
622
623    fn end_map(&mut self) -> Result<(), Self::Error> {
624        Ok(())
625    }
626
627    fn typed_scalar(
628        &mut self,
629        scalar_type: ScalarType,
630        value: Peek<'_, '_>,
631    ) -> Result<(), Self::Error> {
632        match scalar_type {
633            ScalarType::Unit => Ok(()),
634            ScalarType::Bool => {
635                let v = *value.get::<bool>().map_err(|e| {
636                    SerializeError::Custom(alloc::format!("Failed to get bool: {}", e))
637                })?;
638                self.writer.write_byte(if v { 1 } else { 0 })
639            }
640            ScalarType::Char => {
641                let c = *value.get::<char>().map_err(|e| {
642                    SerializeError::Custom(alloc::format!("Failed to get char: {}", e))
643                })?;
644                let mut buf = [0u8; 4];
645                let s = c.encode_utf8(&mut buf);
646                self.write_str(s)
647            }
648            ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
649                let s = value
650                    .as_str()
651                    .ok_or_else(|| SerializeError::Custom("Failed to get string value".into()))?;
652                self.write_str_borrowed(s)
653            }
654            ScalarType::F32 => {
655                let v = *value.get::<f32>().map_err(|e| {
656                    SerializeError::Custom(alloc::format!("Failed to get f32: {}", e))
657                })?;
658                self.writer.write_bytes(&v.to_le_bytes())
659            }
660            ScalarType::F64 => {
661                let v = *value.get::<f64>().map_err(|e| {
662                    SerializeError::Custom(alloc::format!("Failed to get f64: {}", e))
663                })?;
664                self.writer.write_bytes(&v.to_le_bytes())
665            }
666            ScalarType::U8 => {
667                let v = *value.get::<u8>().map_err(|e| {
668                    SerializeError::Custom(alloc::format!("Failed to get u8: {}", e))
669                })?;
670                self.writer.write_byte(v)
671            }
672            ScalarType::U16 => {
673                let v = *value.get::<u16>().map_err(|e| {
674                    SerializeError::Custom(alloc::format!("Failed to get u16: {}", e))
675                })?;
676                write_varint(v as u64, &mut self.writer)
677            }
678            ScalarType::U32 => {
679                let v = *value.get::<u32>().map_err(|e| {
680                    SerializeError::Custom(alloc::format!("Failed to get u32: {}", e))
681                })?;
682                write_varint(v as u64, &mut self.writer)
683            }
684            ScalarType::U64 => {
685                let v = *value.get::<u64>().map_err(|e| {
686                    SerializeError::Custom(alloc::format!("Failed to get u64: {}", e))
687                })?;
688                write_varint(v, &mut self.writer)
689            }
690            ScalarType::U128 => {
691                let v = *value.get::<u128>().map_err(|e| {
692                    SerializeError::Custom(alloc::format!("Failed to get u128: {}", e))
693                })?;
694                write_varint_u128(v, &mut self.writer)
695            }
696            ScalarType::USize => {
697                let v = *value.get::<usize>().map_err(|e| {
698                    SerializeError::Custom(alloc::format!("Failed to get usize: {}", e))
699                })?;
700                write_varint(v as u64, &mut self.writer)
701            }
702            ScalarType::I8 => {
703                let v = *value.get::<i8>().map_err(|e| {
704                    SerializeError::Custom(alloc::format!("Failed to get i8: {}", e))
705                })?;
706                self.writer.write_byte(v as u8)
707            }
708            ScalarType::I16 => {
709                let v = *value.get::<i16>().map_err(|e| {
710                    SerializeError::Custom(alloc::format!("Failed to get i16: {}", e))
711                })?;
712                write_varint_signed(v as i64, &mut self.writer)
713            }
714            ScalarType::I32 => {
715                let v = *value.get::<i32>().map_err(|e| {
716                    SerializeError::Custom(alloc::format!("Failed to get i32: {}", e))
717                })?;
718                write_varint_signed(v as i64, &mut self.writer)
719            }
720            ScalarType::I64 => {
721                let v = *value.get::<i64>().map_err(|e| {
722                    SerializeError::Custom(alloc::format!("Failed to get i64: {}", e))
723                })?;
724                write_varint_signed(v, &mut self.writer)
725            }
726            ScalarType::I128 => {
727                let v = *value.get::<i128>().map_err(|e| {
728                    SerializeError::Custom(alloc::format!("Failed to get i128: {}", e))
729                })?;
730                write_varint_signed_i128(v, &mut self.writer)
731            }
732            ScalarType::ISize => {
733                let v = *value.get::<isize>().map_err(|e| {
734                    SerializeError::Custom(alloc::format!("Failed to get isize: {}", e))
735                })?;
736                write_varint_signed(v as i64, &mut self.writer)
737            }
738            #[cfg(feature = "net")]
739            ScalarType::SocketAddr => {
740                let v = *value.get::<core::net::SocketAddr>().map_err(|e| {
741                    SerializeError::Custom(alloc::format!("Failed to get SocketAddr: {}", e))
742                })?;
743                self.write_str(&v.to_string())
744            }
745            #[cfg(feature = "net")]
746            ScalarType::IpAddr => {
747                let v = *value.get::<core::net::IpAddr>().map_err(|e| {
748                    SerializeError::Custom(alloc::format!("Failed to get IpAddr: {}", e))
749                })?;
750                self.write_str(&v.to_string())
751            }
752            #[cfg(feature = "net")]
753            ScalarType::Ipv4Addr => {
754                let v = *value.get::<core::net::Ipv4Addr>().map_err(|e| {
755                    SerializeError::Custom(alloc::format!("Failed to get Ipv4Addr: {}", e))
756                })?;
757                self.write_str(&v.to_string())
758            }
759            #[cfg(feature = "net")]
760            ScalarType::Ipv6Addr => {
761                let v = *value.get::<core::net::Ipv6Addr>().map_err(|e| {
762                    SerializeError::Custom(alloc::format!("Failed to get Ipv6Addr: {}", e))
763                })?;
764                self.write_str(&v.to_string())
765            }
766            _ => Err(SerializeError::Custom(alloc::format!(
767                "Unsupported scalar type: {:?}",
768                scalar_type
769            ))),
770        }
771    }
772
773    fn begin_option_some(&mut self) -> Result<(), Self::Error> {
774        self.writer.write_byte(1)
775    }
776
777    fn serialize_none(&mut self) -> Result<(), Self::Error> {
778        self.writer.write_byte(0)
779    }
780
781    fn begin_enum_variant(
782        &mut self,
783        variant_index: usize,
784        _variant_name: &'static str,
785    ) -> Result<(), Self::Error> {
786        write_varint(variant_index as u64, &mut self.writer)
787    }
788
789    fn serialize_byte_sequence(&mut self, bytes: &[u8]) -> Result<bool, Self::Error> {
790        // Postcard stores byte sequences as varint length + raw bytes
791        self.write_bytes_borrowed(bytes)?;
792        Ok(true)
793    }
794
795    fn serialize_byte_array(&mut self, bytes: &[u8]) -> Result<bool, Self::Error> {
796        // Arrays have no length prefix - just raw bytes
797        self.write_byte_array_borrowed(bytes)?;
798        Ok(true)
799    }
800
801    fn serialize_opaque_scalar(
802        &mut self,
803        shape: &'static facet_core::Shape,
804        value: Peek<'_, '_>,
805    ) -> Result<bool, Self::Error> {
806        self.serialize_opaque_scalar_with_field(None, shape, value)
807    }
808
809    fn serialize_opaque_scalar_with_field(
810        &mut self,
811        field: Option<&facet_core::Field>,
812        shape: &'static facet_core::Shape,
813        value: Peek<'_, '_>,
814    ) -> Result<bool, Self::Error> {
815        if value.scalar_type().is_some() {
816            return Ok(false);
817        }
818
819        if let Some(adapter) = shape.opaque_adapter {
820            let mapped = unsafe { (adapter.serialize)(value.data()) };
821            let mapped_peek = unsafe { Peek::unchecked_new(mapped.ptr, mapped.shape) };
822            if has_trailing_attr(field) {
823                // Trailing opaque fields stream mapped payload directly (no outer length framing),
824                // preserving scatter-gather references for borrowed bytes.
825                serialize_root(self, mapped_peek).map_err(map_format_error)?;
826            } else {
827                let mut bytes = Vec::new();
828                let mut mapped_serializer = PostcardSerializer::new(CopyWriter::new(&mut bytes));
829                serialize_root(&mut mapped_serializer, mapped_peek).map_err(map_format_error)?;
830                self.write_bytes(&bytes)?;
831            }
832            return Ok(true);
833        }
834
835        // Camino types (UTF-8 paths)
836        #[cfg(feature = "camino")]
837        if shape.is_type::<camino::Utf8PathBuf>() {
838            use camino::Utf8PathBuf;
839            let path = value.get::<Utf8PathBuf>().map_err(|e| {
840                SerializeError::Custom(alloc::format!("Failed to get Utf8PathBuf: {}", e))
841            })?;
842            self.write_str(path.as_str())?;
843            return Ok(true);
844        }
845        #[cfg(feature = "camino")]
846        if shape.id == facet_core::Shape::id_of::<camino::Utf8Path>() {
847            use camino::Utf8Path;
848            let path = value.get::<Utf8Path>().map_err(|e| {
849                SerializeError::Custom(alloc::format!("Failed to get Utf8Path: {}", e))
850            })?;
851            self.write_str(path.as_str())?;
852            return Ok(true);
853        }
854
855        // UUID - serialize as 16 bytes (native format)
856        #[cfg(feature = "uuid")]
857        if shape.is_type::<uuid::Uuid>() {
858            use uuid::Uuid;
859            let uuid = value
860                .get::<Uuid>()
861                .map_err(|e| SerializeError::Custom(alloc::format!("Failed to get Uuid: {}", e)))?;
862            self.writer.write_bytes(uuid.as_bytes())?;
863            return Ok(true);
864        }
865
866        // ULID - serialize as 16 bytes (native format)
867        #[cfg(feature = "ulid")]
868        if shape.is_type::<ulid::Ulid>() {
869            use ulid::Ulid;
870            let ulid = value
871                .get::<Ulid>()
872                .map_err(|e| SerializeError::Custom(alloc::format!("Failed to get Ulid: {}", e)))?;
873            self.writer.write_bytes(&ulid.to_bytes())?;
874            return Ok(true);
875        }
876
877        // Jiff date/time types - serialize as RFC3339 strings
878        #[cfg(feature = "jiff02")]
879        if shape.is_type::<jiff::Zoned>() {
880            use jiff::Zoned;
881            let zoned = value.get::<Zoned>().map_err(|e| {
882                SerializeError::Custom(alloc::format!("Failed to get Zoned: {}", e))
883            })?;
884            self.write_str(&zoned.to_string())?;
885            return Ok(true);
886        }
887        #[cfg(feature = "jiff02")]
888        if shape.is_type::<jiff::Timestamp>() {
889            use jiff::Timestamp;
890            let ts = value.get::<Timestamp>().map_err(|e| {
891                SerializeError::Custom(alloc::format!("Failed to get Timestamp: {}", e))
892            })?;
893            self.write_str(&ts.to_string())?;
894            return Ok(true);
895        }
896        #[cfg(feature = "jiff02")]
897        if shape.is_type::<jiff::civil::DateTime>() {
898            use jiff::civil::DateTime;
899            let dt = value.get::<DateTime>().map_err(|e| {
900                SerializeError::Custom(alloc::format!("Failed to get DateTime: {}", e))
901            })?;
902            self.write_str(&dt.to_string())?;
903            return Ok(true);
904        }
905
906        // Chrono date/time types - serialize as RFC3339 strings
907        #[cfg(feature = "chrono")]
908        if shape.is_type::<chrono::DateTime<chrono::Utc>>() {
909            use chrono::{DateTime, SecondsFormat, Utc};
910            let dt = value.get::<DateTime<Utc>>().map_err(|e| {
911                SerializeError::Custom(alloc::format!("Failed to get DateTime<Utc>: {}", e))
912            })?;
913            self.write_str(&dt.to_rfc3339_opts(SecondsFormat::AutoSi, true))?;
914            return Ok(true);
915        }
916        #[cfg(feature = "chrono")]
917        if shape.is_type::<chrono::DateTime<chrono::Local>>() {
918            use chrono::{DateTime, Local, SecondsFormat};
919            let dt = value.get::<DateTime<Local>>().map_err(|e| {
920                SerializeError::Custom(alloc::format!("Failed to get DateTime<Local>: {}", e))
921            })?;
922            self.write_str(&dt.to_rfc3339_opts(SecondsFormat::AutoSi, false))?;
923            return Ok(true);
924        }
925        #[cfg(feature = "chrono")]
926        if shape.is_type::<chrono::DateTime<chrono::FixedOffset>>() {
927            use chrono::{DateTime, FixedOffset, SecondsFormat};
928            let dt = value.get::<DateTime<FixedOffset>>().map_err(|e| {
929                SerializeError::Custom(alloc::format!("Failed to get DateTime<FixedOffset>: {}", e))
930            })?;
931            self.write_str(&dt.to_rfc3339_opts(SecondsFormat::AutoSi, false))?;
932            return Ok(true);
933        }
934        #[cfg(feature = "chrono")]
935        if shape.is_type::<chrono::NaiveDateTime>() {
936            use chrono::NaiveDateTime;
937            let dt = value.get::<NaiveDateTime>().map_err(|e| {
938                SerializeError::Custom(alloc::format!("Failed to get NaiveDateTime: {}", e))
939            })?;
940            self.write_str(&dt.format("%Y-%m-%dT%H:%M:%S").to_string())?;
941            return Ok(true);
942        }
943        #[cfg(feature = "chrono")]
944        if shape.is_type::<chrono::NaiveDate>() {
945            use chrono::NaiveDate;
946            let date = value.get::<NaiveDate>().map_err(|e| {
947                SerializeError::Custom(alloc::format!("Failed to get NaiveDate: {}", e))
948            })?;
949            self.write_str(&date.to_string())?;
950            return Ok(true);
951        }
952        #[cfg(feature = "chrono")]
953        if shape.is_type::<chrono::NaiveTime>() {
954            use chrono::NaiveTime;
955            let time = value.get::<NaiveTime>().map_err(|e| {
956                SerializeError::Custom(alloc::format!("Failed to get NaiveTime: {}", e))
957            })?;
958            self.write_str(&time.to_string())?;
959            return Ok(true);
960        }
961
962        // Time crate date/time types - serialize as RFC3339 strings
963        #[cfg(feature = "time")]
964        if shape.is_type::<time::UtcDateTime>() {
965            use time::UtcDateTime;
966            let dt = value.get::<UtcDateTime>().map_err(|e| {
967                SerializeError::Custom(alloc::format!("Failed to get UtcDateTime: {}", e))
968            })?;
969            let s = dt
970                .format(&time::format_description::well_known::Rfc3339)
971                .unwrap_or_else(|_| "<invalid>".to_string());
972            self.write_str(&s)?;
973            return Ok(true);
974        }
975        #[cfg(feature = "time")]
976        if shape.is_type::<time::OffsetDateTime>() {
977            use time::OffsetDateTime;
978            let dt = value.get::<OffsetDateTime>().map_err(|e| {
979                SerializeError::Custom(alloc::format!("Failed to get OffsetDateTime: {}", e))
980            })?;
981            let s = dt
982                .format(&time::format_description::well_known::Rfc3339)
983                .unwrap_or_else(|_| "<invalid>".to_string());
984            self.write_str(&s)?;
985            return Ok(true);
986        }
987
988        // OrderedFloat - serialize as the inner float
989        #[cfg(feature = "ordered-float")]
990        if shape.is_type::<ordered_float::OrderedFloat<f32>>() {
991            use ordered_float::OrderedFloat;
992            let val = value.get::<OrderedFloat<f32>>().map_err(|e| {
993                SerializeError::Custom(alloc::format!("Failed to get OrderedFloat<f32>: {}", e))
994            })?;
995            self.writer.write_bytes(&val.0.to_le_bytes())?;
996            return Ok(true);
997        } else if shape.is_type::<ordered_float::OrderedFloat<f64>>() {
998            use ordered_float::OrderedFloat;
999            let val = value.get::<OrderedFloat<f64>>().map_err(|e| {
1000                SerializeError::Custom(alloc::format!("Failed to get OrderedFloat<f64>: {}", e))
1001            })?;
1002            self.writer.write_bytes(&val.0.to_le_bytes())?;
1003            return Ok(true);
1004        }
1005
1006        // NotNan - serialize as the inner float
1007        #[cfg(feature = "ordered-float")]
1008        if shape.is_type::<ordered_float::NotNan<f32>>() {
1009            use ordered_float::NotNan;
1010            let val = value.get::<NotNan<f32>>().map_err(|e| {
1011                SerializeError::Custom(alloc::format!("Failed to get NotNan<f32>: {}", e))
1012            })?;
1013            self.writer.write_bytes(&val.into_inner().to_le_bytes())?;
1014            return Ok(true);
1015        } else if shape.is_type::<ordered_float::NotNan<f64>>() {
1016            use ordered_float::NotNan;
1017            let val = value.get::<NotNan<f64>>().map_err(|e| {
1018                SerializeError::Custom(alloc::format!("Failed to get NotNan<f64>: {}", e))
1019            })?;
1020            self.writer.write_bytes(&val.into_inner().to_le_bytes())?;
1021            return Ok(true);
1022        }
1023
1024        // bytestring::ByteString
1025        #[cfg(feature = "bytestring")]
1026        if shape == <bytestring::ByteString as facet_core::Facet>::SHAPE {
1027            let bs = value.get::<bytestring::ByteString>().map_err(|e| {
1028                SerializeError::Custom(alloc::format!("Failed to get ByteString: {}", e))
1029            })?;
1030            self.write_str(bs.as_ref())?;
1031            return Ok(true);
1032        }
1033
1034        // compact_str::CompactString
1035        #[cfg(feature = "compact_str")]
1036        if shape == <compact_str::CompactString as facet_core::Facet>::SHAPE {
1037            let cs = value.get::<compact_str::CompactString>().map_err(|e| {
1038                SerializeError::Custom(alloc::format!("Failed to get CompactString: {}", e))
1039            })?;
1040            self.write_str(cs.as_str())?;
1041            return Ok(true);
1042        }
1043
1044        // smartstring::SmartString<LazyCompact>
1045        #[cfg(feature = "smartstring")]
1046        if shape == <smartstring::SmartString<smartstring::LazyCompact> as facet_core::Facet>::SHAPE
1047        {
1048            let ss = value
1049                .get::<smartstring::SmartString<smartstring::LazyCompact>>()
1050                .map_err(|e| {
1051                    SerializeError::Custom(alloc::format!("Failed to get SmartString: {}", e))
1052                })?;
1053            self.write_str(ss.as_str())?;
1054            return Ok(true);
1055        }
1056
1057        if shape.inner.is_some() {
1058            return Ok(false);
1059        }
1060
1061        // Fallback to string or Display for non-standard scalars.
1062        if matches!(shape.def, Def::Scalar) {
1063            if let Some(s) = value.as_str() {
1064                self.write_str(s)?;
1065                return Ok(true);
1066            }
1067            if shape.vtable.has_display() {
1068                let s = alloc::format!("{}", value);
1069                self.write_str(&s)?;
1070                return Ok(true);
1071            }
1072        }
1073
1074        Ok(false)
1075    }
1076}
1077
1078/// Write an unsigned varint (LEB128-like encoding used by postcard)
1079fn write_varint<W: Writer>(mut value: u64, writer: &mut W) -> Result<(), SerializeError> {
1080    loop {
1081        let mut byte = (value & 0x7F) as u8;
1082        value >>= 7;
1083        if value != 0 {
1084            byte |= 0x80;
1085        }
1086        writer.write_byte(byte)?;
1087        if value == 0 {
1088            break;
1089        }
1090    }
1091    Ok(())
1092}
1093
1094/// Write an unsigned 128-bit varint
1095fn write_varint_u128<W: Writer>(mut value: u128, writer: &mut W) -> Result<(), SerializeError> {
1096    loop {
1097        let mut byte = (value & 0x7F) as u8;
1098        value >>= 7;
1099        if value != 0 {
1100            byte |= 0x80;
1101        }
1102        writer.write_byte(byte)?;
1103        if value == 0 {
1104            break;
1105        }
1106    }
1107    Ok(())
1108}
1109
1110/// Write a signed varint using zigzag encoding
1111fn write_varint_signed<W: Writer>(value: i64, writer: &mut W) -> Result<(), SerializeError> {
1112    // Zigzag encoding: (value << 1) ^ (value >> 63)
1113    let encoded = ((value << 1) ^ (value >> 63)) as u64;
1114    write_varint(encoded, writer)
1115}
1116
1117/// Write a signed 128-bit varint using zigzag encoding
1118fn write_varint_signed_i128<W: Writer>(value: i128, writer: &mut W) -> Result<(), SerializeError> {
1119    // Zigzag encoding: (value << 1) ^ (value >> 127)
1120    let encoded = ((value << 1) ^ (value >> 127)) as u128;
1121    write_varint_u128(encoded, writer)
1122}
1123
1124#[cfg(test)]
1125mod tests {
1126    use super::*;
1127    use facet::Facet;
1128    use facet_value::{VArray, VBytes, VNumber, VObject, VString, Value};
1129    use postcard::to_allocvec as postcard_to_vec;
1130    use serde::Serialize;
1131
1132    #[derive(Facet, Serialize, PartialEq, Debug)]
1133    struct SimpleStruct {
1134        a: u32,
1135        b: alloc::string::String,
1136        c: bool,
1137    }
1138
1139    #[test]
1140    fn test_simple_struct() {
1141        facet_testhelpers::setup();
1142
1143        let value = SimpleStruct {
1144            a: 123,
1145            b: "hello".into(),
1146            c: true,
1147        };
1148
1149        let facet_bytes = to_vec(&value).unwrap();
1150        let postcard_bytes = postcard_to_vec(&value).unwrap();
1151
1152        assert_eq!(facet_bytes, postcard_bytes);
1153    }
1154
1155    #[test]
1156    fn test_u8() {
1157        facet_testhelpers::setup();
1158
1159        #[derive(Facet, Serialize, PartialEq, Debug)]
1160        struct U8Struct {
1161            value: u8,
1162        }
1163
1164        let value = U8Struct { value: 42 };
1165        let facet_bytes = to_vec(&value).unwrap();
1166        let postcard_bytes = postcard_to_vec(&value).unwrap();
1167        assert_eq!(facet_bytes, postcard_bytes);
1168    }
1169
1170    #[test]
1171    fn test_i32() {
1172        facet_testhelpers::setup();
1173
1174        #[derive(Facet, Serialize, PartialEq, Debug)]
1175        struct I32Struct {
1176            value: i32,
1177        }
1178
1179        let value = I32Struct { value: -100000 };
1180        let facet_bytes = to_vec(&value).unwrap();
1181        let postcard_bytes = postcard_to_vec(&value).unwrap();
1182        assert_eq!(facet_bytes, postcard_bytes);
1183    }
1184
1185    #[test]
1186    fn test_string() {
1187        facet_testhelpers::setup();
1188
1189        #[derive(Facet, Serialize, PartialEq, Debug)]
1190        struct StringStruct {
1191            value: alloc::string::String,
1192        }
1193
1194        let value = StringStruct {
1195            value: "hello world".into(),
1196        };
1197        let facet_bytes = to_vec(&value).unwrap();
1198        let postcard_bytes = postcard_to_vec(&value).unwrap();
1199        assert_eq!(facet_bytes, postcard_bytes);
1200    }
1201
1202    #[test]
1203    fn test_vec() {
1204        facet_testhelpers::setup();
1205
1206        #[derive(Facet, Serialize, PartialEq, Debug)]
1207        struct VecStruct {
1208            values: Vec<u32>,
1209        }
1210
1211        let value = VecStruct {
1212            values: alloc::vec![1, 2, 3, 4, 5],
1213        };
1214        let facet_bytes = to_vec(&value).unwrap();
1215        let postcard_bytes = postcard_to_vec(&value).unwrap();
1216        assert_eq!(facet_bytes, postcard_bytes);
1217    }
1218
1219    #[test]
1220    fn test_vec_u8() {
1221        facet_testhelpers::setup();
1222
1223        #[derive(Facet, Serialize, PartialEq, Debug)]
1224        struct BytesStruct {
1225            data: Vec<u8>,
1226        }
1227
1228        let value = BytesStruct {
1229            data: alloc::vec![0, 1, 2, 3, 4, 5, 255, 128, 64],
1230        };
1231        let facet_bytes = to_vec(&value).unwrap();
1232        let postcard_bytes = postcard_to_vec(&value).unwrap();
1233        assert_eq!(facet_bytes, postcard_bytes);
1234
1235        // Also test the roundtrip
1236        let decoded: BytesStruct = crate::from_slice(&facet_bytes).unwrap();
1237        assert_eq!(decoded, value);
1238    }
1239
1240    #[test]
1241    fn test_vec_u8_large() {
1242        facet_testhelpers::setup();
1243
1244        #[derive(Facet, Serialize, PartialEq, Debug)]
1245        struct LargeBytes {
1246            data: Vec<u8>,
1247        }
1248
1249        // Test with a larger byte array to ensure bulk serialization works
1250        let value = LargeBytes {
1251            data: (0..1000).map(|i| (i % 256) as u8).collect(),
1252        };
1253        let facet_bytes = to_vec(&value).unwrap();
1254        let postcard_bytes = postcard_to_vec(&value).unwrap();
1255        assert_eq!(facet_bytes, postcard_bytes);
1256
1257        // Also test the roundtrip
1258        let decoded: LargeBytes = crate::from_slice(&facet_bytes).unwrap();
1259        assert_eq!(decoded, value);
1260    }
1261
1262    #[test]
1263    fn test_vec_u8_empty() {
1264        facet_testhelpers::setup();
1265
1266        #[derive(Facet, Serialize, PartialEq, Debug)]
1267        struct EmptyBytes {
1268            data: Vec<u8>,
1269        }
1270
1271        let value = EmptyBytes {
1272            data: alloc::vec![],
1273        };
1274        let facet_bytes = to_vec(&value).unwrap();
1275        let postcard_bytes = postcard_to_vec(&value).unwrap();
1276        assert_eq!(facet_bytes, postcard_bytes);
1277
1278        // Also test the roundtrip
1279        let decoded: EmptyBytes = crate::from_slice(&facet_bytes).unwrap();
1280        assert_eq!(decoded, value);
1281    }
1282
1283    #[test]
1284    fn test_option_some() {
1285        facet_testhelpers::setup();
1286
1287        #[derive(Facet, Serialize, PartialEq, Debug)]
1288        struct OptionStruct {
1289            value: Option<u32>,
1290        }
1291
1292        let value = OptionStruct { value: Some(42) };
1293        let facet_bytes = to_vec(&value).unwrap();
1294        let postcard_bytes = postcard_to_vec(&value).unwrap();
1295        assert_eq!(facet_bytes, postcard_bytes);
1296    }
1297
1298    #[test]
1299    fn test_option_none() {
1300        facet_testhelpers::setup();
1301
1302        #[derive(Facet, Serialize, PartialEq, Debug)]
1303        struct OptionStruct {
1304            value: Option<u32>,
1305        }
1306
1307        let value = OptionStruct { value: None };
1308        let facet_bytes = to_vec(&value).unwrap();
1309        let postcard_bytes = postcard_to_vec(&value).unwrap();
1310        assert_eq!(facet_bytes, postcard_bytes);
1311    }
1312
1313    #[test]
1314    fn test_unit_enum() {
1315        facet_testhelpers::setup();
1316
1317        #[derive(Facet, Serialize, PartialEq, Debug)]
1318        #[repr(C)]
1319        enum Color {
1320            Red,
1321            Green,
1322            Blue,
1323        }
1324
1325        let facet_bytes = to_vec(&Color::Red).unwrap();
1326        let postcard_bytes = postcard_to_vec(&Color::Red).unwrap();
1327        assert_eq!(facet_bytes, postcard_bytes);
1328
1329        let facet_bytes = to_vec(&Color::Green).unwrap();
1330        let postcard_bytes = postcard_to_vec(&Color::Green).unwrap();
1331        assert_eq!(facet_bytes, postcard_bytes);
1332
1333        let facet_bytes = to_vec(&Color::Blue).unwrap();
1334        let postcard_bytes = postcard_to_vec(&Color::Blue).unwrap();
1335        assert_eq!(facet_bytes, postcard_bytes);
1336    }
1337
1338    #[test]
1339    fn test_tuple_enum() {
1340        facet_testhelpers::setup();
1341
1342        #[derive(Facet, Serialize, PartialEq, Debug)]
1343        #[repr(C)]
1344        enum Value {
1345            Int(i32),
1346            Text(alloc::string::String),
1347        }
1348
1349        let facet_bytes = to_vec(&Value::Int(42)).unwrap();
1350        let postcard_bytes = postcard_to_vec(&Value::Int(42)).unwrap();
1351        assert_eq!(facet_bytes, postcard_bytes);
1352
1353        let facet_bytes = to_vec(&Value::Text("hello".into())).unwrap();
1354        let postcard_bytes = postcard_to_vec(&Value::Text("hello".into())).unwrap();
1355        assert_eq!(facet_bytes, postcard_bytes);
1356    }
1357
1358    #[test]
1359    fn test_struct_enum() {
1360        facet_testhelpers::setup();
1361
1362        #[derive(Facet, Serialize, PartialEq, Debug)]
1363        #[repr(C)]
1364        enum Message {
1365            Quit,
1366            Move { x: i32, y: i32 },
1367        }
1368
1369        let facet_bytes = to_vec(&Message::Quit).unwrap();
1370        let postcard_bytes = postcard_to_vec(&Message::Quit).unwrap();
1371        assert_eq!(facet_bytes, postcard_bytes);
1372
1373        let facet_bytes = to_vec(&Message::Move { x: 10, y: 20 }).unwrap();
1374        let postcard_bytes = postcard_to_vec(&Message::Move { x: 10, y: 20 }).unwrap();
1375        assert_eq!(facet_bytes, postcard_bytes);
1376    }
1377
1378    #[test]
1379    fn test_to_writer_fallible() {
1380        facet_testhelpers::setup();
1381
1382        struct CustomWriter {
1383            buffer: Vec<u8>,
1384        }
1385
1386        impl Writer for CustomWriter {
1387            fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
1388                self.buffer.push(byte);
1389                Ok(())
1390            }
1391
1392            fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
1393                self.buffer.extend_from_slice(bytes);
1394                Ok(())
1395            }
1396        }
1397
1398        let value = SimpleStruct {
1399            a: 123,
1400            b: "hello".into(),
1401            c: true,
1402        };
1403
1404        let mut writer = CustomWriter { buffer: Vec::new() };
1405        to_writer_fallible(&value, &mut writer).unwrap();
1406
1407        let postcard_bytes = postcard_to_vec(&value).unwrap();
1408        assert_eq!(writer.buffer, postcard_bytes);
1409    }
1410
1411    #[test]
1412    fn test_value_roundtrip() {
1413        facet_testhelpers::setup();
1414
1415        let mut array = VArray::new();
1416        array.push(Value::from(VNumber::from_i64(1)));
1417        array.push(Value::from(VString::new("two")));
1418        array.push(Value::TRUE);
1419
1420        let mut object = VObject::new();
1421        object.insert("n", Value::from(VNumber::from_u64(42)));
1422        object.insert("s", Value::from(VString::new("hello")));
1423        object.insert("b", Value::from(VBytes::new(&[1, 2, 3])));
1424        object.insert("a", Value::from(array));
1425
1426        let value = Value::from(object);
1427        let bytes = to_vec(&value).unwrap();
1428        let decoded: Value = crate::from_slice(&bytes).unwrap();
1429
1430        assert_eq!(decoded, value);
1431    }
1432
1433    #[test]
1434    fn test_to_vec_with_shape_struct() {
1435        facet_testhelpers::setup();
1436
1437        #[derive(Debug, Facet, PartialEq, Serialize)]
1438        struct Point {
1439            x: i32,
1440            y: i32,
1441        }
1442
1443        // Parse JSON into a Value
1444        let value: Value = facet_json::from_str(r#"{"x": 10, "y": 20}"#).unwrap();
1445
1446        // Serialize using Point's shape - produces postcard bytes for Point, not Value
1447        let bytes = to_vec_with_shape(&value, Point::SHAPE).unwrap();
1448
1449        // Verify it matches what we'd get from serializing Point directly
1450        let expected = to_vec(&Point { x: 10, y: 20 }).unwrap();
1451        assert_eq!(bytes, expected);
1452
1453        // Deserialize back into a typed Point
1454        let point: Point = crate::from_slice(&bytes).unwrap();
1455        assert_eq!(point, Point { x: 10, y: 20 });
1456    }
1457
1458    #[test]
1459    fn test_to_vec_with_shape_vec() {
1460        facet_testhelpers::setup();
1461
1462        // Parse JSON array into a Value
1463        let value: Value = facet_json::from_str(r#"[1, 2, 3, 4, 5]"#).unwrap();
1464
1465        // Serialize using Vec<i32>'s shape
1466        let bytes = to_vec_with_shape(&value, <Vec<i32>>::SHAPE).unwrap();
1467
1468        // Verify it matches what we'd get from serializing Vec<i32> directly
1469        let expected = to_vec(&alloc::vec![1i32, 2, 3, 4, 5]).unwrap();
1470        assert_eq!(bytes, expected);
1471
1472        // Deserialize back
1473        let result: Vec<i32> = crate::from_slice(&bytes).unwrap();
1474        assert_eq!(result, alloc::vec![1, 2, 3, 4, 5]);
1475    }
1476
1477    #[test]
1478    fn test_to_vec_with_shape_nested() {
1479        facet_testhelpers::setup();
1480
1481        #[derive(Debug, Facet, PartialEq, Serialize)]
1482        struct Nested {
1483            items: Vec<Item>,
1484        }
1485
1486        #[derive(Debug, Facet, PartialEq, Serialize)]
1487        struct Item {
1488            name: alloc::string::String,
1489            count: u32,
1490        }
1491
1492        // Parse JSON into a Value
1493        let value: Value = facet_json::from_str(
1494            r#"{"items": [{"name": "foo", "count": 10}, {"name": "bar", "count": 20}]}"#,
1495        )
1496        .unwrap();
1497
1498        // Serialize using Nested's shape
1499        let bytes = to_vec_with_shape(&value, Nested::SHAPE).unwrap();
1500
1501        // Deserialize back
1502        let result: Nested = crate::from_slice(&bytes).unwrap();
1503        assert_eq!(
1504            result,
1505            Nested {
1506                items: alloc::vec![
1507                    Item {
1508                        name: "foo".into(),
1509                        count: 10
1510                    },
1511                    Item {
1512                        name: "bar".into(),
1513                        count: 20
1514                    }
1515                ]
1516            }
1517        );
1518    }
1519
1520    #[test]
1521    fn test_to_vec_with_shape_roundtrip() {
1522        facet_testhelpers::setup();
1523
1524        #[derive(Debug, Facet, PartialEq, Serialize)]
1525        struct Config {
1526            name: alloc::string::String,
1527            enabled: bool,
1528            count: u32,
1529        }
1530
1531        // Original typed value
1532        let original = Config {
1533            name: "test".into(),
1534            enabled: true,
1535            count: 42,
1536        };
1537
1538        // Serialize to postcard
1539        let typed_bytes = to_vec(&original).unwrap();
1540
1541        // Deserialize into Value using from_slice_with_shape
1542        let value: Value = crate::from_slice_with_shape(&typed_bytes, Config::SHAPE).unwrap();
1543
1544        // Serialize back using to_vec_with_shape
1545        let value_bytes = to_vec_with_shape(&value, Config::SHAPE).unwrap();
1546
1547        // The bytes should match
1548        assert_eq!(typed_bytes, value_bytes);
1549
1550        // And we should be able to deserialize back to the original type
1551        let roundtrip: Config = crate::from_slice(&value_bytes).unwrap();
1552        assert_eq!(roundtrip, original);
1553    }
1554
1555    #[test]
1556    fn test_value_in_tuple() {
1557        facet_testhelpers::setup();
1558
1559        // Test that Value can be serialized/deserialized as part of a tuple
1560        // This tests the hint_dynamic_value() fix for struct fields
1561        let tuple: (u64, alloc::string::String, Value) =
1562            (42, "hello".into(), Value::from(VNumber::from_i64(123)));
1563
1564        let bytes = to_vec(&tuple).unwrap();
1565        let decoded: (u64, alloc::string::String, Value) = crate::from_slice(&bytes).unwrap();
1566
1567        assert_eq!(decoded.0, 42);
1568        assert_eq!(decoded.1, "hello");
1569        assert_eq!(decoded.2, Value::from(VNumber::from_i64(123)));
1570    }
1571
1572    #[test]
1573    fn test_value_in_struct() {
1574        facet_testhelpers::setup();
1575
1576        #[derive(Debug, Facet, PartialEq)]
1577        struct WithValue {
1578            id: u64,
1579            name: alloc::string::String,
1580            data: Value,
1581        }
1582
1583        let original = WithValue {
1584            id: 1,
1585            name: "test".into(),
1586            data: Value::from(VObject::from_iter([(
1587                "key".to_string(),
1588                Value::from(VString::new("value")),
1589            )])),
1590        };
1591
1592        let bytes = to_vec(&original).unwrap();
1593        let decoded: WithValue = crate::from_slice(&bytes).unwrap();
1594
1595        assert_eq!(decoded, original);
1596    }
1597
1598    #[test]
1599    fn test_value_nested_in_struct() {
1600        facet_testhelpers::setup();
1601
1602        #[derive(Debug, Facet, PartialEq)]
1603        struct Outer {
1604            before: u32,
1605            value: Value,
1606            after: u32,
1607        }
1608
1609        // Test with object value
1610        let mut obj = VObject::new();
1611        obj.insert("nested", Value::from(VNumber::from_i64(99)));
1612        obj.insert("str", Value::from(VString::new("test")));
1613
1614        let original = Outer {
1615            before: 10,
1616            value: Value::from(obj),
1617            after: 20,
1618        };
1619
1620        let bytes = to_vec(&original).unwrap();
1621        let decoded: Outer = crate::from_slice(&bytes).unwrap();
1622        assert_eq!(decoded, original);
1623
1624        // Test with array value
1625        let mut arr = VArray::new();
1626        arr.push(Value::from(VNumber::from_i64(1)));
1627        arr.push(Value::from(VString::new("two")));
1628        arr.push(Value::TRUE);
1629
1630        let original = Outer {
1631            before: 100,
1632            value: Value::from(arr),
1633            after: 200,
1634        };
1635
1636        let bytes = to_vec(&original).unwrap();
1637        let decoded: Outer = crate::from_slice(&bytes).unwrap();
1638        assert_eq!(decoded, original);
1639    }
1640
1641    /// Regression test for https://github.com/facet-rs/facet/issues/1836
1642    ///
1643    /// The `skip_all_unless_truthy` attribute was causing fields to be skipped
1644    /// during serialization, breaking roundtrip for binary formats like postcard
1645    /// where fields are identified by position rather than name.
1646    #[test]
1647    fn test_skip_all_unless_truthy_roundtrip() {
1648        facet_testhelpers::setup();
1649
1650        #[derive(Debug, Clone, PartialEq, Facet)]
1651        #[facet(skip_all_unless_truthy)]
1652        pub struct Value {
1653            pub tag: Option<alloc::string::String>,
1654            pub payload: Option<alloc::string::String>,
1655        }
1656
1657        // Test case from the issue: first field is None, second is Some
1658        let v = Value {
1659            tag: None,
1660            payload: Some("hello".into()),
1661        };
1662
1663        let bytes = to_vec(&v).expect("serialize");
1664        let v2: Value = crate::from_slice(&bytes).expect("deserialize");
1665        assert_eq!(v, v2);
1666
1667        // Also test all None
1668        let v = Value {
1669            tag: None,
1670            payload: None,
1671        };
1672        let bytes = to_vec(&v).expect("serialize");
1673        let v2: Value = crate::from_slice(&bytes).expect("deserialize");
1674        assert_eq!(v, v2);
1675
1676        // Also test all Some
1677        let v = Value {
1678            tag: Some("mytag".into()),
1679            payload: Some("mypayload".into()),
1680        };
1681        let bytes = to_vec(&v).expect("serialize");
1682        let v2: Value = crate::from_slice(&bytes).expect("deserialize");
1683        assert_eq!(v, v2);
1684
1685        // Also test first Some, second None
1686        let v = Value {
1687            tag: Some("mytag".into()),
1688            payload: None,
1689        };
1690        let bytes = to_vec(&v).expect("serialize");
1691        let v2: Value = crate::from_slice(&bytes).expect("deserialize");
1692        assert_eq!(v, v2);
1693    }
1694}