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