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::vec::Vec;
14
15use facet_core::{Def, ScalarType};
16use facet_format::{
17    DynamicValueEncoding, DynamicValueTag, EnumVariantEncoding, FormatSerializer, MapEncoding,
18    SerializeError as FormatSerializeError, StructFieldMode, serialize_root,
19};
20use facet_reflect::Peek;
21
22use crate::error::SerializeError;
23
24/// A trait for writing bytes during serialization with error handling.
25///
26/// This trait enables custom serialization targets that can report errors,
27/// such as buffer overflow. It's designed to support use cases like buffer
28/// pooling where you need to detect when a fixed-size buffer is too small.
29///
30/// # Example
31///
32/// ```
33/// use facet_postcard::{Writer, SerializeError};
34///
35/// struct PooledWriter {
36///     buf: Vec<u8>,  // In practice, this would be from a buffer pool
37///     overflow: Option<Vec<u8>>,
38/// }
39///
40/// impl Writer for PooledWriter {
41///     fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
42///         // Try pooled buffer first, fall back to Vec on overflow
43///         if let Some(ref mut overflow) = self.overflow {
44///             overflow.push(byte);
45///         } else if self.buf.len() < self.buf.capacity() {
46///             self.buf.push(byte);
47///         } else {
48///             // Overflow - allocate Vec and transfer contents
49///             let mut overflow = Vec::new();
50///             overflow.extend_from_slice(&self.buf);
51///             overflow.push(byte);
52///             self.overflow = Some(overflow);
53///         }
54///         Ok(())
55///     }
56///
57///     fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
58///         if let Some(ref mut overflow) = self.overflow {
59///             overflow.extend_from_slice(bytes);
60///         } else if self.buf.len() + bytes.len() <= self.buf.capacity() {
61///             self.buf.extend_from_slice(bytes);
62///         } else {
63///             // Overflow - allocate Vec and transfer contents
64///             let mut overflow = Vec::new();
65///             overflow.extend_from_slice(&self.buf);
66///             overflow.extend_from_slice(bytes);
67///             self.overflow = Some(overflow);
68///         }
69///         Ok(())
70///     }
71/// }
72/// ```
73pub trait Writer {
74    /// Write a single byte to the writer.
75    fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError>;
76
77    /// Write a slice of bytes to the writer.
78    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError>;
79}
80
81impl Writer for Vec<u8> {
82    fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
83        self.push(byte);
84        Ok(())
85    }
86
87    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
88        self.extend_from_slice(bytes);
89        Ok(())
90    }
91}
92
93/// Serializes any Facet type to postcard bytes.
94///
95/// # Example
96/// ```
97/// use facet::Facet;
98/// use facet_postcard::to_vec;
99///
100/// #[derive(Debug, Facet)]
101/// struct Point {
102///     x: i32,
103///     y: i32,
104/// }
105///
106/// let point = Point { x: 10, y: 20 };
107/// let bytes = to_vec(&point).unwrap();
108/// ```
109pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, SerializeError>
110where
111    T: facet_core::Facet<'static>,
112{
113    let mut buffer = Vec::new();
114    to_writer_fallible(value, &mut buffer)?;
115    Ok(buffer)
116}
117
118/// Serializes any Facet type to a custom writer implementing the fallible `Writer` trait.
119///
120/// This function allows external crates to implement custom serialization targets
121/// that can report errors, such as buffer overflow. This is useful for use cases
122/// like buffer pooling where you need to detect when a fixed-size buffer is too
123/// small and transparently fall back to heap allocation.
124///
125/// # Example
126/// ```
127/// use facet::Facet;
128/// use facet_postcard::{to_writer_fallible, Writer, SerializeError};
129///
130/// #[derive(Debug, Facet)]
131/// struct Point {
132///     x: i32,
133///     y: i32,
134/// }
135///
136/// struct CustomWriter {
137///     buffer: Vec<u8>,
138/// }
139///
140/// impl Writer for CustomWriter {
141///     fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
142///         self.buffer.push(byte);
143///         Ok(())
144///     }
145///
146///     fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
147///         self.buffer.extend_from_slice(bytes);
148///         Ok(())
149///     }
150/// }
151///
152/// let point = Point { x: 10, y: 20 };
153/// let mut writer = CustomWriter { buffer: Vec::new() };
154/// to_writer_fallible(&point, &mut writer).unwrap();
155/// ```
156pub fn to_writer_fallible<T, W>(value: &T, writer: &mut W) -> Result<(), SerializeError>
157where
158    T: facet_core::Facet<'static>,
159    W: Writer,
160{
161    let peek = Peek::new(value);
162    let mut serializer = PostcardSerializer::new(writer);
163    serialize_root(&mut serializer, peek).map_err(map_format_error)
164}
165
166/// Serializes a [`Peek`] reference to postcard bytes.
167///
168/// This is useful when you have a type-erased reference via reflection
169/// and need to serialize it without knowing the concrete type at compile time.
170///
171/// # Example
172/// ```
173/// use facet::Facet;
174/// use facet_reflect::Peek;
175/// use facet_postcard::peek_to_vec;
176///
177/// #[derive(Debug, Facet)]
178/// struct Point {
179///     x: i32,
180///     y: i32,
181/// }
182///
183/// let point = Point { x: 10, y: 20 };
184/// let peek = Peek::new(&point);
185/// let bytes = peek_to_vec(peek).unwrap();
186/// ```
187pub fn peek_to_vec(peek: Peek<'_, '_>) -> Result<Vec<u8>, SerializeError> {
188    let mut buffer = Vec::new();
189    let mut serializer = PostcardSerializer::new(&mut buffer);
190    serialize_root(&mut serializer, peek).map_err(map_format_error)?;
191    Ok(buffer)
192}
193
194fn map_format_error(error: FormatSerializeError<SerializeError>) -> SerializeError {
195    match error {
196        FormatSerializeError::Backend(err) => err,
197        FormatSerializeError::Reflect(err) => SerializeError::Custom(alloc::format!("{err}")),
198        FormatSerializeError::Unsupported(message) => SerializeError::Custom(message.into_owned()),
199        FormatSerializeError::Internal(message) => SerializeError::Custom(message.into_owned()),
200    }
201}
202
203struct PostcardSerializer<'a, W> {
204    writer: &'a mut W,
205}
206
207impl<'a, W> PostcardSerializer<'a, W> {
208    fn new(writer: &'a mut W) -> Self {
209        Self { writer }
210    }
211
212    fn write_str(&mut self, s: &str) -> Result<(), SerializeError>
213    where
214        W: Writer,
215    {
216        write_varint(s.len() as u64, self.writer)?;
217        self.writer.write_bytes(s.as_bytes())
218    }
219
220    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError>
221    where
222        W: Writer,
223    {
224        write_varint(bytes.len() as u64, self.writer)?;
225        self.writer.write_bytes(bytes)
226    }
227
228    fn write_dynamic_tag(&mut self, tag: DynamicValueTag) -> Result<(), SerializeError>
229    where
230        W: Writer,
231    {
232        let byte = match tag {
233            DynamicValueTag::Null => 0,
234            DynamicValueTag::Bool => 1,
235            DynamicValueTag::I64 => 2,
236            DynamicValueTag::U64 => 3,
237            DynamicValueTag::F64 => 4,
238            DynamicValueTag::String => 5,
239            DynamicValueTag::Bytes => 6,
240            DynamicValueTag::Array => 7,
241            DynamicValueTag::Object => 8,
242            DynamicValueTag::DateTime => 9,
243        };
244        self.writer.write_byte(byte)
245    }
246}
247
248impl<W: Writer> FormatSerializer for PostcardSerializer<'_, W> {
249    type Error = SerializeError;
250
251    fn begin_struct(&mut self) -> Result<(), Self::Error> {
252        Ok(())
253    }
254
255    fn field_key(&mut self, _key: &str) -> Result<(), Self::Error> {
256        Err(SerializeError::Custom(
257            "postcard does not support named fields".into(),
258        ))
259    }
260
261    fn end_struct(&mut self) -> Result<(), Self::Error> {
262        Ok(())
263    }
264
265    fn begin_seq(&mut self) -> Result<(), Self::Error> {
266        Ok(())
267    }
268
269    fn end_seq(&mut self) -> Result<(), Self::Error> {
270        Ok(())
271    }
272
273    fn scalar(&mut self, scalar: facet_format::ScalarValue<'_>) -> Result<(), Self::Error> {
274        match scalar {
275            facet_format::ScalarValue::Null => Ok(()),
276            facet_format::ScalarValue::Bool(v) => self.writer.write_byte(if v { 1 } else { 0 }),
277            facet_format::ScalarValue::Char(c) => {
278                // Postcard encodes char as UTF-8
279                let mut buf = [0u8; 4];
280                let s = c.encode_utf8(&mut buf);
281                self.write_str(s)
282            }
283            facet_format::ScalarValue::I64(n) => write_varint_signed(n, self.writer),
284            facet_format::ScalarValue::U64(n) => write_varint(n, self.writer),
285            facet_format::ScalarValue::I128(n) => write_varint_signed_i128(n, self.writer),
286            facet_format::ScalarValue::U128(n) => write_varint_u128(n, self.writer),
287            facet_format::ScalarValue::F64(n) => self.writer.write_bytes(&n.to_le_bytes()),
288            facet_format::ScalarValue::Str(s) | facet_format::ScalarValue::StringlyTyped(s) => {
289                self.write_str(&s)
290            }
291            facet_format::ScalarValue::Bytes(bytes) => self.write_bytes(&bytes),
292        }
293    }
294
295    fn struct_field_mode(&self) -> StructFieldMode {
296        StructFieldMode::Unnamed
297    }
298
299    fn map_encoding(&self) -> MapEncoding {
300        MapEncoding::Pairs
301    }
302
303    fn enum_variant_encoding(&self) -> EnumVariantEncoding {
304        EnumVariantEncoding::Index
305    }
306
307    fn dynamic_value_encoding(&self) -> DynamicValueEncoding {
308        DynamicValueEncoding::Tagged
309    }
310
311    fn dynamic_value_tag(&mut self, tag: DynamicValueTag) -> Result<(), Self::Error> {
312        self.write_dynamic_tag(tag)
313    }
314
315    fn begin_seq_with_len(&mut self, len: usize) -> Result<(), Self::Error> {
316        write_varint(len as u64, self.writer)
317    }
318
319    fn begin_map_with_len(&mut self, len: usize) -> Result<(), Self::Error> {
320        write_varint(len as u64, self.writer)
321    }
322
323    fn end_map(&mut self) -> Result<(), Self::Error> {
324        Ok(())
325    }
326
327    fn typed_scalar(
328        &mut self,
329        scalar_type: ScalarType,
330        value: Peek<'_, '_>,
331    ) -> Result<(), Self::Error> {
332        match scalar_type {
333            ScalarType::Unit => Ok(()),
334            ScalarType::Bool => {
335                let v = *value.get::<bool>().map_err(|e| {
336                    SerializeError::Custom(alloc::format!("Failed to get bool: {}", e))
337                })?;
338                self.writer.write_byte(if v { 1 } else { 0 })
339            }
340            ScalarType::Char => {
341                let c = *value.get::<char>().map_err(|e| {
342                    SerializeError::Custom(alloc::format!("Failed to get char: {}", e))
343                })?;
344                let mut buf = [0u8; 4];
345                let s = c.encode_utf8(&mut buf);
346                self.write_str(s)
347            }
348            ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
349                let s = value
350                    .as_str()
351                    .ok_or_else(|| SerializeError::Custom("Failed to get string value".into()))?;
352                self.write_str(s)
353            }
354            ScalarType::F32 => {
355                let v = *value.get::<f32>().map_err(|e| {
356                    SerializeError::Custom(alloc::format!("Failed to get f32: {}", e))
357                })?;
358                self.writer.write_bytes(&v.to_le_bytes())
359            }
360            ScalarType::F64 => {
361                let v = *value.get::<f64>().map_err(|e| {
362                    SerializeError::Custom(alloc::format!("Failed to get f64: {}", e))
363                })?;
364                self.writer.write_bytes(&v.to_le_bytes())
365            }
366            ScalarType::U8 => {
367                let v = *value.get::<u8>().map_err(|e| {
368                    SerializeError::Custom(alloc::format!("Failed to get u8: {}", e))
369                })?;
370                self.writer.write_byte(v)
371            }
372            ScalarType::U16 => {
373                let v = *value.get::<u16>().map_err(|e| {
374                    SerializeError::Custom(alloc::format!("Failed to get u16: {}", e))
375                })?;
376                write_varint(v as u64, self.writer)
377            }
378            ScalarType::U32 => {
379                let v = *value.get::<u32>().map_err(|e| {
380                    SerializeError::Custom(alloc::format!("Failed to get u32: {}", e))
381                })?;
382                write_varint(v as u64, self.writer)
383            }
384            ScalarType::U64 => {
385                let v = *value.get::<u64>().map_err(|e| {
386                    SerializeError::Custom(alloc::format!("Failed to get u64: {}", e))
387                })?;
388                write_varint(v, self.writer)
389            }
390            ScalarType::U128 => {
391                let v = *value.get::<u128>().map_err(|e| {
392                    SerializeError::Custom(alloc::format!("Failed to get u128: {}", e))
393                })?;
394                write_varint_u128(v, self.writer)
395            }
396            ScalarType::USize => {
397                let v = *value.get::<usize>().map_err(|e| {
398                    SerializeError::Custom(alloc::format!("Failed to get usize: {}", e))
399                })?;
400                write_varint(v as u64, self.writer)
401            }
402            ScalarType::I8 => {
403                let v = *value.get::<i8>().map_err(|e| {
404                    SerializeError::Custom(alloc::format!("Failed to get i8: {}", e))
405                })?;
406                self.writer.write_byte(v as u8)
407            }
408            ScalarType::I16 => {
409                let v = *value.get::<i16>().map_err(|e| {
410                    SerializeError::Custom(alloc::format!("Failed to get i16: {}", e))
411                })?;
412                write_varint_signed(v as i64, self.writer)
413            }
414            ScalarType::I32 => {
415                let v = *value.get::<i32>().map_err(|e| {
416                    SerializeError::Custom(alloc::format!("Failed to get i32: {}", e))
417                })?;
418                write_varint_signed(v as i64, self.writer)
419            }
420            ScalarType::I64 => {
421                let v = *value.get::<i64>().map_err(|e| {
422                    SerializeError::Custom(alloc::format!("Failed to get i64: {}", e))
423                })?;
424                write_varint_signed(v, self.writer)
425            }
426            ScalarType::I128 => {
427                let v = *value.get::<i128>().map_err(|e| {
428                    SerializeError::Custom(alloc::format!("Failed to get i128: {}", e))
429                })?;
430                write_varint_signed_i128(v, self.writer)
431            }
432            ScalarType::ISize => {
433                let v = *value.get::<isize>().map_err(|e| {
434                    SerializeError::Custom(alloc::format!("Failed to get isize: {}", e))
435                })?;
436                write_varint_signed(v as i64, self.writer)
437            }
438            #[cfg(feature = "net")]
439            ScalarType::SocketAddr => {
440                let v = *value.get::<core::net::SocketAddr>().map_err(|e| {
441                    SerializeError::Custom(alloc::format!("Failed to get SocketAddr: {}", e))
442                })?;
443                self.write_str(&v.to_string())
444            }
445            #[cfg(feature = "net")]
446            ScalarType::IpAddr => {
447                let v = *value.get::<core::net::IpAddr>().map_err(|e| {
448                    SerializeError::Custom(alloc::format!("Failed to get IpAddr: {}", e))
449                })?;
450                self.write_str(&v.to_string())
451            }
452            #[cfg(feature = "net")]
453            ScalarType::Ipv4Addr => {
454                let v = *value.get::<core::net::Ipv4Addr>().map_err(|e| {
455                    SerializeError::Custom(alloc::format!("Failed to get Ipv4Addr: {}", e))
456                })?;
457                self.write_str(&v.to_string())
458            }
459            #[cfg(feature = "net")]
460            ScalarType::Ipv6Addr => {
461                let v = *value.get::<core::net::Ipv6Addr>().map_err(|e| {
462                    SerializeError::Custom(alloc::format!("Failed to get Ipv6Addr: {}", e))
463                })?;
464                self.write_str(&v.to_string())
465            }
466            _ => Err(SerializeError::Custom(alloc::format!(
467                "Unsupported scalar type: {:?}",
468                scalar_type
469            ))),
470        }
471    }
472
473    fn begin_option_some(&mut self) -> Result<(), Self::Error> {
474        self.writer.write_byte(1)
475    }
476
477    fn serialize_none(&mut self) -> Result<(), Self::Error> {
478        self.writer.write_byte(0)
479    }
480
481    fn begin_enum_variant(
482        &mut self,
483        variant_index: usize,
484        _variant_name: &'static str,
485    ) -> Result<(), Self::Error> {
486        write_varint(variant_index as u64, self.writer)
487    }
488
489    fn serialize_opaque_scalar(
490        &mut self,
491        shape: &'static facet_core::Shape,
492        value: Peek<'_, '_>,
493    ) -> Result<bool, Self::Error> {
494        if value.scalar_type().is_some() {
495            return Ok(false);
496        }
497
498        // Camino types (UTF-8 paths)
499        #[cfg(feature = "camino")]
500        if shape.is_type::<camino::Utf8PathBuf>() {
501            use camino::Utf8PathBuf;
502            let path = value.get::<Utf8PathBuf>().map_err(|e| {
503                SerializeError::Custom(alloc::format!("Failed to get Utf8PathBuf: {}", e))
504            })?;
505            self.write_str(path.as_str())?;
506            return Ok(true);
507        }
508        #[cfg(feature = "camino")]
509        if shape.id == facet_core::Shape::id_of::<camino::Utf8Path>() {
510            use camino::Utf8Path;
511            let path = value.get::<Utf8Path>().map_err(|e| {
512                SerializeError::Custom(alloc::format!("Failed to get Utf8Path: {}", e))
513            })?;
514            self.write_str(path.as_str())?;
515            return Ok(true);
516        }
517
518        // UUID - serialize as 16 bytes (native format)
519        #[cfg(feature = "uuid")]
520        if shape.is_type::<uuid::Uuid>() {
521            use uuid::Uuid;
522            let uuid = value
523                .get::<Uuid>()
524                .map_err(|e| SerializeError::Custom(alloc::format!("Failed to get Uuid: {}", e)))?;
525            self.writer.write_bytes(uuid.as_bytes())?;
526            return Ok(true);
527        }
528
529        // ULID - serialize as 16 bytes (native format)
530        #[cfg(feature = "ulid")]
531        if shape.is_type::<ulid::Ulid>() {
532            use ulid::Ulid;
533            let ulid = value
534                .get::<Ulid>()
535                .map_err(|e| SerializeError::Custom(alloc::format!("Failed to get Ulid: {}", e)))?;
536            self.writer.write_bytes(&ulid.to_bytes())?;
537            return Ok(true);
538        }
539
540        // Jiff date/time types - serialize as RFC3339 strings
541        #[cfg(feature = "jiff02")]
542        if shape.is_type::<jiff::Zoned>() {
543            use jiff::Zoned;
544            let zoned = value.get::<Zoned>().map_err(|e| {
545                SerializeError::Custom(alloc::format!("Failed to get Zoned: {}", e))
546            })?;
547            self.write_str(&zoned.to_string())?;
548            return Ok(true);
549        }
550        #[cfg(feature = "jiff02")]
551        if shape.is_type::<jiff::Timestamp>() {
552            use jiff::Timestamp;
553            let ts = value.get::<Timestamp>().map_err(|e| {
554                SerializeError::Custom(alloc::format!("Failed to get Timestamp: {}", e))
555            })?;
556            self.write_str(&ts.to_string())?;
557            return Ok(true);
558        }
559        #[cfg(feature = "jiff02")]
560        if shape.is_type::<jiff::civil::DateTime>() {
561            use jiff::civil::DateTime;
562            let dt = value.get::<DateTime>().map_err(|e| {
563                SerializeError::Custom(alloc::format!("Failed to get DateTime: {}", e))
564            })?;
565            self.write_str(&dt.to_string())?;
566            return Ok(true);
567        }
568
569        // Chrono date/time types - serialize as RFC3339 strings
570        #[cfg(feature = "chrono")]
571        if shape.is_type::<chrono::DateTime<chrono::Utc>>() {
572            use chrono::{DateTime, SecondsFormat, Utc};
573            let dt = value.get::<DateTime<Utc>>().map_err(|e| {
574                SerializeError::Custom(alloc::format!("Failed to get DateTime<Utc>: {}", e))
575            })?;
576            self.write_str(&dt.to_rfc3339_opts(SecondsFormat::AutoSi, true))?;
577            return Ok(true);
578        }
579        #[cfg(feature = "chrono")]
580        if shape.is_type::<chrono::DateTime<chrono::Local>>() {
581            use chrono::{DateTime, Local, SecondsFormat};
582            let dt = value.get::<DateTime<Local>>().map_err(|e| {
583                SerializeError::Custom(alloc::format!("Failed to get DateTime<Local>: {}", e))
584            })?;
585            self.write_str(&dt.to_rfc3339_opts(SecondsFormat::AutoSi, false))?;
586            return Ok(true);
587        }
588        #[cfg(feature = "chrono")]
589        if shape.is_type::<chrono::DateTime<chrono::FixedOffset>>() {
590            use chrono::{DateTime, FixedOffset, SecondsFormat};
591            let dt = value.get::<DateTime<FixedOffset>>().map_err(|e| {
592                SerializeError::Custom(alloc::format!("Failed to get DateTime<FixedOffset>: {}", e))
593            })?;
594            self.write_str(&dt.to_rfc3339_opts(SecondsFormat::AutoSi, false))?;
595            return Ok(true);
596        }
597        #[cfg(feature = "chrono")]
598        if shape.is_type::<chrono::NaiveDateTime>() {
599            use chrono::NaiveDateTime;
600            let dt = value.get::<NaiveDateTime>().map_err(|e| {
601                SerializeError::Custom(alloc::format!("Failed to get NaiveDateTime: {}", e))
602            })?;
603            self.write_str(&dt.format("%Y-%m-%dT%H:%M:%S").to_string())?;
604            return Ok(true);
605        }
606        #[cfg(feature = "chrono")]
607        if shape.is_type::<chrono::NaiveDate>() {
608            use chrono::NaiveDate;
609            let date = value.get::<NaiveDate>().map_err(|e| {
610                SerializeError::Custom(alloc::format!("Failed to get NaiveDate: {}", e))
611            })?;
612            self.write_str(&date.to_string())?;
613            return Ok(true);
614        }
615        #[cfg(feature = "chrono")]
616        if shape.is_type::<chrono::NaiveTime>() {
617            use chrono::NaiveTime;
618            let time = value.get::<NaiveTime>().map_err(|e| {
619                SerializeError::Custom(alloc::format!("Failed to get NaiveTime: {}", e))
620            })?;
621            self.write_str(&time.to_string())?;
622            return Ok(true);
623        }
624
625        // Time crate date/time types - serialize as RFC3339 strings
626        #[cfg(feature = "time")]
627        if shape.is_type::<time::UtcDateTime>() {
628            use time::UtcDateTime;
629            let dt = value.get::<UtcDateTime>().map_err(|e| {
630                SerializeError::Custom(alloc::format!("Failed to get UtcDateTime: {}", e))
631            })?;
632            let s = dt
633                .format(&time::format_description::well_known::Rfc3339)
634                .unwrap_or_else(|_| "<invalid>".to_string());
635            self.write_str(&s)?;
636            return Ok(true);
637        }
638        #[cfg(feature = "time")]
639        if shape.is_type::<time::OffsetDateTime>() {
640            use time::OffsetDateTime;
641            let dt = value.get::<OffsetDateTime>().map_err(|e| {
642                SerializeError::Custom(alloc::format!("Failed to get OffsetDateTime: {}", e))
643            })?;
644            let s = dt
645                .format(&time::format_description::well_known::Rfc3339)
646                .unwrap_or_else(|_| "<invalid>".to_string());
647            self.write_str(&s)?;
648            return Ok(true);
649        }
650
651        // OrderedFloat - serialize as the inner float
652        #[cfg(feature = "ordered-float")]
653        if shape.is_type::<ordered_float::OrderedFloat<f32>>() {
654            use ordered_float::OrderedFloat;
655            let val = value.get::<OrderedFloat<f32>>().map_err(|e| {
656                SerializeError::Custom(alloc::format!("Failed to get OrderedFloat<f32>: {}", e))
657            })?;
658            self.writer.write_bytes(&val.0.to_le_bytes())?;
659            return Ok(true);
660        } else if shape.is_type::<ordered_float::OrderedFloat<f64>>() {
661            use ordered_float::OrderedFloat;
662            let val = value.get::<OrderedFloat<f64>>().map_err(|e| {
663                SerializeError::Custom(alloc::format!("Failed to get OrderedFloat<f64>: {}", e))
664            })?;
665            self.writer.write_bytes(&val.0.to_le_bytes())?;
666            return Ok(true);
667        }
668
669        // NotNan - serialize as the inner float
670        #[cfg(feature = "ordered-float")]
671        if shape.is_type::<ordered_float::NotNan<f32>>() {
672            use ordered_float::NotNan;
673            let val = value.get::<NotNan<f32>>().map_err(|e| {
674                SerializeError::Custom(alloc::format!("Failed to get NotNan<f32>: {}", e))
675            })?;
676            self.writer.write_bytes(&val.into_inner().to_le_bytes())?;
677            return Ok(true);
678        } else if shape.is_type::<ordered_float::NotNan<f64>>() {
679            use ordered_float::NotNan;
680            let val = value.get::<NotNan<f64>>().map_err(|e| {
681                SerializeError::Custom(alloc::format!("Failed to get NotNan<f64>: {}", e))
682            })?;
683            self.writer.write_bytes(&val.into_inner().to_le_bytes())?;
684            return Ok(true);
685        }
686
687        // bytestring::ByteString
688        #[cfg(feature = "bytestring")]
689        if shape == <bytestring::ByteString as facet_core::Facet>::SHAPE {
690            let bs = value.get::<bytestring::ByteString>().map_err(|e| {
691                SerializeError::Custom(alloc::format!("Failed to get ByteString: {}", e))
692            })?;
693            self.write_str(bs.as_ref())?;
694            return Ok(true);
695        }
696
697        // compact_str::CompactString
698        #[cfg(feature = "compact_str")]
699        if shape == <compact_str::CompactString as facet_core::Facet>::SHAPE {
700            let cs = value.get::<compact_str::CompactString>().map_err(|e| {
701                SerializeError::Custom(alloc::format!("Failed to get CompactString: {}", e))
702            })?;
703            self.write_str(cs.as_str())?;
704            return Ok(true);
705        }
706
707        // smartstring::SmartString<LazyCompact>
708        #[cfg(feature = "smartstring")]
709        if shape == <smartstring::SmartString<smartstring::LazyCompact> as facet_core::Facet>::SHAPE
710        {
711            let ss = value
712                .get::<smartstring::SmartString<smartstring::LazyCompact>>()
713                .map_err(|e| {
714                    SerializeError::Custom(alloc::format!("Failed to get SmartString: {}", e))
715                })?;
716            self.write_str(ss.as_str())?;
717            return Ok(true);
718        }
719
720        if shape.inner.is_some() {
721            return Ok(false);
722        }
723
724        // Fallback to string or Display for non-standard scalars.
725        if matches!(shape.def, Def::Scalar) {
726            if let Some(s) = value.as_str() {
727                self.write_str(s)?;
728                return Ok(true);
729            }
730            if shape.vtable.has_display() {
731                let s = alloc::format!("{}", value);
732                self.write_str(&s)?;
733                return Ok(true);
734            }
735        }
736
737        Ok(false)
738    }
739}
740
741/// Write an unsigned varint (LEB128-like encoding used by postcard)
742fn write_varint<W: Writer>(mut value: u64, writer: &mut W) -> Result<(), SerializeError> {
743    loop {
744        let mut byte = (value & 0x7F) as u8;
745        value >>= 7;
746        if value != 0 {
747            byte |= 0x80;
748        }
749        writer.write_byte(byte)?;
750        if value == 0 {
751            break;
752        }
753    }
754    Ok(())
755}
756
757/// Write an unsigned 128-bit varint
758fn write_varint_u128<W: Writer>(mut value: u128, writer: &mut W) -> Result<(), SerializeError> {
759    loop {
760        let mut byte = (value & 0x7F) as u8;
761        value >>= 7;
762        if value != 0 {
763            byte |= 0x80;
764        }
765        writer.write_byte(byte)?;
766        if value == 0 {
767            break;
768        }
769    }
770    Ok(())
771}
772
773/// Write a signed varint using zigzag encoding
774fn write_varint_signed<W: Writer>(value: i64, writer: &mut W) -> Result<(), SerializeError> {
775    // Zigzag encoding: (value << 1) ^ (value >> 63)
776    let encoded = ((value << 1) ^ (value >> 63)) as u64;
777    write_varint(encoded, writer)
778}
779
780/// Write a signed 128-bit varint using zigzag encoding
781fn write_varint_signed_i128<W: Writer>(value: i128, writer: &mut W) -> Result<(), SerializeError> {
782    // Zigzag encoding: (value << 1) ^ (value >> 127)
783    let encoded = ((value << 1) ^ (value >> 127)) as u128;
784    write_varint_u128(encoded, writer)
785}
786
787#[cfg(test)]
788mod tests {
789    use super::*;
790    use facet::Facet;
791    use facet_value::{VArray, VBytes, VNumber, VObject, VString, Value};
792    use postcard::to_allocvec as postcard_to_vec;
793    use serde::Serialize;
794
795    #[derive(Facet, Serialize, PartialEq, Debug)]
796    struct SimpleStruct {
797        a: u32,
798        b: alloc::string::String,
799        c: bool,
800    }
801
802    #[test]
803    fn test_simple_struct() {
804        facet_testhelpers::setup();
805
806        let value = SimpleStruct {
807            a: 123,
808            b: "hello".into(),
809            c: true,
810        };
811
812        let facet_bytes = to_vec(&value).unwrap();
813        let postcard_bytes = postcard_to_vec(&value).unwrap();
814
815        assert_eq!(facet_bytes, postcard_bytes);
816    }
817
818    #[test]
819    fn test_u8() {
820        facet_testhelpers::setup();
821
822        #[derive(Facet, Serialize, PartialEq, Debug)]
823        struct U8Struct {
824            value: u8,
825        }
826
827        let value = U8Struct { value: 42 };
828        let facet_bytes = to_vec(&value).unwrap();
829        let postcard_bytes = postcard_to_vec(&value).unwrap();
830        assert_eq!(facet_bytes, postcard_bytes);
831    }
832
833    #[test]
834    fn test_i32() {
835        facet_testhelpers::setup();
836
837        #[derive(Facet, Serialize, PartialEq, Debug)]
838        struct I32Struct {
839            value: i32,
840        }
841
842        let value = I32Struct { value: -100000 };
843        let facet_bytes = to_vec(&value).unwrap();
844        let postcard_bytes = postcard_to_vec(&value).unwrap();
845        assert_eq!(facet_bytes, postcard_bytes);
846    }
847
848    #[test]
849    fn test_string() {
850        facet_testhelpers::setup();
851
852        #[derive(Facet, Serialize, PartialEq, Debug)]
853        struct StringStruct {
854            value: alloc::string::String,
855        }
856
857        let value = StringStruct {
858            value: "hello world".into(),
859        };
860        let facet_bytes = to_vec(&value).unwrap();
861        let postcard_bytes = postcard_to_vec(&value).unwrap();
862        assert_eq!(facet_bytes, postcard_bytes);
863    }
864
865    #[test]
866    fn test_vec() {
867        facet_testhelpers::setup();
868
869        #[derive(Facet, Serialize, PartialEq, Debug)]
870        struct VecStruct {
871            values: Vec<u32>,
872        }
873
874        let value = VecStruct {
875            values: alloc::vec![1, 2, 3, 4, 5],
876        };
877        let facet_bytes = to_vec(&value).unwrap();
878        let postcard_bytes = postcard_to_vec(&value).unwrap();
879        assert_eq!(facet_bytes, postcard_bytes);
880    }
881
882    #[test]
883    fn test_option_some() {
884        facet_testhelpers::setup();
885
886        #[derive(Facet, Serialize, PartialEq, Debug)]
887        struct OptionStruct {
888            value: Option<u32>,
889        }
890
891        let value = OptionStruct { value: Some(42) };
892        let facet_bytes = to_vec(&value).unwrap();
893        let postcard_bytes = postcard_to_vec(&value).unwrap();
894        assert_eq!(facet_bytes, postcard_bytes);
895    }
896
897    #[test]
898    fn test_option_none() {
899        facet_testhelpers::setup();
900
901        #[derive(Facet, Serialize, PartialEq, Debug)]
902        struct OptionStruct {
903            value: Option<u32>,
904        }
905
906        let value = OptionStruct { value: None };
907        let facet_bytes = to_vec(&value).unwrap();
908        let postcard_bytes = postcard_to_vec(&value).unwrap();
909        assert_eq!(facet_bytes, postcard_bytes);
910    }
911
912    #[test]
913    fn test_unit_enum() {
914        facet_testhelpers::setup();
915
916        #[derive(Facet, Serialize, PartialEq, Debug)]
917        #[repr(C)]
918        enum Color {
919            Red,
920            Green,
921            Blue,
922        }
923
924        let facet_bytes = to_vec(&Color::Red).unwrap();
925        let postcard_bytes = postcard_to_vec(&Color::Red).unwrap();
926        assert_eq!(facet_bytes, postcard_bytes);
927
928        let facet_bytes = to_vec(&Color::Green).unwrap();
929        let postcard_bytes = postcard_to_vec(&Color::Green).unwrap();
930        assert_eq!(facet_bytes, postcard_bytes);
931
932        let facet_bytes = to_vec(&Color::Blue).unwrap();
933        let postcard_bytes = postcard_to_vec(&Color::Blue).unwrap();
934        assert_eq!(facet_bytes, postcard_bytes);
935    }
936
937    #[test]
938    fn test_tuple_enum() {
939        facet_testhelpers::setup();
940
941        #[derive(Facet, Serialize, PartialEq, Debug)]
942        #[repr(C)]
943        enum Value {
944            Int(i32),
945            Text(alloc::string::String),
946        }
947
948        let facet_bytes = to_vec(&Value::Int(42)).unwrap();
949        let postcard_bytes = postcard_to_vec(&Value::Int(42)).unwrap();
950        assert_eq!(facet_bytes, postcard_bytes);
951
952        let facet_bytes = to_vec(&Value::Text("hello".into())).unwrap();
953        let postcard_bytes = postcard_to_vec(&Value::Text("hello".into())).unwrap();
954        assert_eq!(facet_bytes, postcard_bytes);
955    }
956
957    #[test]
958    fn test_struct_enum() {
959        facet_testhelpers::setup();
960
961        #[derive(Facet, Serialize, PartialEq, Debug)]
962        #[repr(C)]
963        enum Message {
964            Quit,
965            Move { x: i32, y: i32 },
966        }
967
968        let facet_bytes = to_vec(&Message::Quit).unwrap();
969        let postcard_bytes = postcard_to_vec(&Message::Quit).unwrap();
970        assert_eq!(facet_bytes, postcard_bytes);
971
972        let facet_bytes = to_vec(&Message::Move { x: 10, y: 20 }).unwrap();
973        let postcard_bytes = postcard_to_vec(&Message::Move { x: 10, y: 20 }).unwrap();
974        assert_eq!(facet_bytes, postcard_bytes);
975    }
976
977    #[test]
978    fn test_to_writer_fallible() {
979        facet_testhelpers::setup();
980
981        struct CustomWriter {
982            buffer: Vec<u8>,
983        }
984
985        impl Writer for CustomWriter {
986            fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
987                self.buffer.push(byte);
988                Ok(())
989            }
990
991            fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SerializeError> {
992                self.buffer.extend_from_slice(bytes);
993                Ok(())
994            }
995        }
996
997        let value = SimpleStruct {
998            a: 123,
999            b: "hello".into(),
1000            c: true,
1001        };
1002
1003        let mut writer = CustomWriter { buffer: Vec::new() };
1004        to_writer_fallible(&value, &mut writer).unwrap();
1005
1006        let postcard_bytes = postcard_to_vec(&value).unwrap();
1007        assert_eq!(writer.buffer, postcard_bytes);
1008    }
1009
1010    #[test]
1011    fn test_value_roundtrip() {
1012        facet_testhelpers::setup();
1013
1014        let mut array = VArray::new();
1015        array.push(Value::from(VNumber::from_i64(1)));
1016        array.push(Value::from(VString::new("two")));
1017        array.push(Value::TRUE);
1018
1019        let mut object = VObject::new();
1020        object.insert("n", Value::from(VNumber::from_u64(42)));
1021        object.insert("s", Value::from(VString::new("hello")));
1022        object.insert("b", Value::from(VBytes::new(&[1, 2, 3])));
1023        object.insert("a", Value::from(array));
1024
1025        let value = Value::from(object);
1026        let bytes = to_vec(&value).unwrap();
1027        let decoded: Value = crate::from_slice(&bytes).unwrap();
1028
1029        assert_eq!(decoded, value);
1030    }
1031}