Skip to main content

wincode/schema/
mod.rs

1//! Schema traits.
2//!
3//! # Example
4//!
5//! ```
6//! # #[cfg(all(feature = "solana-short-vec", feature = "alloc"))] {
7//! # use rand::random;
8//! # use wincode::{Serialize, Deserialize, len::{BincodeLen, ShortU16}, containers};
9//! # use wincode_derive::{SchemaWrite, SchemaRead};
10//! # use std::array;
11//!
12//! # #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
13//! #[repr(transparent)]
14//! #[derive(Clone, Copy)]
15//! struct Signature([u8; 32]);
16//! # #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
17//! #[repr(transparent)]
18//! #[derive(Clone, Copy)]
19//! struct Address([u8; 32]);
20//!
21//! wincode::pod_wrapper! {
22//!     unsafe struct PodSignature(Signature);
23//!     unsafe struct PodAddress(Address);
24//! }
25//!
26//! # #[derive(SchemaWrite, SchemaRead, serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
27//! struct MyStruct {
28//!     #[wincode(with = "containers::Vec<PodSignature, BincodeLen>")]
29//!     signature: Vec<Signature>,
30//!     #[serde(with = "solana_short_vec")]
31//!     #[wincode(with = "containers::Vec<PodAddress, ShortU16>")]
32//!     address: Vec<Address>,
33//! }
34//!
35//! let my_struct = MyStruct {
36//!     signature: (0..10).map(|_| Signature(array::from_fn(|_| random()))).collect(),
37//!     address: (0..10).map(|_| Address(array::from_fn(|_| random()))).collect(),
38//! };
39//! let bincode_serialized = bincode::serialize(&my_struct).unwrap();
40//! let wincode_serialized = wincode::serialize(&my_struct).unwrap();
41//! assert_eq!(bincode_serialized, wincode_serialized);
42//!
43//! let bincode_deserialized: MyStruct = bincode::deserialize(&bincode_serialized).unwrap();
44//! let wincode_deserialized: MyStruct = wincode::deserialize(&wincode_serialized).unwrap();
45//! assert_eq!(bincode_deserialized, wincode_deserialized);
46//! # }
47//! ```
48use {
49    crate::{
50        config::{self, ConfigCore, DefaultConfig},
51        error::{ReadResult, WriteResult},
52        io::*,
53        len::SeqLen,
54    },
55    core::mem::MaybeUninit,
56};
57
58pub mod containers;
59pub mod context;
60mod external;
61mod impls;
62pub mod int_encoding;
63pub mod tag_encoding;
64
65/// Indicates what kind of assumptions can be made when encoding or decoding a type.
66///
67/// Readers and writers may use this to optimize their behavior.
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub enum TypeMeta {
70    /// The type has a statically known serialized size.
71    ///
72    /// Specifying this variant can have significant performance benefits, as it can allow
73    /// writers to prefetch larger chunks of memory such that subsequent read/write operations
74    /// in those chunks can be performed at once without intermediate bounds checks.
75    ///
76    /// Specifying this variant incorrectly will almost certainly result in a panic at runtime.
77    ///
78    /// Take care not to specify this on variable length types, like `Vec` or `String`, as their
79    /// serialized size will vary based on their length.
80    Static {
81        /// The static serialized size of the type.
82        size: usize,
83        /// Whether the type is eligible for zero-copy encoding/decoding.
84        ///
85        /// This indicates that the type has no invalid bit patterns, no layout requirements, no endianness
86        /// checks, etc. This is a very strong claim that should be used judiciously.
87        ///
88        /// Specifying this incorrectly may trigger UB.
89        zero_copy: bool,
90    },
91    /// The type has a dynamic size, and no optimizations can be made.
92    Dynamic,
93}
94
95impl TypeMeta {
96    #[inline(always)]
97    pub(crate) const fn size_assert_zero_copy(self) -> usize {
98        match self {
99            TypeMeta::Static {
100                size,
101                zero_copy: true,
102            } => size,
103            _ => panic!("Type is not zero-copy"),
104        }
105    }
106
107    #[cfg(all(test, feature = "std", feature = "derive"))]
108    pub(crate) const fn size_assert_static(self) -> usize {
109        match self {
110            TypeMeta::Static { size, zero_copy: _ } => size,
111            _ => panic!("Type is not static"),
112        }
113    }
114
115    /// Returns this [`TypeMeta`] instance with `zero_copy` masked by `keep_zero_copy`.
116    ///
117    /// For `TypeMeta::Static`, this preserves `size` and computes:
118    /// `zero_copy = zero_copy && keep_zero_copy`.
119    ///
120    /// For `TypeMeta::Dynamic`, this is a no-op.
121    ///
122    /// This method never upgrades a type to zero-copy.
123    /// - `keep_zero_copy(true)` leaves the flag unchanged.
124    /// - `keep_zero_copy(false)` clears the flag.
125    pub const fn keep_zero_copy(self, keep_zero_copy: bool) -> Self {
126        match self {
127            Self::Static { size, zero_copy } => TypeMeta::Static {
128                size,
129                zero_copy: zero_copy && keep_zero_copy,
130            },
131            Self::Dynamic => Self::Dynamic,
132        }
133    }
134
135    /// Combines multiple constituent [`TypeMeta`] values into one aggregate.
136    ///
137    /// Intended for composite types whose constituents are serialized sequentially.
138    ///
139    /// Semantics:
140    /// - If any input is `Dynamic`, returns `Dynamic`.
141    /// - Otherwise returns `Static` with:
142    ///   - `size = sum of all constituent sizes`
143    ///   - `zero_copy = logical AND of all constituent zero_copy flags`
144    ///
145    /// Notes:
146    /// - This function does **not** validate layout/padding; it only combines metadata.
147    /// - For `N = 0`, the result is `TypeMeta::Static { size: 0, zero_copy: true }`.
148    /// - The caller must ensure the summed size is meaningful for the target type.
149    ///
150    /// ```
151    /// use wincode::TypeMeta;
152    ///
153    /// let types = [
154    ///     TypeMeta::Static { size: 1, zero_copy: true },
155    ///     TypeMeta::Static { size: 2, zero_copy: true },
156    ///     TypeMeta::Dynamic,
157    ///     TypeMeta::Static { size: 3, zero_copy: true },
158    /// ];
159    /// assert_eq!(TypeMeta::join_types(types), TypeMeta::Dynamic);
160    /// ```
161    ///
162    /// ```
163    /// use wincode::TypeMeta;
164    ///
165    /// let types = [
166    ///     TypeMeta::Static { size: 1, zero_copy: true },
167    ///     TypeMeta::Static { size: 2, zero_copy: true },
168    ///     TypeMeta::Static { size: 3, zero_copy: true },
169    /// ];
170    /// assert_eq!(TypeMeta::join_types(types), TypeMeta::Static { size: 6, zero_copy: true });
171    /// ```
172    ///
173    /// ```
174    /// use wincode::TypeMeta;
175    ///
176    /// let types = [
177    ///     TypeMeta::Static { size: 1, zero_copy: true },
178    ///     TypeMeta::Static { size: 2, zero_copy: false },
179    ///     TypeMeta::Static { size: 3, zero_copy: true },
180    /// ];
181    /// assert_eq!(TypeMeta::join_types(types), TypeMeta::Static { size: 6, zero_copy: false });
182    /// ```
183    #[expect(clippy::arithmetic_side_effects)]
184    pub const fn join_types<const N: usize>(types: [Self; N]) -> Self {
185        let mut acc_size = 0;
186        let mut all_zero_copy = true;
187        let mut i = 0;
188        while i < N {
189            match types[i] {
190                Self::Dynamic => return Self::Dynamic,
191                Self::Static { size, zero_copy } => {
192                    acc_size += size;
193                    all_zero_copy &= zero_copy;
194                }
195            }
196            i += 1;
197        }
198        Self::Static {
199            size: acc_size,
200            zero_copy: all_zero_copy,
201        }
202    }
203}
204
205/// Types that can be written (serialized) to a [`Writer`].
206///
207/// # Safety
208///
209/// Implementors must adhere to the Safety section of the associated constant
210/// `TYPE_META` (or leave it as the default) and the method `size_of`
211pub unsafe trait SchemaWrite<C: ConfigCore> {
212    type Src: ?Sized;
213
214    /// Metadata about the type's serialization.
215    ///
216    /// # Safety
217    ///
218    /// It is always safe to leave this as the default `TypeMeta::Dynamic`. If
219    /// you set it to `TypeMeta::Static { size, zero_copy }`, you have to ensure
220    /// the following two points:
221    /// - `size` must always correspond to the number of bytes written by
222    ///   `write`. `size_of` must always return `Ok(size)`.
223    /// - If `zero_copy` is `true`, `Src`'s in-memory representation must
224    ///   correspond exactly to the serialized form. There must be no padding in
225    ///   the in-memory representation of `Src`.
226    const TYPE_META: TypeMeta = TypeMeta::Dynamic;
227
228    #[cfg(test)]
229    #[allow(unused_variables)]
230    fn type_meta(config: C) -> TypeMeta {
231        Self::TYPE_META
232    }
233
234    /// Get the serialized size of `Self::Src`.
235    ///
236    /// # Safety
237    ///
238    /// If `Ok(…)` is returned, it must contain the exact number of bytes
239    /// written by the `write` function for this particular object instance.
240    fn size_of(src: &Self::Src) -> WriteResult<usize>;
241
242    /// Write `Self::Src` to `writer`.
243    fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()>;
244}
245
246/// Types that can be read (deserialized) from a [`Reader`].
247///
248/// # Safety
249///
250/// Implementors must adhere to the Safety section of the associated constant
251/// `TYPE_META` (or leave it as the default) and the method `read`.
252pub unsafe trait SchemaRead<'de, C: ConfigCore> {
253    type Dst;
254
255    /// Metadata about the type's serialization.
256    ///
257    /// # Safety
258    ///
259    /// It is always safe to leave this as the default `TypeMeta::Dynamic`. If
260    /// you set it to `TypeMeta::Static { size, zero_copy }`, you have to ensure
261    /// the following two points:
262    /// - `size` must always correspond to the number of bytes read by `read`.
263    /// - If `zero_copy` is `true`, `Dst`'s in-memory representation must
264    ///   correspond exactly to the serialized form, and all byte sequences must
265    ///   be valid in-memory representations of `Dst`.
266    const TYPE_META: TypeMeta = TypeMeta::Dynamic;
267
268    #[cfg(test)]
269    #[allow(unused_variables)]
270    fn type_meta(config: C) -> TypeMeta {
271        Self::TYPE_META
272    }
273
274    /// Read into `dst` from `reader`.
275    ///
276    /// # Safety
277    ///
278    /// You must initialize `dst` if **and only if** you return `Ok(())`. In the
279    /// `Err(…)` case, initializing `dst` can lead to memory leaks.
280    ///
281    /// It is permissible to not initialize `dst` if `dst` is an inhabited
282    /// zero-sized type.
283    fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()>;
284
285    /// Read `Self::Dst` from `reader` into a new `Self::Dst`.
286    #[inline(always)]
287    fn get(reader: impl Reader<'de>) -> ReadResult<Self::Dst> {
288        let mut value = MaybeUninit::uninit();
289        Self::read(reader, &mut value)?;
290        // SAFETY: `read` must properly initialize the `Self::Dst`.
291        Ok(unsafe { value.assume_init() })
292    }
293}
294
295/// Types that can be read (deserialized) from a [`Reader`] with an additional context parameter.
296///
297/// # Safety
298///
299/// Implementors must adhere to the Safety section of the associated constant
300/// `TYPE_META` (or leave it as the default) and the method `read`.
301pub unsafe trait SchemaReadContext<'de, C: ConfigCore, Ctx> {
302    type Dst;
303
304    /// Metadata about the type's serialization.
305    ///
306    /// # Safety
307    ///
308    /// It is always safe to leave this as the default `TypeMeta::Dynamic`. If
309    /// you set it to `TypeMeta::Static { size, zero_copy }`, you have to ensure
310    /// the following two points:
311    /// - `size` must always correspond to the number of bytes read by `read`.
312    /// - If `zero_copy` is `true`, `Dst`'s in-memory representation must
313    ///   correspond exactly to the serialized form, and all byte sequences must
314    ///   be valid in-memory representations of `Dst`.
315    const TYPE_META: TypeMeta = TypeMeta::Dynamic;
316
317    /// Read into `dst` from `reader` with context.
318    ///
319    /// You must initialize `dst` if **and only if** you return `Ok(())`. In the
320    /// `Err(…)` case, initializing `dst` can lead to memory leaks.
321    ///
322    /// It is permissible to not initialize `dst` if `dst` is an inhabited
323    /// zero-sized type.
324    fn read_with_context(
325        ctx: Ctx,
326        reader: impl Reader<'de>,
327        dst: &mut MaybeUninit<Self::Dst>,
328    ) -> ReadResult<()>;
329
330    /// Read `Self::Dst` from `reader` into a new `Self::Dst` with context.
331    #[inline(always)]
332    fn get_with_context(ctx: Ctx, reader: impl Reader<'de>) -> ReadResult<Self::Dst> {
333        let mut value = MaybeUninit::uninit();
334        Self::read_with_context(ctx, reader, &mut value)?;
335        // SAFETY: `read_with_context` must properly initialize the `Self::Dst`.
336        Ok(unsafe { value.assume_init() })
337    }
338}
339
340/// Marker trait for types that can be deserialized via direct borrows from a [`Reader`]
341/// using the default configuration. See [`config::ZeroCopy`] for configuration
342/// aware methods.
343///
344/// Always prefer using [`config::ZeroCopy`] for your implementations to keep them fully
345/// generic.
346///
347/// # Safety
348///
349/// - The type must not have any invalid bit patterns, no layout requirements, no endianness checks, etc.
350pub unsafe trait ZeroCopy: config::ZeroCopy<DefaultConfig> {
351    /// Get a reference to a type from the given bytes.
352    ///
353    /// # Examples
354    ///
355    /// ```
356    /// # #[cfg(all(feature = "alloc", feature = "derive"))] {
357    /// # use wincode::{SchemaWrite, SchemaRead, ZeroCopy};
358    /// # #[derive(Debug, PartialEq, Eq)]
359    /// #[derive(SchemaWrite, SchemaRead)]
360    /// #[repr(C)]
361    /// struct Data {
362    ///     bytes: [u8; 7],
363    ///     the_answer: u8,
364    /// }
365    ///
366    /// let data = Data { bytes: *b"wincode", the_answer: 42 };
367    ///
368    /// let serialized = wincode::serialize(&data).unwrap();
369    /// let data_ref = Data::from_bytes(&serialized).unwrap();
370    ///
371    /// assert_eq!(data_ref, &data);
372    /// # }
373    /// ```
374    #[inline(always)]
375    fn from_bytes<'de>(bytes: &'de [u8]) -> ReadResult<&'de Self>
376    where
377        Self: SchemaRead<'de, DefaultConfig, Dst = Self> + Sized,
378    {
379        <&Self as SchemaRead<'de, DefaultConfig>>::get(bytes)
380    }
381
382    /// Get a mutable reference to a type from the given bytes.
383    ///
384    /// # Examples
385    ///
386    /// ```
387    /// # #[cfg(all(feature = "alloc", feature = "derive"))] {
388    /// # use wincode::{SchemaWrite, SchemaRead, ZeroCopy};
389    /// # #[derive(Debug, PartialEq, Eq)]
390    /// #[derive(SchemaWrite, SchemaRead)]
391    /// #[repr(C)]
392    /// struct Data {
393    ///     bytes: [u8; 7],
394    ///     the_answer: u8,
395    /// }
396    ///
397    /// let data = Data { bytes: [0; 7], the_answer: 0 };
398    ///
399    /// let mut serialized = wincode::serialize(&data).unwrap();
400    /// let data_mut = Data::from_bytes_mut(&mut serialized).unwrap();
401    /// data_mut.bytes = *b"wincode";
402    /// data_mut.the_answer = 42;
403    ///
404    /// let deserialized: Data = wincode::deserialize(&serialized).unwrap();
405    /// assert_eq!(deserialized, Data { bytes: *b"wincode", the_answer: 42 });
406    /// # }
407    /// ```
408    #[inline(always)]
409    fn from_bytes_mut<'de>(bytes: &'de mut [u8]) -> ReadResult<&'de mut Self>
410    where
411        Self: SchemaRead<'de, DefaultConfig, Dst = Self> + Sized,
412    {
413        <&mut Self as SchemaRead<'de, DefaultConfig>>::get(bytes)
414    }
415}
416
417unsafe impl<T> ZeroCopy for T where T: config::ZeroCopy<DefaultConfig> {}
418
419/// A type that can be read (deserialized) from a [`Reader`] without borrowing from it.
420pub trait SchemaReadOwned<C: ConfigCore>: for<'de> SchemaRead<'de, C> {}
421impl<T, C: ConfigCore> SchemaReadOwned<C> for T where T: for<'de> SchemaRead<'de, C> {}
422
423#[inline(always)]
424#[allow(clippy::arithmetic_side_effects)]
425fn size_of_elem_iter<'a, T, Len, C>(
426    value: impl ExactSizeIterator<Item = &'a T::Src>,
427) -> WriteResult<usize>
428where
429    C: ConfigCore,
430    Len: SeqLen<C>,
431    T: SchemaWrite<C> + 'a,
432{
433    if let TypeMeta::Static { size, .. } = T::TYPE_META {
434        return Ok(Len::write_bytes_needed(value.len())? + size * value.len());
435    }
436    // Extremely unlikely a type-in-memory's size will overflow usize::MAX.
437    Ok(Len::write_bytes_needed(value.len())?
438        + (value
439            .map(T::size_of)
440            .try_fold(0usize, |acc, x| x.map(|x| acc + x))?))
441}
442
443#[inline(always)]
444#[allow(clippy::arithmetic_side_effects)]
445/// Variant of [`size_of_elem_iter`] specialized for slices.
446fn size_of_elem_slice<T, Len, C>(value: &[T::Src]) -> WriteResult<usize>
447where
448    C: ConfigCore,
449    Len: SeqLen<C>,
450    T: SchemaWrite<C>,
451    T::Src: Sized,
452{
453    size_of_elem_iter::<T, Len, C>(value.iter())
454}
455
456#[inline(always)]
457fn write_elem_iter<'a, T, Len, C>(
458    mut writer: impl Writer,
459    src: impl ExactSizeIterator<Item = &'a T::Src>,
460) -> WriteResult<()>
461where
462    C: ConfigCore,
463    Len: SeqLen<C>,
464    T: SchemaWrite<C> + 'a,
465{
466    if let TypeMeta::Static { size, .. } = T::TYPE_META {
467        #[allow(clippy::arithmetic_side_effects)]
468        let needed = Len::write_bytes_needed(src.len())? + size * src.len();
469        // SAFETY: `needed` is the size of the encoded length plus the size of the items.
470        // `Len::write` and len writes of `T::Src` will write `needed` bytes,
471        // fully initializing the trusted window.
472        let mut writer = unsafe { writer.as_trusted_for(needed) }?;
473        Len::write(writer.by_ref(), src.len())?;
474        for item in src {
475            T::write(writer.by_ref(), item)?;
476        }
477        writer.finish()?;
478        return Ok(());
479    }
480
481    Len::write(writer.by_ref(), src.len())?;
482    for item in src {
483        T::write(writer.by_ref(), item)?;
484    }
485    Ok(())
486}
487
488#[inline(always)]
489#[cfg(feature = "alloc")]
490fn write_elem_iter_prealloc_check<'a, T, Len, C>(
491    writer: impl Writer,
492    src: impl ExactSizeIterator<Item = &'a T::Src>,
493) -> WriteResult<()>
494where
495    C: ConfigCore,
496    Len: SeqLen<C>,
497    T: SchemaWrite<C> + 'a,
498{
499    Len::prealloc_check::<T>(src.len())?;
500    write_elem_iter::<T, Len, C>(writer, src)
501}
502
503#[inline(always)]
504#[allow(clippy::arithmetic_side_effects)]
505/// Variant of [`write_elem_iter`] specialized for slices, which can opt into
506/// an optimized implementation for bytes (`u8`s).
507fn write_elem_slice<T, Len, C>(mut writer: impl Writer, src: &[T::Src]) -> WriteResult<()>
508where
509    C: ConfigCore,
510    Len: SeqLen<C>,
511    T: SchemaWrite<C>,
512    T::Src: Sized,
513{
514    if let TypeMeta::Static {
515        size,
516        zero_copy: true,
517    } = T::TYPE_META
518    {
519        let needed = Len::write_bytes_needed(src.len())? + src.len() * size;
520        // SAFETY: `needed` is the size of the encoded length plus the size of the slice (bytes).
521        // `Len::write` and `writer.write(src)` will write `needed` bytes,
522        // fully initializing the trusted window.
523        let mut writer = unsafe { writer.as_trusted_for(needed) }?;
524        Len::write(writer.by_ref(), src.len())?;
525        // SAFETY: `T::Src` is zero-copy eligible (no invalid bit patterns, no layout requirements, no endianness checks, etc.).
526        unsafe { writer.write_slice_t(src)? };
527        writer.finish()?;
528        return Ok(());
529    }
530    write_elem_iter::<T, Len, C>(writer, src.iter())
531}
532
533#[inline(always)]
534#[cfg(feature = "alloc")]
535fn write_elem_slice_prealloc_check<T, Len, C>(
536    writer: impl Writer,
537    src: &[T::Src],
538) -> WriteResult<()>
539where
540    C: ConfigCore,
541    Len: SeqLen<C>,
542    T: SchemaWrite<C>,
543    T::Src: Sized,
544{
545    Len::prealloc_check::<T>(src.len())?;
546    write_elem_slice::<T, Len, C>(writer, src)
547}
548
549#[cfg(all(test, feature = "std", feature = "derive"))]
550mod tests {
551    #![allow(clippy::arithmetic_side_effects)]
552
553    use {
554        crate::{
555            Deserialize, ReadResult, SchemaRead, SchemaReadContext, SchemaWrite, Serialize,
556            TypeMeta, UninitBuilder, WriteResult, ZeroCopy,
557            config::{self, Config, ConfigCore, Configuration, DefaultConfig},
558            containers, context, deserialize, deserialize_exact, deserialize_mut,
559            error::{self, invalid_tag_encoding},
560            io::{Reader, Writer, test_util::NoBorrowReader},
561            len::{BincodeLen, FixIntLen},
562            pod_wrapper,
563            proptest_config::proptest_cfg,
564            serialize,
565        },
566        bincode::Options,
567        core::{marker::PhantomData, ptr},
568        proptest::prelude::*,
569        std::{
570            alloc::Layout,
571            borrow::Cow,
572            cell::Cell,
573            collections::{BinaryHeap, HashMap, HashSet, VecDeque},
574            hash::{BuildHasher, Hasher},
575            mem::MaybeUninit,
576            net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
577            num::{
578                NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
579                NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
580            },
581            ops::{Bound, Deref, DerefMut, Range, RangeInclusive},
582            rc::Rc,
583            result::Result,
584            sync::Arc,
585            time::{Duration, SystemTime, UNIX_EPOCH},
586        },
587    };
588
589    #[cfg(target_endian = "little")]
590    #[derive(
591        serde::Serialize,
592        serde::Deserialize,
593        Debug,
594        PartialEq,
595        Eq,
596        Ord,
597        PartialOrd,
598        SchemaWrite,
599        SchemaRead,
600        proptest_derive::Arbitrary,
601        Hash,
602        Clone,
603        Copy,
604    )]
605    #[wincode(internal)]
606    #[repr(C)]
607    struct StructZeroCopy {
608        a: u128,
609        b: i128,
610        c: u64,
611        d: i64,
612        e: u32,
613        f: i32,
614        ar1: [u8; 8],
615        g: u16,
616        h: i16,
617        ar2: [u8; 12],
618        i: u8,
619        j: i8,
620        ar3: [u8; 14],
621    }
622
623    #[cfg(not(target_endian = "little"))]
624    #[derive(
625        serde::Serialize,
626        serde::Deserialize,
627        Debug,
628        PartialEq,
629        Eq,
630        Ord,
631        PartialOrd,
632        SchemaWrite,
633        SchemaRead,
634        proptest_derive::Arbitrary,
635        Hash,
636        Clone,
637        Copy,
638    )]
639    #[wincode(internal)]
640    #[repr(C)]
641    struct StructZeroCopy {
642        byte: u8,
643        ar: [u8; 32],
644    }
645
646    #[derive(
647        serde::Serialize,
648        serde::Deserialize,
649        Debug,
650        PartialEq,
651        Eq,
652        Ord,
653        PartialOrd,
654        SchemaWrite,
655        SchemaRead,
656        proptest_derive::Arbitrary,
657        Hash,
658    )]
659    #[wincode(internal)]
660    struct StructStatic {
661        a: u64,
662        b: bool,
663        e: [u8; 32],
664    }
665
666    #[derive(
667        serde::Serialize,
668        serde::Deserialize,
669        Debug,
670        PartialEq,
671        Eq,
672        Ord,
673        PartialOrd,
674        SchemaWrite,
675        SchemaRead,
676        proptest_derive::Arbitrary,
677        Hash,
678    )]
679    #[wincode(internal)]
680    struct StructNonStatic {
681        a: u64,
682        b: bool,
683        e: String,
684    }
685
686    #[test]
687    fn struct_zero_copy_derive_size() {
688        #[cfg(target_endian = "little")]
689        let size = size_of::<u128>()
690            + size_of::<i128>()
691            + size_of::<u64>()
692            + size_of::<i64>()
693            + size_of::<u32>()
694            + size_of::<i32>()
695            + size_of::<[u8; 8]>()
696            + size_of::<u16>()
697            + size_of::<i16>()
698            + size_of::<[u8; 12]>()
699            + size_of::<u8>()
700            + size_of::<i8>()
701            + size_of::<[u8; 14]>();
702        #[cfg(not(target_endian = "little"))]
703        let size = size_of::<u8>() + size_of::<[u8; 32]>();
704        let expected = TypeMeta::Static {
705            size,
706            zero_copy: true,
707        };
708        assert_eq!(
709            <StructZeroCopy as SchemaWrite<DefaultConfig>>::TYPE_META,
710            expected
711        );
712        assert_eq!(
713            <StructZeroCopy as SchemaRead<'_, DefaultConfig>>::TYPE_META,
714            expected
715        );
716    }
717
718    #[test]
719    fn struct_zero_copy_transparent_derive_size() {
720        #[derive(SchemaWrite, SchemaRead)]
721        #[wincode(internal)]
722        #[repr(transparent)]
723        struct Address([u8; 32]);
724
725        let expected = TypeMeta::Static {
726            size: size_of::<[u8; 32]>(),
727            zero_copy: true,
728        };
729        assert_eq!(<Address as SchemaWrite<DefaultConfig>>::TYPE_META, expected);
730        assert_eq!(
731            <Address as SchemaRead<'_, DefaultConfig>>::TYPE_META,
732            expected
733        );
734    }
735
736    #[test]
737    fn struct_static_derive_size() {
738        let expected = TypeMeta::Static {
739            size: size_of::<u64>() + size_of::<bool>() + size_of::<[u8; 32]>(),
740            zero_copy: false,
741        };
742        assert_eq!(
743            <StructStatic as SchemaWrite<DefaultConfig>>::TYPE_META,
744            expected
745        );
746        assert_eq!(
747            <StructStatic as SchemaRead<'_, DefaultConfig>>::TYPE_META,
748            expected
749        );
750    }
751
752    #[test]
753    fn struct_non_static_derive_size() {
754        let expected = TypeMeta::Dynamic;
755        assert_eq!(
756            <StructNonStatic as SchemaWrite<DefaultConfig>>::TYPE_META,
757            expected
758        );
759        assert_eq!(
760            <StructNonStatic as SchemaRead<'_, DefaultConfig>>::TYPE_META,
761            expected
762        );
763    }
764
765    thread_local! {
766        /// TL counter for tracking drops (or lack thereof -- a leak).
767        static TL_DROP_COUNT: Cell<isize> = const { Cell::new(0) };
768    }
769
770    fn get_tl_drop_count() -> isize {
771        TL_DROP_COUNT.with(|cell| cell.get())
772    }
773
774    fn tl_drop_count_inc() {
775        TL_DROP_COUNT.with(|cell| cell.set(cell.get() + 1));
776    }
777
778    fn tl_drop_count_dec() {
779        TL_DROP_COUNT.with(|cell| cell.set(cell.get() - 1));
780    }
781
782    fn tl_drop_count_reset() {
783        TL_DROP_COUNT.with(|cell| cell.set(0));
784    }
785
786    #[must_use]
787    #[derive(Debug)]
788    /// Guard for test set up that will ensure that the TL counter is 0 at the start and end of the test.
789    struct TLDropGuard;
790
791    impl TLDropGuard {
792        fn new() -> Self {
793            assert_eq!(
794                get_tl_drop_count(),
795                0,
796                "TL counter drifted from zero -- another test may have leaked"
797            );
798            Self
799        }
800    }
801
802    impl Drop for TLDropGuard {
803        #[track_caller]
804        fn drop(&mut self) {
805            let v = get_tl_drop_count();
806            if !std::thread::panicking() {
807                assert_eq!(
808                    v, 0,
809                    "TL counter drifted from zero -- this test might have leaked"
810                );
811            }
812            tl_drop_count_reset();
813        }
814    }
815
816    #[derive(Debug, PartialEq, Eq)]
817    /// A `SchemaWrite` and `SchemaRead` that will increment the TL counter when constructed.
818    struct DropCounted;
819
820    impl Arbitrary for DropCounted {
821        type Parameters = ();
822        type Strategy = Just<Self>;
823        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
824            Just(Self::new())
825        }
826    }
827
828    impl DropCounted {
829        const TAG_BYTE: u8 = 0;
830
831        fn new() -> Self {
832            tl_drop_count_inc();
833            Self
834        }
835    }
836
837    impl Clone for DropCounted {
838        fn clone(&self) -> Self {
839            tl_drop_count_inc();
840            Self
841        }
842    }
843
844    impl Drop for DropCounted {
845        fn drop(&mut self) {
846            tl_drop_count_dec();
847        }
848    }
849
850    unsafe impl<C: Config> SchemaWrite<C> for DropCounted {
851        type Src = Self;
852
853        const TYPE_META: TypeMeta = TypeMeta::Static {
854            size: 1,
855            zero_copy: false,
856        };
857
858        fn size_of(_src: &Self::Src) -> WriteResult<usize> {
859            Ok(1)
860        }
861        fn write(writer: impl Writer, _src: &Self::Src) -> WriteResult<()> {
862            <u8 as SchemaWrite<C>>::write(writer, &Self::TAG_BYTE)?;
863            Ok(())
864        }
865    }
866
867    unsafe impl<'de, C: Config> SchemaRead<'de, C> for DropCounted {
868        type Dst = Self;
869
870        const TYPE_META: TypeMeta = TypeMeta::Static {
871            size: 1,
872            zero_copy: false,
873        };
874
875        fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
876            reader.take_byte()?;
877            // This will increment the counter.
878            dst.write(DropCounted::new());
879            Ok(())
880        }
881    }
882
883    /// A `SchemaRead` that will always error on read.
884    #[derive(Debug, Clone, Copy, PartialEq, Eq, proptest_derive::Arbitrary)]
885    struct ErrorsOnRead;
886
887    impl ErrorsOnRead {
888        const TAG_BYTE: u8 = 1;
889    }
890
891    unsafe impl<C: Config> SchemaWrite<C> for ErrorsOnRead {
892        type Src = Self;
893
894        const TYPE_META: TypeMeta = TypeMeta::Static {
895            size: 1,
896            zero_copy: false,
897        };
898
899        fn size_of(_src: &Self::Src) -> WriteResult<usize> {
900            Ok(1)
901        }
902
903        fn write(writer: impl Writer, _src: &Self::Src) -> WriteResult<()> {
904            <u8 as SchemaWrite<C>>::write(writer, &Self::TAG_BYTE)
905        }
906    }
907
908    unsafe impl<'de, C: Config> SchemaRead<'de, C> for ErrorsOnRead {
909        type Dst = Self;
910
911        const TYPE_META: TypeMeta = TypeMeta::Static {
912            size: 1,
913            zero_copy: false,
914        };
915
916        fn read(mut reader: impl Reader<'de>, _dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
917            reader.take_byte()?;
918            Err(error::ReadError::PointerSizedReadError)
919        }
920    }
921
922    #[derive(Debug, Clone, PartialEq, Eq, proptest_derive::Arbitrary)]
923    enum DropCountedMaybeError {
924        DropCounted(DropCounted),
925        ErrorsOnRead(ErrorsOnRead),
926    }
927
928    unsafe impl<C: Config> SchemaWrite<C> for DropCountedMaybeError {
929        type Src = Self;
930
931        const TYPE_META: TypeMeta = TypeMeta::Static {
932            size: 1,
933            zero_copy: false,
934        };
935
936        fn size_of(src: &Self::Src) -> WriteResult<usize> {
937            match src {
938                DropCountedMaybeError::DropCounted(v) => {
939                    <DropCounted as SchemaWrite<C>>::size_of(v)
940                }
941                DropCountedMaybeError::ErrorsOnRead(v) => {
942                    <ErrorsOnRead as SchemaWrite<C>>::size_of(v)
943                }
944            }
945        }
946
947        fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
948            match src {
949                DropCountedMaybeError::DropCounted(v) => {
950                    <DropCounted as SchemaWrite<C>>::write(writer, v)
951                }
952                DropCountedMaybeError::ErrorsOnRead(v) => {
953                    <ErrorsOnRead as SchemaWrite<C>>::write(writer, v)
954                }
955            }
956        }
957    }
958
959    unsafe impl<'de, C: Config> SchemaRead<'de, C> for DropCountedMaybeError {
960        type Dst = Self;
961
962        const TYPE_META: TypeMeta = TypeMeta::Static {
963            size: 1,
964            zero_copy: false,
965        };
966
967        fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
968            let byte = <u8 as SchemaRead<'de, C>>::get(reader)?;
969            match byte {
970                DropCounted::TAG_BYTE => {
971                    dst.write(DropCountedMaybeError::DropCounted(DropCounted::new()));
972                    Ok(())
973                }
974                ErrorsOnRead::TAG_BYTE => Err(error::ReadError::PointerSizedReadError),
975                _ => Err(invalid_tag_encoding(byte as usize)),
976            }
977        }
978    }
979
980    #[test]
981    fn drop_count_sanity() {
982        let _guard = TLDropGuard::new();
983        // Ensure our incrementing counter works
984        let serialized = { serialize(&[DropCounted::new(), DropCounted::new()]).unwrap() };
985        let _deserialized: [DropCounted; 2] = deserialize(&serialized).unwrap();
986        assert_eq!(get_tl_drop_count(), 2);
987    }
988
989    #[test]
990    fn drop_count_maybe_error_sanity() {
991        let _guard = TLDropGuard::new();
992        let serialized =
993            { serialize(&[DropCountedMaybeError::DropCounted(DropCounted::new())]).unwrap() };
994        let _deserialized: [DropCountedMaybeError; 1] = deserialize(&serialized).unwrap();
995        assert_eq!(get_tl_drop_count(), 1);
996
997        let serialized = {
998            serialize(&[
999                DropCountedMaybeError::DropCounted(DropCounted::new()),
1000                DropCountedMaybeError::ErrorsOnRead(ErrorsOnRead),
1001            ])
1002            .unwrap()
1003        };
1004        let _deserialized: ReadResult<[DropCountedMaybeError; 2]> = deserialize(&serialized);
1005    }
1006
1007    /// Test that the derive macro handles drops of initialized fields on partially initialized structs.
1008    #[test]
1009    fn test_struct_derive_handles_partial_drop() {
1010        /// Represents a struct that would leak if the derive macro didn't handle drops of initialized fields
1011        /// on error.
1012        #[derive(SchemaWrite, SchemaRead, proptest_derive::Arbitrary, Debug, PartialEq, Eq)]
1013        #[wincode(internal)]
1014        struct CouldLeak {
1015            data: DropCountedMaybeError,
1016            data2: DropCountedMaybeError,
1017            data3: DropCountedMaybeError,
1018        }
1019
1020        let _guard = TLDropGuard::new();
1021        proptest!(proptest_cfg(), |(could_leak: CouldLeak)| {
1022            let serialized = serialize(&could_leak).unwrap();
1023            let deserialized = CouldLeak::deserialize(&serialized);
1024            if let Ok(deserialized) = deserialized {
1025                prop_assert_eq!(could_leak, deserialized);
1026            }
1027        });
1028    }
1029
1030    // Odd use case, but it's technically valid so we test it.
1031    #[test]
1032    fn test_vec_of_references_borrows_from_input() {
1033        #[derive(
1034            SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary, Clone, Copy,
1035        )]
1036        #[wincode(internal)]
1037        #[repr(transparent)]
1038        struct BigBytes([u8; 512]);
1039        proptest!(proptest_cfg(), |(vec in proptest::collection::vec(any::<BigBytes>(), 0..=8))| {
1040            // Serialize as owned bytes.
1041            let bytes = serialize(&vec).unwrap();
1042            let borrowed: Vec<&BigBytes> = deserialize(&bytes).unwrap();
1043
1044            prop_assert_eq!(borrowed.len(), vec.len());
1045            let start = bytes.as_ptr().addr();
1046            let end = start + bytes.len();
1047            for (i, r) in borrowed.iter().enumerate() {
1048                // Values match
1049                prop_assert_eq!(**r, vec[i]);
1050                // References point into the input buffer
1051                let p = ptr::from_ref(*r).addr();
1052                prop_assert!(p >= start && p < end);
1053            }
1054        });
1055    }
1056
1057    // Odd use case, but it's technically valid so we test it.
1058    #[test]
1059    fn test_boxed_slice_of_references_borrows_from_input() {
1060        #[derive(
1061            SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary, Clone, Copy,
1062        )]
1063        #[wincode(internal)]
1064        #[repr(transparent)]
1065        struct BigBytes([u8; 512]);
1066        proptest!(proptest_cfg(), |(vec in proptest::collection::vec(any::<BigBytes>(), 0..=8))| {
1067            let boxed: Box<[BigBytes]> = vec.into_boxed_slice();
1068            let bytes = serialize(&boxed).unwrap();
1069            let borrowed: Box<[&BigBytes]> = deserialize(&bytes).unwrap();
1070
1071            prop_assert_eq!(borrowed.len(), boxed.len());
1072            let start = bytes.as_ptr().addr();
1073            let end = start + bytes.len();
1074            for (i, &r) in borrowed.iter().enumerate() {
1075                prop_assert_eq!(*r, boxed[i]);
1076                let p = ptr::from_ref(r).addr();
1077                prop_assert!(p >= start && p < end);
1078            }
1079        });
1080    }
1081
1082    /// Test that the derive macro handles drops of initialized fields on partially initialized enums.
1083    #[test]
1084    fn test_enum_derive_handles_partial_drop() {
1085        /// Represents an enum that would leak if the derive macro didn't handle drops of initialized fields
1086        /// on error.
1087        #[derive(SchemaWrite, SchemaRead, proptest_derive::Arbitrary, Debug, PartialEq, Eq)]
1088        #[wincode(internal)]
1089        enum CouldLeak {
1090            A {
1091                a: DropCountedMaybeError,
1092                b: DropCountedMaybeError,
1093            },
1094            B(
1095                DropCountedMaybeError,
1096                DropCountedMaybeError,
1097                DropCountedMaybeError,
1098            ),
1099            C(DropCountedMaybeError),
1100            D,
1101        }
1102
1103        let _guard = TLDropGuard::new();
1104        proptest!(proptest_cfg(), |(could_leak: CouldLeak)| {
1105            let serialized = serialize(&could_leak).unwrap();
1106            let deserialized = CouldLeak::deserialize(&serialized);
1107            if let Ok(deserialized) = deserialized {
1108                prop_assert_eq!(could_leak, deserialized);
1109            }
1110        });
1111    }
1112
1113    #[test]
1114    fn test_tuple_handles_partial_drop() {
1115        let _guard = TLDropGuard::new();
1116        let serialized =
1117            { serialize(&(DropCounted::new(), DropCounted::new(), ErrorsOnRead)).unwrap() };
1118        let deserialized: ReadResult<(DropCounted, DropCounted, ErrorsOnRead)> =
1119            deserialize(&serialized);
1120        assert!(deserialized.is_err());
1121    }
1122
1123    #[test]
1124    fn test_vec_handles_partial_drop() {
1125        let _guard = TLDropGuard::new();
1126        proptest!(proptest_cfg(), |(vec in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100))| {
1127            let serialized = serialize(&vec).unwrap();
1128            let deserialized = <Vec<DropCountedMaybeError>>::deserialize(&serialized);
1129            if let Ok(deserialized) = deserialized {
1130                prop_assert_eq!(vec, deserialized);
1131            }
1132        });
1133    }
1134
1135    #[test]
1136    fn test_vec_deque_handles_partial_drop() {
1137        let _guard = TLDropGuard::new();
1138        proptest!(proptest_cfg(), |(vec in proptest::collection::vec_deque(any::<DropCountedMaybeError>(), 0..100))| {
1139            let serialized = serialize(&vec).unwrap();
1140            let deserialized = <VecDeque<DropCountedMaybeError>>::deserialize(&serialized);
1141            if let Ok(deserialized) = deserialized {
1142                prop_assert_eq!(vec, deserialized);
1143            }
1144        });
1145    }
1146
1147    #[test]
1148    fn test_boxed_slice_handles_partial_drop() {
1149        let _guard = TLDropGuard::new();
1150        proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(|vec| vec.into_boxed_slice()))| {
1151            let serialized = serialize(&slice).unwrap();
1152            let deserialized = <Box<[DropCountedMaybeError]>>::deserialize(&serialized);
1153            if let Ok(deserialized) = deserialized {
1154                prop_assert_eq!(slice, deserialized);
1155            }
1156        });
1157    }
1158
1159    #[test]
1160    fn test_rc_slice_handles_partial_drop() {
1161        let _guard = TLDropGuard::new();
1162        proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(Rc::from))| {
1163            let serialized = serialize(&slice).unwrap();
1164            let deserialized = <Rc<[DropCountedMaybeError]>>::deserialize(&serialized);
1165            if let Ok(deserialized) = deserialized {
1166                prop_assert_eq!(slice, deserialized);
1167            }
1168        });
1169    }
1170
1171    #[test]
1172    fn test_arc_slice_handles_partial_drop() {
1173        let _guard = TLDropGuard::new();
1174        proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(Arc::from))| {
1175            let serialized = serialize(&slice).unwrap();
1176            let deserialized = <Arc<[DropCountedMaybeError]>>::deserialize(&serialized);
1177            if let Ok(deserialized) = deserialized {
1178                prop_assert_eq!(slice, deserialized);
1179            }
1180        });
1181    }
1182
1183    #[test]
1184    fn test_arc_handles_drop() {
1185        let _guard = TLDropGuard::new();
1186        proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Rc::from))| {
1187            let serialized = serialize(&data).unwrap();
1188            let deserialized = deserialize(&serialized);
1189            if let Ok(deserialized) = deserialized {
1190                prop_assert_eq!(data, deserialized);
1191            }
1192        });
1193    }
1194
1195    #[test]
1196    fn test_rc_handles_drop() {
1197        let _guard = TLDropGuard::new();
1198        proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Rc::from))| {
1199            let serialized = serialize(&data).unwrap();
1200            let deserialized = deserialize(&serialized);
1201            if let Ok(deserialized) = deserialized {
1202                prop_assert_eq!(data, deserialized);
1203            }
1204        });
1205    }
1206
1207    #[test]
1208    fn test_box_handles_drop() {
1209        let _guard = TLDropGuard::new();
1210        proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Box::new))| {
1211            let serialized = serialize(&data).unwrap();
1212            let deserialized = deserialize(&serialized);
1213            if let Ok(deserialized) = deserialized {
1214                prop_assert_eq!(data, deserialized);
1215            }
1216        });
1217    }
1218
1219    #[test]
1220    fn test_array_handles_partial_drop() {
1221        let _guard = TLDropGuard::new();
1222
1223        proptest!(proptest_cfg(), |(array in proptest::array::uniform32(any::<DropCountedMaybeError>()))| {
1224            let serialized = serialize(&array).unwrap();
1225            let deserialized = <[DropCountedMaybeError; 32]>::deserialize(&serialized);
1226            if let Ok(deserialized) = deserialized {
1227                prop_assert_eq!(array, deserialized);
1228            }
1229        });
1230    }
1231
1232    #[test]
1233    fn test_uninit_builder_handles_partial_drop() {
1234        #[derive(SchemaWrite, UninitBuilder, Debug, proptest_derive::Arbitrary)]
1235        #[wincode(internal)]
1236        struct Test {
1237            a: DropCounted,
1238            b: DropCounted,
1239            c: DropCounted,
1240        }
1241
1242        {
1243            let _guard = TLDropGuard::new();
1244            proptest!(proptest_cfg(), |(test: Test)| {
1245                let serialized = serialize(&test).unwrap();
1246                let mut test = MaybeUninit::<Test>::uninit();
1247                let mut reader = serialized.as_slice();
1248                let mut builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut test);
1249                builder.read_a(reader.by_ref())?.read_b(reader.by_ref())?;
1250                prop_assert!(!builder.is_init());
1251                // Struct is not fully initialized, so the two initialized fields should be dropped.
1252            });
1253        }
1254
1255        #[derive(SchemaWrite, UninitBuilder, Debug, proptest_derive::Arbitrary)]
1256        #[wincode(internal)]
1257        // Same test, but with a tuple struct.
1258        struct TestTuple(DropCounted, DropCounted);
1259
1260        {
1261            let _guard = TLDropGuard::new();
1262            proptest!(proptest_cfg(), |(test: TestTuple)| {
1263                let serialized = serialize(&test).unwrap();
1264                let mut test = MaybeUninit::<TestTuple>::uninit();
1265                let reader = &mut serialized.as_slice();
1266                let mut builder = TestTupleUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut test);
1267                builder.read_0(reader)?;
1268                prop_assert!(!builder.is_init());
1269                // Struct is not fully initialized, so the first initialized field should be dropped.
1270            });
1271        }
1272    }
1273
1274    #[test]
1275    fn test_uninit_builder_nested_builder_handles_partial_drop() {
1276        #[derive(SchemaWrite, SchemaRead, UninitBuilder, Debug, proptest_derive::Arbitrary)]
1277        #[wincode(internal)]
1278        struct Inner {
1279            a: DropCounted,
1280            b: DropCounted,
1281            c: DropCounted,
1282        }
1283
1284        #[derive(SchemaWrite, UninitBuilder, Debug, proptest_derive::Arbitrary)]
1285        #[wincode(internal)]
1286        struct Test {
1287            inner: Inner,
1288            b: DropCounted,
1289        }
1290
1291        {
1292            let _guard = TLDropGuard::new();
1293            proptest!(proptest_cfg(), |(test: Test)| {
1294                let serialized = serialize(&test).unwrap();
1295                let mut test = MaybeUninit::<Test>::uninit();
1296                let mut reader = serialized.as_slice();
1297                let mut outer_builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut test);
1298                unsafe {
1299                    outer_builder.init_inner_with(|inner| {
1300                        let mut inner_builder = InnerUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(inner);
1301                        inner_builder.read_a(reader.by_ref())?;
1302                        inner_builder.read_b(reader.by_ref())?;
1303                        inner_builder.read_c(reader.by_ref())?;
1304                        assert!(inner_builder.is_init());
1305                        inner_builder.finish();
1306                        Ok(())
1307                    })?;
1308                }
1309                // Outer struct is not fully initialized, so the inner struct should be dropped.
1310            });
1311        }
1312    }
1313
1314    #[test]
1315    fn test_uninit_builder_nested_fully_initialized() {
1316        #[derive(
1317            SchemaWrite, SchemaRead, UninitBuilder, Debug, PartialEq, Eq, proptest_derive::Arbitrary,
1318        )]
1319        #[wincode(internal)]
1320        struct Inner {
1321            a: DropCounted,
1322            b: DropCounted,
1323            c: DropCounted,
1324        }
1325
1326        #[derive(SchemaWrite, UninitBuilder, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1327        #[wincode(internal)]
1328        struct Test {
1329            inner: Inner,
1330            b: DropCounted,
1331        }
1332
1333        {
1334            let _guard = TLDropGuard::new();
1335            proptest!(proptest_cfg(), |(test: Test)| {
1336                let serialized = serialize(&test).unwrap();
1337                let mut uninit = MaybeUninit::<Test>::uninit();
1338                let mut reader = serialized.as_slice();
1339                let mut outer_builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1340                unsafe {
1341                    outer_builder.init_inner_with(|inner| {
1342                        let mut inner_builder = InnerUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(inner);
1343                        inner_builder.read_a(reader.by_ref())?;
1344                        inner_builder.read_b(reader.by_ref())?;
1345                        inner_builder.read_c(reader.by_ref())?;
1346                        assert!(inner_builder.is_init());
1347                        inner_builder.finish();
1348                        Ok(())
1349                    })?;
1350                }
1351                outer_builder.read_b(reader.by_ref())?;
1352                prop_assert!(outer_builder.is_init());
1353                outer_builder.finish();
1354                let init = unsafe { uninit.assume_init() };
1355                prop_assert_eq!(test, init);
1356            });
1357        }
1358    }
1359
1360    #[test]
1361    fn test_uninit_builder() {
1362        #[derive(SchemaWrite, UninitBuilder, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1363        #[wincode(internal)]
1364        struct Test {
1365            a: Vec<u8>,
1366            b: [u8; 32],
1367            c: u64,
1368        }
1369
1370        proptest!(proptest_cfg(), |(test: Test)| {
1371            let serialized = serialize(&test).unwrap();
1372            let mut uninit = MaybeUninit::<Test>::uninit();
1373            let mut reader = serialized.as_slice();
1374            let mut builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1375            builder
1376                .read_a(reader.by_ref())?
1377                .read_b(reader.by_ref())?
1378                .write_c(test.c);
1379            prop_assert!(builder.is_init());
1380            builder.finish();
1381            let init = unsafe { uninit.assume_init() };
1382            prop_assert_eq!(test, init);
1383        });
1384    }
1385
1386    #[test]
1387    fn test_uninit_builder_uninit_ref() {
1388        #[derive(SchemaWrite, UninitBuilder, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1389        #[wincode(internal)]
1390        struct Test {
1391            a: Vec<u8>,
1392            b: [u8; 32],
1393            c: u64,
1394        }
1395
1396        proptest!(proptest_cfg(), |(test: Test)| {
1397            let serialized = serialize(&test).unwrap();
1398            let mut uninit = MaybeUninit::<Test>::uninit();
1399            let mut reader = serialized.as_slice();
1400            let mut builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1401            builder
1402                .read_a(reader.by_ref())?
1403                .read_b(reader.by_ref())?
1404                .write_c(test.c);
1405            prop_assert!(builder.is_init());
1406
1407            unsafe {
1408                prop_assert_eq!(builder.uninit_a_ref().assume_init_ref(), &test.a);
1409                prop_assert_eq!(builder.uninit_b_ref().assume_init_ref(), &test.b);
1410                prop_assert_eq!(builder.uninit_c_ref().assume_init_ref(), &test.c);
1411            }
1412
1413            builder.finish();
1414            let init = unsafe { uninit.assume_init() };
1415            prop_assert_eq!(test, init);
1416        });
1417    }
1418
1419    #[test]
1420    #[allow(deprecated)]
1421    fn test_struct_extensions_sanity() {
1422        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1423        #[wincode(internal, struct_extensions)]
1424        struct Test {
1425            a: Vec<u8>,
1426            b: [u8; 32],
1427            c: u64,
1428        }
1429
1430        proptest!(proptest_cfg(), |(test: Test)| {
1431            let serialized = serialize(&test).unwrap();
1432            let mut uninit = MaybeUninit::<Test>::uninit();
1433            let mut reader = serialized.as_slice();
1434            let mut builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1435            builder
1436                .read_a(reader.by_ref())?
1437                .read_b(reader.by_ref())?
1438                .write_c(test.c);
1439            prop_assert!(builder.is_init());
1440            builder.finish();
1441            let init = unsafe { uninit.assume_init() };
1442            prop_assert_eq!(test, init);
1443        });
1444    }
1445
1446    #[test]
1447    fn test_uninit_builder_with_container() {
1448        #[derive(UninitBuilder, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1449        #[wincode(internal)]
1450        struct Test {
1451            #[wincode(with = "containers::Vec<_, BincodeLen>")]
1452            a: Vec<u8>,
1453            b: [u8; 32],
1454            c: u64,
1455        }
1456
1457        proptest!(proptest_cfg(), |(test: Test)| {
1458            let mut uninit = MaybeUninit::<Test>::uninit();
1459            let mut builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1460            builder
1461                .write_a(test.a.clone())
1462                .write_b(test.b)
1463                .write_c(test.c);
1464            prop_assert!(builder.is_init());
1465            let init_mut = unsafe { builder.into_assume_init_mut() };
1466            prop_assert_eq!(&test, init_mut);
1467            // Ensure `uninit` is marked initialized so fields are dropped.
1468            let init = unsafe { uninit.assume_init() };
1469            prop_assert_eq!(test, init);
1470        });
1471    }
1472
1473    #[test]
1474    fn test_uninit_builder_extensions_with_reference() {
1475        #[derive(Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1476        struct Test {
1477            a: Vec<u8>,
1478            b: Option<String>,
1479        }
1480
1481        #[derive(UninitBuilder, Debug, PartialEq, Eq)]
1482        #[wincode(internal)]
1483        struct TestRef<'a> {
1484            a: &'a [u8],
1485            b: Option<&'a str>,
1486        }
1487
1488        proptest!(proptest_cfg(), |(test: Test)| {
1489            let mut uninit = MaybeUninit::<TestRef>::uninit();
1490            let mut builder = TestRefUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1491            builder
1492                .write_a(test.a.as_slice())
1493                .write_b(test.b.as_deref());
1494            prop_assert!(builder.is_init());
1495            builder.finish();
1496            let init = unsafe { uninit.assume_init() };
1497            prop_assert_eq!(test.a.as_slice(), init.a);
1498            prop_assert_eq!(test.b.as_deref(), init.b);
1499        });
1500    }
1501
1502    #[test]
1503    fn test_uninit_builder_with_mapped_type() {
1504        #[derive(Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1505        struct Test {
1506            a: Vec<u8>,
1507            b: [u8; 32],
1508            c: u64,
1509        }
1510
1511        #[derive(UninitBuilder)]
1512        #[wincode(internal, from = "Test")]
1513        #[allow(unused)]
1514        struct TestMapped {
1515            a: containers::Vec<u8, BincodeLen>,
1516            b: [u8; 32],
1517            c: u64,
1518        }
1519
1520        proptest!(proptest_cfg(), |(test: Test)| {
1521            let mut uninit = MaybeUninit::<Test>::uninit();
1522            let mut builder = TestMappedUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1523            builder
1524                .write_a(test.a.clone())
1525                .write_b(test.b)
1526                .write_c(test.c);
1527            prop_assert!(builder.is_init());
1528            builder.finish();
1529            let init = unsafe { uninit.assume_init() };
1530            prop_assert_eq!(test, init);
1531        });
1532    }
1533
1534    #[test]
1535    fn test_uninit_builder_builder_fully_initialized() {
1536        #[derive(SchemaWrite, UninitBuilder, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1537        #[wincode(internal)]
1538        struct Test {
1539            a: DropCounted,
1540            b: DropCounted,
1541            c: DropCounted,
1542        }
1543
1544        {
1545            let _guard = TLDropGuard::new();
1546            proptest!(proptest_cfg(), |(test: Test)| {
1547                let serialized = serialize(&test).unwrap();
1548                let mut uninit = MaybeUninit::<Test>::uninit();
1549                let mut reader = serialized.as_slice();
1550                let mut builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1551                builder
1552                    .read_a(reader.by_ref())?
1553                    .read_b(reader.by_ref())?
1554                    .read_c(reader.by_ref())?;
1555                prop_assert!(builder.is_init());
1556                let init = unsafe { builder.into_assume_init_mut() };
1557                prop_assert_eq!(&test, init);
1558
1559                let init = unsafe { uninit.assume_init() };
1560                prop_assert_eq!(test, init);
1561            });
1562        }
1563
1564        #[derive(SchemaWrite, UninitBuilder, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1565        #[wincode(internal)]
1566        // Same test, but with a tuple struct.
1567        struct TestTuple(DropCounted, DropCounted);
1568
1569        {
1570            let _guard = TLDropGuard::new();
1571            proptest!(proptest_cfg(), |(test: TestTuple)| {
1572                let serialized = serialize(&test).unwrap();
1573                let mut uninit = MaybeUninit::<TestTuple>::uninit();
1574                let mut reader = serialized.as_slice();
1575                let mut builder = TestTupleUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1576                builder
1577                    .read_0(reader.by_ref())?
1578                    .read_1(reader.by_ref())?;
1579                assert!(builder.is_init());
1580                builder.finish();
1581
1582                let init = unsafe { uninit.assume_init() };
1583                prop_assert_eq!(test, init);
1584            });
1585        }
1586    }
1587
1588    #[test]
1589    #[cfg(feature = "solana-short-vec")]
1590    fn test_uninit_builder_with() {
1591        use crate::len::ShortU16;
1592
1593        #[derive(
1594            SchemaWrite,
1595            UninitBuilder,
1596            Debug,
1597            PartialEq,
1598            Eq,
1599            proptest_derive::Arbitrary,
1600            serde::Serialize,
1601            serde::Deserialize,
1602        )]
1603        #[wincode(internal)]
1604        struct Test {
1605            #[wincode(with = "containers::Vec<u8, ShortU16>")]
1606            #[serde(with = "solana_short_vec")]
1607            foo: Vec<u8>,
1608        }
1609
1610        proptest!(proptest_cfg(), |(test: Test)| {
1611            let serialized = serialize(&test).unwrap();
1612            let bincode_serialized = bincode::serialize(&test).unwrap();
1613            prop_assert_eq!(&serialized, &bincode_serialized);
1614
1615            let bincode_deserialized: Test = bincode::deserialize(&bincode_serialized).unwrap();
1616            let mut uninit = MaybeUninit::<Test>::uninit();
1617            let mut builder = TestUninitBuilder::<DefaultConfig>::from_maybe_uninit_mut(&mut uninit);
1618            let mut reader = serialized.as_slice();
1619            builder.read_foo(reader.by_ref())?;
1620            builder.finish();
1621            let deserialized = unsafe { uninit.assume_init() };
1622
1623            prop_assert_eq!(&test, &bincode_deserialized);
1624            prop_assert_eq!(test, deserialized);
1625        });
1626    }
1627
1628    #[test]
1629    fn test_struct_with_reference_equivalence() {
1630        #[derive(
1631            SchemaWrite, SchemaRead, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize,
1632        )]
1633        #[wincode(internal)]
1634        struct WithReference<'a> {
1635            data: &'a str,
1636            id: u64,
1637        }
1638
1639        proptest!(proptest_cfg(), |(s in any::<String>(), id in any::<u64>())| {
1640            let serialized = serialize(&WithReference { data: &s, id }).unwrap();
1641            let bincode_serialized = bincode::serialize(&WithReference { data: &s, id }).unwrap();
1642            prop_assert_eq!(&serialized, &bincode_serialized);
1643            let deserialized: WithReference = deserialize(&serialized).unwrap();
1644            let bincode_deserialized: WithReference = bincode::deserialize(&bincode_serialized).unwrap();
1645            prop_assert_eq!(deserialized, bincode_deserialized);
1646        });
1647    }
1648
1649    #[test]
1650    fn test_skipped_fields() {
1651        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1652        #[wincode(internal)]
1653        struct Test {
1654            a: StructZeroCopy,
1655            #[wincode(skip)]
1656            b: [u8; 32],
1657            c: StructStatic,
1658            #[wincode(skip(default_val = 345))]
1659            d: u32,
1660        }
1661
1662        let expected = TypeMeta::Static {
1663            size: size_of::<StructZeroCopy>()
1664                + <StructStatic as SchemaWrite<DefaultConfig>>::TYPE_META.size_assert_static(),
1665            zero_copy: false,
1666        };
1667        assert_eq!(<Test as SchemaWrite<DefaultConfig>>::TYPE_META, expected);
1668
1669        proptest!(proptest_cfg(), |(test: Test)| {
1670            let mut serialized = serialize(&test).unwrap();
1671            let mut uninit_zeroed = MaybeUninit::<Test>::uninit();
1672            Test::deserialize_into(serialized.as_mut(), &mut uninit_zeroed).unwrap();
1673            let deserialized = unsafe { uninit_zeroed.assume_init() };
1674            assert_eq!(deserialized.b, [0; 32]);
1675            assert_eq!(deserialized.d, 345);
1676            let reinitialized = Test {
1677                b: test.b,
1678                d: test.d,
1679                ..deserialized
1680            };
1681            prop_assert_eq!(reinitialized, test);
1682        });
1683
1684        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1685        #[wincode(internal)]
1686        struct TestTuple(StructZeroCopy, #[wincode(skip)] u64, u32);
1687
1688        let expected = TypeMeta::Static {
1689            size: size_of::<StructZeroCopy>() + size_of::<u32>(),
1690            zero_copy: false,
1691        };
1692        assert_eq!(
1693            <TestTuple as SchemaWrite<DefaultConfig>>::TYPE_META,
1694            expected
1695        );
1696
1697        proptest!(proptest_cfg(), |(test: TestTuple)| {
1698            let mut serialized = serialize(&test).unwrap();
1699            let mut uninit_zeroed = MaybeUninit::<TestTuple>::uninit();
1700            TestTuple::deserialize_into(serialized.as_mut(), &mut uninit_zeroed).unwrap();
1701            let deserialized = unsafe { uninit_zeroed.assume_init() };
1702            assert_eq!(deserialized.1, 0);
1703            let reinitialized = TestTuple(deserialized.0, test.1, deserialized.2);
1704            prop_assert_eq!(reinitialized, test);
1705        });
1706
1707        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1708        #[wincode(internal)]
1709        enum TestEnum {
1710            X([u64; 17], u8),
1711            Y(Test),
1712            Z(([u64; 16], u8), #[wincode(skip(default_val = 9))] u8, u64),
1713            W {
1714                a: u8,
1715                #[wincode(skip(default_val = 123))]
1716                b: u16,
1717                c: [u64; 17],
1718            },
1719        }
1720        let expected = TypeMeta::Static {
1721            size: size_of::<u32>() // discriminant
1722                + size_of::<u64>() * 17 + size_of::<u8>(),
1723            zero_copy: false,
1724        };
1725        assert_eq!(
1726            <TestEnum as SchemaWrite<DefaultConfig>>::TYPE_META,
1727            expected
1728        );
1729
1730        proptest!(proptest_cfg(), |(test: TestEnum)| {
1731            let mut serialized = serialize(&test).unwrap();
1732            let mut uninit_zeroed = MaybeUninit::<TestEnum>::uninit();
1733            TestEnum::deserialize_into(serialized.as_mut(), &mut uninit_zeroed).unwrap();
1734
1735            let deserialized = unsafe { uninit_zeroed.assume_init() };
1736            let reinitialized = match (deserialized, &test) {
1737                (TestEnum::Y(deserialized_y), TestEnum::Y(test_y)) => {
1738                    assert_eq!(deserialized_y.b, [0; 32]);
1739                    assert_eq!(deserialized_y.d, 345);
1740                    TestEnum::Y(Test {
1741                        b: test_y.b,
1742                        d: test_y.d,
1743                        ..deserialized_y
1744                    })
1745                },
1746                (TestEnum::Z(d_0, d_1, d_2), TestEnum::Z(_, t_1, _)) => {
1747                    assert_eq!(d_1, 9);
1748                    TestEnum::Z(d_0, *t_1, d_2)
1749                },
1750                (TestEnum::W { a: d_a, b: d_b, c:  d_c }, TestEnum::W { a: _, b: test_b, c: _ }) => {
1751                    assert_eq!(d_b, 123);
1752                    TestEnum::W {
1753                        a: d_a,
1754                        b: *test_b,
1755                        c: d_c,
1756                    }
1757                },
1758                (other, _) => other
1759            };
1760            prop_assert_eq!(reinitialized, test);
1761        });
1762
1763        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1764        #[wincode(internal)]
1765        #[repr(C)]
1766        struct TestZeroCopy {
1767            a: StructZeroCopy,
1768            #[wincode(skip)]
1769            b: (),
1770            c: [u8; 16],
1771        }
1772        assert_eq!(
1773            <TestZeroCopy as SchemaWrite<DefaultConfig>>::TYPE_META,
1774            TypeMeta::Static {
1775                size: size_of::<StructZeroCopy>() + 16,
1776                zero_copy: true,
1777            }
1778        );
1779
1780        proptest!(proptest_cfg(), |(test: TestZeroCopy)| {
1781            let mut serialized = serialize(&test).unwrap();
1782            let mut uninit_zeroed = MaybeUninit::<TestZeroCopy>::uninit();
1783            TestZeroCopy::deserialize_into(serialized.as_mut(), &mut uninit_zeroed).unwrap();
1784            let deserialized = unsafe { uninit_zeroed.assume_init() };
1785            prop_assert_eq!(deserialized, test);
1786        });
1787
1788        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1789        #[wincode(internal)]
1790        #[repr(C)]
1791        struct TestNonZeroCopy {
1792            a: StructZeroCopy,
1793            #[wincode(skip(default_val = [1u8; 16]))]
1794            b: [u8; 16],
1795        }
1796        assert_eq!(
1797            <TestNonZeroCopy as SchemaWrite<DefaultConfig>>::TYPE_META,
1798            TypeMeta::Static {
1799                size: size_of::<StructZeroCopy>(),
1800                zero_copy: false,
1801            }
1802        );
1803
1804        proptest!(proptest_cfg(), |(test: TestNonZeroCopy)| {
1805            let mut serialized = serialize(&test).unwrap();
1806            let mut uninit_zeroed = MaybeUninit::<TestNonZeroCopy>::uninit();
1807            TestNonZeroCopy::deserialize_into(serialized.as_mut(), &mut uninit_zeroed).unwrap();
1808            let deserialized = unsafe { uninit_zeroed.assume_init() };
1809            assert_eq!(deserialized.b, [1u8; 16]);
1810            let reinitialized = TestNonZeroCopy {
1811                b: test.b,
1812                ..deserialized
1813            };
1814            prop_assert_eq!(reinitialized, test);
1815        });
1816    }
1817
1818    #[test]
1819    fn test_enum_equivalence() {
1820        #[derive(
1821            SchemaWrite,
1822            SchemaRead,
1823            Debug,
1824            PartialEq,
1825            Eq,
1826            serde::Serialize,
1827            serde::Deserialize,
1828            Clone,
1829            proptest_derive::Arbitrary,
1830        )]
1831        #[wincode(internal)]
1832        enum Enum {
1833            A { name: String, id: u64 },
1834            B(String, Vec<u8>),
1835            C,
1836        }
1837
1838        proptest!(proptest_cfg(), |(e: Enum)| {
1839            let serialized = serialize(&e).unwrap();
1840            let bincode_serialized = bincode::serialize(&e).unwrap();
1841            prop_assert_eq!(&serialized, &bincode_serialized);
1842            let deserialized: Enum = deserialize(&serialized).unwrap();
1843            let bincode_deserialized: Enum = bincode::deserialize(&bincode_serialized).unwrap();
1844            prop_assert_eq!(deserialized, bincode_deserialized);
1845        });
1846    }
1847
1848    #[test]
1849    fn enum_with_tag_encoding_roundtrip() {
1850        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1851        #[wincode(internal, tag_encoding = "u8")]
1852        enum Enum {
1853            A { name: String, id: u64 },
1854            B(String, Vec<u8>),
1855            C,
1856        }
1857
1858        proptest!(proptest_cfg(), |(e: Enum)| {
1859            let serialized = serialize(&e).unwrap();
1860            let deserialized: Enum = deserialize(&serialized).unwrap();
1861            prop_assert_eq!(deserialized, e);
1862        });
1863    }
1864
1865    #[test]
1866    fn enum_with_custom_tag_roundtrip() {
1867        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1868        #[wincode(internal)]
1869        enum Enum {
1870            #[wincode(tag = 5)]
1871            A { name: String, id: u64 },
1872            #[wincode(tag = 8)]
1873            B(String, Vec<u8>),
1874            #[wincode(tag = 13)]
1875            C,
1876        }
1877
1878        proptest!(proptest_cfg(), |(e: Enum)| {
1879            let serialized = serialize(&e).unwrap();
1880            let deserialized: Enum = deserialize(&serialized).unwrap();
1881            prop_assert_eq!(deserialized, e);
1882        });
1883
1884        proptest!(proptest_cfg(), |(e: Enum)| {
1885            let serialized = serialize(&e).unwrap();
1886            let int: u32 = match e {
1887                Enum::A { .. } => 5,
1888                Enum::B(..) => 8,
1889                Enum::C => 13,
1890            };
1891            prop_assert_eq!(&int.to_le_bytes(), &serialized[..4]);
1892        });
1893    }
1894
1895    #[test]
1896    fn unit_enum_with_tag_encoding_static_size() {
1897        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq)]
1898        #[wincode(internal, tag_encoding = "u8")]
1899        enum Enum {
1900            A,
1901            B,
1902            C,
1903        }
1904
1905        assert!(matches!(
1906            <Enum as SchemaWrite<DefaultConfig>>::TYPE_META,
1907            TypeMeta::Static {
1908                size: 1,
1909                zero_copy: false
1910            }
1911        ));
1912
1913        assert!(matches!(
1914            <Enum as SchemaRead<'_, DefaultConfig>>::TYPE_META,
1915            TypeMeta::Static {
1916                size: 1,
1917                zero_copy: false
1918            }
1919        ));
1920    }
1921
1922    #[test]
1923    fn unit_enum_with_static_size() {
1924        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq)]
1925        #[wincode(internal)]
1926        enum Enum {
1927            A,
1928            B,
1929            C,
1930        }
1931
1932        assert!(matches!(
1933            <Enum as SchemaWrite<DefaultConfig>>::TYPE_META,
1934            TypeMeta::Static {
1935                size: 4,
1936                zero_copy: false
1937            }
1938        ));
1939
1940        assert!(matches!(
1941            <Enum as SchemaRead<'_, DefaultConfig>>::TYPE_META,
1942            TypeMeta::Static {
1943                size: 4,
1944                zero_copy: false
1945            }
1946        ));
1947    }
1948
1949    #[test]
1950    fn enum_tag_encoding() {
1951        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1952        #[wincode(internal, tag_encoding = "u8")]
1953        enum EnumU8 {
1954            A,
1955            B,
1956            C,
1957        }
1958
1959        proptest!(proptest_cfg(), |(e: EnumU8)| {
1960            let serialized = serialize(&e).unwrap();
1961            let int = e as u8;
1962            prop_assert_eq!(&int.to_le_bytes(), &serialized[..]);
1963        });
1964
1965        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1966        #[wincode(internal, tag_encoding = "u8")]
1967        enum EnumTupleU8 {
1968            A(u64),
1969            B(StructStatic),
1970            C(StructNonStatic),
1971        }
1972
1973        proptest!(proptest_cfg(), |(e: EnumTupleU8)| {
1974            let serialized = serialize(&e).unwrap();
1975            let int: u8 = match e {
1976                EnumTupleU8::A(_) => 0,
1977                EnumTupleU8::B(_) => 1,
1978                EnumTupleU8::C(_) => 2,
1979            };
1980            prop_assert_eq!(&int.to_le_bytes(), &serialized[..1]);
1981        });
1982
1983        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1984        #[wincode(internal, tag_encoding = "u8")]
1985        enum EnumRecordU8 {
1986            A { id: u64 },
1987            B { data: StructStatic },
1988            C { data: StructNonStatic },
1989        }
1990
1991        proptest!(proptest_cfg(), |(e: EnumRecordU8)| {
1992            let serialized = serialize(&e).unwrap();
1993            let int: u8 = match e {
1994                EnumRecordU8::A { .. } => 0,
1995                EnumRecordU8::B { .. } => 1,
1996                EnumRecordU8::C { .. } => 2,
1997            };
1998            prop_assert_eq!(&int.to_le_bytes(), &serialized[..1]);
1999        });
2000    }
2001
2002    #[test]
2003    fn enum_static_uniform_variants() {
2004        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
2005        #[wincode(internal)]
2006        enum Enum {
2007            A {
2008                a: u64,
2009            },
2010            B {
2011                x: u32,
2012                y: u32,
2013            },
2014            C {
2015                a: u8,
2016                b: u8,
2017                c: u8,
2018                d: u8,
2019                e: u8,
2020                f: u8,
2021                g: u8,
2022                h: u8,
2023            },
2024        }
2025
2026        assert_eq!(
2027            <Enum as SchemaWrite<DefaultConfig>>::TYPE_META,
2028            TypeMeta::Static {
2029                // (account for discriminant u32)
2030                size: 8 + 4,
2031                zero_copy: false
2032            }
2033        );
2034        assert_eq!(
2035            <Enum as SchemaRead<'_, DefaultConfig>>::TYPE_META,
2036            TypeMeta::Static {
2037                // (account for discriminant u32)
2038                size: 8 + 4,
2039                zero_copy: false
2040            }
2041        );
2042
2043        proptest!(proptest_cfg(), |(e: Enum)| {
2044            let serialized = serialize(&e).unwrap();
2045            let deserialized: Enum = deserialize(&serialized).unwrap();
2046            prop_assert_eq!(deserialized, e);
2047        });
2048    }
2049
2050    #[test]
2051    fn enum_dynamic_non_uniform_variants() {
2052        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
2053        #[wincode(internal)]
2054        enum Enum {
2055            A { a: u64 },
2056            B { x: u32, y: u32 },
2057            C { a: u8, b: u8 },
2058        }
2059
2060        assert_eq!(
2061            <Enum as SchemaWrite<DefaultConfig>>::TYPE_META,
2062            TypeMeta::Dynamic
2063        );
2064        assert_eq!(
2065            <Enum as SchemaRead<'_, DefaultConfig>>::TYPE_META,
2066            TypeMeta::Dynamic
2067        );
2068
2069        proptest!(proptest_cfg(), |(e: Enum)| {
2070            let serialized = serialize(&e).unwrap();
2071            let deserialized: Enum = deserialize(&serialized).unwrap();
2072            prop_assert_eq!(deserialized, e);
2073        });
2074    }
2075
2076    #[test]
2077    fn enum_single_variant_type_meta_pass_thru() {
2078        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
2079        #[wincode(internal)]
2080        enum Enum {
2081            A { a: u8, b: [u8; 32] },
2082        }
2083
2084        // Single variant enums should use the `TypeMeta` of the variant, but the zero-copy
2085        // flag should be `false`, due to the discriminant having potentially invalid bit patterns.
2086        assert_eq!(
2087            <Enum as SchemaWrite<DefaultConfig>>::TYPE_META,
2088            TypeMeta::Static {
2089                size: 1 + 32 + 4,
2090                zero_copy: false
2091            }
2092        );
2093        assert_eq!(
2094            <Enum as SchemaRead<'_, DefaultConfig>>::TYPE_META,
2095            TypeMeta::Static {
2096                size: 1 + 32 + 4,
2097                zero_copy: false
2098            }
2099        );
2100    }
2101
2102    #[test]
2103    fn enum_unit_and_non_unit_dynamic() {
2104        #[derive(
2105            SchemaWrite,
2106            SchemaRead,
2107            Debug,
2108            PartialEq,
2109            proptest_derive::Arbitrary,
2110            serde::Serialize,
2111            serde::Deserialize,
2112        )]
2113        #[wincode(internal)]
2114        enum Enum {
2115            Unit,
2116            NonUnit(u8),
2117        }
2118
2119        assert_eq!(
2120            <Enum as SchemaWrite<DefaultConfig>>::TYPE_META,
2121            TypeMeta::Dynamic
2122        );
2123        assert_eq!(
2124            <Enum as SchemaRead<'_, DefaultConfig>>::TYPE_META,
2125            TypeMeta::Dynamic
2126        );
2127
2128        proptest!(proptest_cfg(), |(e: Enum)| {
2129            let serialized = serialize(&e).unwrap();
2130            let bincode_serialized = bincode::serialize(&e).unwrap();
2131            prop_assert_eq!(&serialized, &bincode_serialized);
2132
2133            let deserialized: Enum = deserialize(&serialized).unwrap();
2134            let bincode_deserialized: Enum = bincode::deserialize(&bincode_serialized).unwrap();
2135            prop_assert_eq!(&deserialized, &bincode_deserialized);
2136            prop_assert_eq!(deserialized, e);
2137        });
2138    }
2139
2140    #[test]
2141    fn test_enum_config_discriminant_u8() {
2142        let config = Configuration::default().with_tag_encoding::<u8>();
2143
2144        #[derive(SchemaRead, SchemaWrite, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
2145        #[wincode(internal)]
2146        enum Enum {
2147            A,
2148            B,
2149        }
2150
2151        assert_eq!(
2152            <Enum as SchemaRead<'_, _>>::type_meta(config),
2153            TypeMeta::Static {
2154                size: 1,
2155                zero_copy: false
2156            }
2157        );
2158
2159        assert_eq!(
2160            <Enum as SchemaWrite<_>>::type_meta(config),
2161            TypeMeta::Static {
2162                size: 1,
2163                zero_copy: false
2164            }
2165        );
2166
2167        proptest!(proptest_cfg(), |(e: Enum)| {
2168            let serialized = config::serialize(&e, config).unwrap();
2169            prop_assert_eq!(serialized.len(), 1);
2170            match e {
2171                Enum::A => prop_assert_eq!(serialized[0], 0),
2172                Enum::B => prop_assert_eq!(serialized[0], 1),
2173            }
2174            let deserialized: Enum = config::deserialize(&serialized, config).unwrap();
2175            prop_assert_eq!(deserialized, e);
2176        });
2177    }
2178
2179    #[test]
2180    fn test_enum_config_discriminant_override() {
2181        let config = Configuration::default().with_tag_encoding::<u8>();
2182
2183        #[derive(SchemaRead, SchemaWrite, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
2184        #[wincode(internal, tag_encoding = "u32")]
2185        enum Enum {
2186            A,
2187            B,
2188        }
2189
2190        assert_eq!(
2191            <Enum as SchemaRead<'_, _>>::type_meta(config),
2192            TypeMeta::Static {
2193                size: 4,
2194                zero_copy: false
2195            }
2196        );
2197
2198        assert_eq!(
2199            <Enum as SchemaWrite<_>>::type_meta(config),
2200            TypeMeta::Static {
2201                size: 4,
2202                zero_copy: false
2203            }
2204        );
2205
2206        proptest!(proptest_cfg(), |(e: Enum)| {
2207            let serialized = config::serialize(&e, config).unwrap();
2208            prop_assert_eq!(serialized.len(), 4);
2209            let discriminant = u32::from_le_bytes(serialized[0..4].try_into().unwrap());
2210            match e {
2211                Enum::A => prop_assert_eq!(discriminant, 0u32),
2212                Enum::B => prop_assert_eq!(discriminant, 1u32),
2213            }
2214            let deserialized: Enum = config::deserialize(&serialized, config).unwrap();
2215            prop_assert_eq!(deserialized, e);
2216        });
2217    }
2218
2219    #[test]
2220    fn test_enum_config_discriminant_u8_custom_tag() {
2221        let config = Configuration::default().with_tag_encoding::<u8>();
2222
2223        #[derive(SchemaRead, SchemaWrite, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
2224        #[wincode(internal)]
2225        enum Enum {
2226            #[wincode(tag = 2)]
2227            A,
2228            #[wincode(tag = 3)]
2229            B,
2230            #[wincode(tag = 5)]
2231            C,
2232        }
2233
2234        proptest!(proptest_cfg(), |(e: Enum)| {
2235            let serialized = config::serialize(&e, config).unwrap();
2236            prop_assert_eq!(serialized.len(), 1);
2237            match e {
2238                Enum::A => prop_assert_eq!(serialized[0], 2),
2239                Enum::B => prop_assert_eq!(serialized[0], 3),
2240                Enum::C => prop_assert_eq!(serialized[0], 5),
2241            }
2242            let deserialized: Enum = config::deserialize(&serialized, config).unwrap();
2243            prop_assert_eq!(deserialized, e);
2244        });
2245    }
2246
2247    #[test]
2248    fn test_phantom_data() {
2249        let val = PhantomData::<StructStatic>;
2250        let serialized = serialize(&val).unwrap();
2251        let bincode_serialized = bincode::serialize(&val).unwrap();
2252        assert_eq!(&serialized, &bincode_serialized);
2253        assert_eq!(
2254            <PhantomData<StructStatic> as SchemaWrite<DefaultConfig>>::size_of(&val).unwrap(),
2255            bincode::serialized_size(&val).unwrap() as usize
2256        );
2257        let deserialized: PhantomData<StructStatic> = deserialize(&serialized).unwrap();
2258        let bincode_deserialized: PhantomData<StructStatic> =
2259            bincode::deserialize(&bincode_serialized).unwrap();
2260        assert_eq!(deserialized, bincode_deserialized);
2261    }
2262
2263    #[test]
2264    fn test_unit() {
2265        let serialized = serialize(&()).unwrap();
2266        let bincode_serialized = bincode::serialize(&()).unwrap();
2267        assert_eq!(&serialized, &bincode_serialized);
2268        assert_eq!(
2269            <() as SchemaWrite<DefaultConfig>>::size_of(&()).unwrap(),
2270            bincode::serialized_size(&()).unwrap() as usize
2271        );
2272        assert!(deserialize::<()>(&serialized).is_ok());
2273        assert!(bincode::deserialize::<()>(&bincode_serialized).is_ok());
2274    }
2275
2276    #[test]
2277    fn test_duration_varint_type_meta_dynamic() {
2278        let config = Configuration::default().with_varint_encoding();
2279
2280        assert_eq!(
2281            <Duration as SchemaWrite<_>>::type_meta(config),
2282            TypeMeta::Dynamic
2283        );
2284        assert_eq!(
2285            <Duration as SchemaRead<'_, _>>::type_meta(config),
2286            TypeMeta::Dynamic
2287        );
2288
2289        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
2290        #[wincode(internal)]
2291        struct WithDuration {
2292            a: u8,
2293            d: Duration,
2294            b: u8,
2295        }
2296
2297        assert_eq!(
2298            <WithDuration as SchemaWrite<_>>::type_meta(config),
2299            TypeMeta::Dynamic
2300        );
2301        assert_eq!(
2302            <WithDuration as SchemaRead<'_, _>>::type_meta(config),
2303            TypeMeta::Dynamic
2304        );
2305
2306        let val = WithDuration {
2307            a: 1,
2308            d: Duration::new(0, 0),
2309            b: 2,
2310        };
2311
2312        // u64(0) + u32(0) use varint -> 1 byte each.
2313        assert_eq!(config::serialized_size(&val.d, config).unwrap(), 2);
2314
2315        // Buffer is intentionally < fixed-width size (1 + 12 + 1 = 14). Old (incorrect) TYPE_META
2316        // would try to reserve 14 bytes via a trusted window and fail with WriteSizeLimit.
2317        let mut buf = [0xAAu8; 13];
2318        let written = {
2319            let buf_len = buf.len();
2320            let mut writer: &mut [u8] = &mut buf;
2321            config::serialize_into(&mut writer, &val, config).unwrap();
2322            buf_len - writer.len()
2323        };
2324        assert_eq!(written, 4);
2325        assert_eq!(&buf[..written], &[1, 0, 0, 2]);
2326        assert!(buf[written..].iter().all(|&b| b == 0xAA));
2327
2328        let roundtrip: WithDuration = config::deserialize(&buf[..written], config).unwrap();
2329        assert_eq!(roundtrip, val);
2330    }
2331
2332    #[test]
2333    fn test_system_time_varint_type_meta_dynamic() {
2334        let config = Configuration::default().with_varint_encoding();
2335
2336        assert_eq!(
2337            <SystemTime as SchemaWrite<_>>::type_meta(config),
2338            TypeMeta::Dynamic
2339        );
2340        assert_eq!(
2341            <SystemTime as SchemaRead<'_, _>>::type_meta(config),
2342            TypeMeta::Dynamic
2343        );
2344
2345        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
2346        #[wincode(internal)]
2347        struct WithSystemTime {
2348            a: u8,
2349            t: SystemTime,
2350            b: u8,
2351        }
2352
2353        assert_eq!(
2354            <WithSystemTime as SchemaWrite<_>>::type_meta(config),
2355            TypeMeta::Dynamic
2356        );
2357        assert_eq!(
2358            <WithSystemTime as SchemaRead<'_, _>>::type_meta(config),
2359            TypeMeta::Dynamic
2360        );
2361
2362        let val = WithSystemTime {
2363            a: 1,
2364            t: UNIX_EPOCH,
2365            b: 2,
2366        };
2367
2368        // SystemTime encodes as Duration since UNIX_EPOCH.
2369        assert_eq!(config::serialized_size(&val.t, config).unwrap(), 2);
2370
2371        let mut buf = [0xAAu8; 13];
2372        let written = {
2373            let buf_len = buf.len();
2374            let mut writer: &mut [u8] = &mut buf;
2375            config::serialize_into(&mut writer, &val, config).unwrap();
2376            buf_len - writer.len()
2377        };
2378        assert_eq!(written, 4);
2379        assert_eq!(&buf[..written], &[1, 0, 0, 2]);
2380        assert!(buf[written..].iter().all(|&b| b == 0xAA));
2381
2382        let roundtrip: WithSystemTime = config::deserialize(&buf[..written], config).unwrap();
2383        assert_eq!(roundtrip, val);
2384    }
2385
2386    #[test]
2387    fn test_borrowed_bytes() {
2388        #[derive(
2389            SchemaWrite, SchemaRead, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize,
2390        )]
2391        #[wincode(internal)]
2392        struct BorrowedBytes<'a> {
2393            bytes: &'a [u8],
2394        }
2395
2396        proptest!(proptest_cfg(), |(bytes in proptest::collection::vec(any::<u8>(), 0..=100))| {
2397            let val = BorrowedBytes { bytes: &bytes };
2398            let bincode_serialized = bincode::serialize(&val).unwrap();
2399            let schema_serialized = serialize(&val).unwrap();
2400            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2401            let bincode_deserialized: BorrowedBytes = bincode::deserialize(&bincode_serialized).unwrap();
2402            let schema_deserialized: BorrowedBytes = deserialize(&schema_serialized).unwrap();
2403            prop_assert_eq!(&val, &bincode_deserialized);
2404            prop_assert_eq!(val, schema_deserialized);
2405        });
2406    }
2407
2408    #[test]
2409    fn test_boxed_slice_pod_drop() {
2410        #[derive(proptest_derive::Arbitrary, Debug, Clone, Copy)]
2411        #[allow(dead_code)]
2412        struct Signature([u8; 64]);
2413
2414        pod_wrapper! {
2415            unsafe struct PodSignature(Signature);
2416        }
2417
2418        type Target = containers::Box<[PodSignature], BincodeLen>;
2419        proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<Signature>(), 1..=32).prop_map(|vec| vec.into_boxed_slice()))| {
2420            let serialized = Target::serialize(&slice).unwrap();
2421            // Deliberately trigger the drop with a failed deserialization
2422            // This test is specifically to get miri to exercise the drop logic
2423            let deserialized = Target::deserialize(&serialized[..serialized.len() - 32]);
2424            prop_assert!(deserialized.is_err());
2425        });
2426    }
2427
2428    #[test]
2429    fn test_zero_copy_padding_disqualification() {
2430        #[derive(SchemaWrite, SchemaRead)]
2431        #[wincode(internal)]
2432        #[repr(C, align(4))]
2433        struct Padded {
2434            a: u8,
2435        }
2436
2437        assert!(matches!(
2438            <Padded as SchemaWrite<DefaultConfig>>::TYPE_META,
2439            TypeMeta::Static {
2440                // Serialized size is still the size of the byte, not the in-memory size.
2441                size: 1,
2442                // Padding disqualifies the type from zero-copy optimization.
2443                zero_copy: false
2444            }
2445        ));
2446
2447        assert!(matches!(
2448            <Padded as SchemaRead<'_, DefaultConfig>>::TYPE_META,
2449            TypeMeta::Static {
2450                // Serialized size is still the size of the byte, not the in-memory size.
2451                size: 1,
2452                // Padding disqualifies the type from zero-copy optimization.
2453                zero_copy: false
2454            }
2455        ));
2456    }
2457
2458    proptest! {
2459        #![proptest_config(proptest_cfg())]
2460
2461        #[test]
2462        fn test_char(val in any::<char>()) {
2463            let bincode_serialized = bincode::serialize(&val).unwrap();
2464            let schema_serialized = serialize(&val).unwrap();
2465            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2466            prop_assert_eq!(<char as SchemaWrite<DefaultConfig>>::size_of(&val).unwrap(), bincode::serialized_size(&val).unwrap() as usize);
2467
2468            let bincode_deserialized: char = bincode::deserialize(&bincode_serialized).unwrap();
2469            let schema_deserialized: char = deserialize(&schema_serialized).unwrap();
2470            prop_assert_eq!(val, bincode_deserialized);
2471            prop_assert_eq!(val, schema_deserialized);
2472        }
2473
2474        #[test]
2475        fn test_vec_elem_static(vec in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
2476            let bincode_serialized = bincode::serialize(&vec).unwrap();
2477            let schema_serialized = serialize(&vec).unwrap();
2478            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2479
2480            let bincode_deserialized: Vec<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2481            let schema_deserialized: Vec<StructStatic> = deserialize(&schema_serialized).unwrap();
2482            prop_assert_eq!(&vec, &bincode_deserialized);
2483            prop_assert_eq!(vec, schema_deserialized);
2484        }
2485
2486        #[test]
2487        fn test_vec_elem_zero_copy(vec in proptest::collection::vec(any::<StructZeroCopy>(), 0..=100)) {
2488            let bincode_serialized = bincode::serialize(&vec).unwrap();
2489            let schema_serialized = serialize(&vec).unwrap();
2490            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2491
2492            let bincode_deserialized: Vec<StructZeroCopy> = bincode::deserialize(&bincode_serialized).unwrap();
2493            let schema_deserialized: Vec<StructZeroCopy> = deserialize(&schema_serialized).unwrap();
2494            prop_assert_eq!(&vec, &bincode_deserialized);
2495            prop_assert_eq!(vec, schema_deserialized);
2496        }
2497
2498        #[test]
2499        fn test_vec_elem_non_static(vec in proptest::collection::vec(any::<StructNonStatic>(), 0..=16)) {
2500            let bincode_serialized = bincode::serialize(&vec).unwrap();
2501            let schema_serialized = serialize(&vec).unwrap();
2502            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2503
2504            let bincode_deserialized: Vec<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2505            let schema_deserialized: Vec<StructNonStatic> = deserialize(&schema_serialized).unwrap();
2506            prop_assert_eq!(&vec, &bincode_deserialized);
2507            prop_assert_eq!(vec, schema_deserialized);
2508        }
2509
2510        #[test]
2511        fn test_vec_elem_bytes(vec in proptest::collection::vec(any::<u8>(), 0..=100)) {
2512            let bincode_serialized = bincode::serialize(&vec).unwrap();
2513            let schema_serialized = serialize(&vec).unwrap();
2514            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2515
2516            let bincode_deserialized: Vec<u8> = bincode::deserialize(&bincode_serialized).unwrap();
2517            let schema_deserialized: Vec<u8> = deserialize(&schema_serialized).unwrap();
2518            prop_assert_eq!(&vec, &bincode_deserialized);
2519            prop_assert_eq!(vec, schema_deserialized);
2520        }
2521
2522        #[test]
2523        fn test_serialize_slice(slice in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
2524            let bincode_serialized = bincode::serialize(slice.as_slice()).unwrap();
2525            let schema_serialized = serialize(slice.as_slice()).unwrap();
2526            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2527        }
2528
2529        #[test]
2530        fn test_vec_pod(vec in proptest::collection::vec(any::<[u8; 32]>(), 0..=100)) {
2531            let bincode_serialized = bincode::serialize(&vec).unwrap();
2532            let schema_serialized = serialize(&vec).unwrap();
2533            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2534
2535            let bincode_deserialized: Vec<[u8; 32]> = bincode::deserialize(&bincode_serialized).unwrap();
2536            let schema_deserialized: Vec<[u8; 32]> = deserialize(&schema_serialized).unwrap();
2537            prop_assert_eq!(&vec, &bincode_deserialized);
2538            prop_assert_eq!(vec, schema_deserialized);
2539        }
2540
2541        #[test]
2542        fn test_vec_deque_elem_static(vec in proptest::collection::vec_deque(any::<StructStatic>(), 0..=100)) {
2543            let bincode_serialized = bincode::serialize(&vec).unwrap();
2544            let schema_serialized = serialize(&vec).unwrap();
2545            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2546
2547            let bincode_deserialized: VecDeque<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2548            let schema_deserialized: VecDeque<StructStatic> = deserialize(&schema_serialized).unwrap();
2549            prop_assert_eq!(&vec, &bincode_deserialized);
2550            prop_assert_eq!(vec, schema_deserialized);
2551        }
2552
2553        #[test]
2554        fn test_vec_deque_elem_non_static(vec in proptest::collection::vec_deque(any::<StructNonStatic>(), 0..=16)) {
2555            let bincode_serialized = bincode::serialize(&vec).unwrap();
2556            let schema_serialized = serialize(&vec).unwrap();
2557            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2558
2559            let bincode_deserialized: VecDeque<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2560            let schema_deserialized: VecDeque<StructNonStatic> = deserialize(&schema_serialized).unwrap();
2561            prop_assert_eq!(&vec, &bincode_deserialized);
2562            prop_assert_eq!(vec, schema_deserialized);
2563        }
2564
2565        #[test]
2566        fn test_vec_deque_elem_bytes(vec in proptest::collection::vec_deque(any::<u8>(), 0..=100)) {
2567            let bincode_serialized = bincode::serialize(&vec).unwrap();
2568            let schema_serialized = serialize(&vec).unwrap();
2569            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2570
2571            let bincode_deserialized: VecDeque<u8> = bincode::deserialize(&bincode_serialized).unwrap();
2572            let schema_deserialized: VecDeque<u8> = deserialize(&schema_serialized).unwrap();
2573            prop_assert_eq!(&vec, &bincode_deserialized);
2574            prop_assert_eq!(vec, schema_deserialized);
2575        }
2576
2577        #[test]
2578        fn test_hash_map_zero_copy(map in proptest::collection::hash_map(any::<u8>(), any::<StructZeroCopy>(), 0..=100)) {
2579            let bincode_serialized = bincode::serialize(&map).unwrap();
2580            let schema_serialized = serialize(&map).unwrap();
2581            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2582
2583            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2584            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2585            prop_assert_eq!(&map, &bincode_deserialized);
2586            prop_assert_eq!(map, schema_deserialized);
2587        }
2588
2589        #[test]
2590        fn test_hash_map_static(map in proptest::collection::hash_map(any::<u64>(), any::<StructStatic>(), 0..=100)) {
2591            let bincode_serialized = bincode::serialize(&map).unwrap();
2592            let schema_serialized = serialize(&map).unwrap();
2593            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2594
2595            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2596            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2597            prop_assert_eq!(&map, &bincode_deserialized);
2598            prop_assert_eq!(map, schema_deserialized);
2599        }
2600
2601        #[test]
2602        fn test_hash_map_non_static(map in proptest::collection::hash_map(any::<u64>(), any::<StructNonStatic>(), 0..=16)) {
2603            let bincode_serialized = bincode::serialize(&map).unwrap();
2604            let schema_serialized = serialize(&map).unwrap();
2605            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2606
2607            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2608            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2609            prop_assert_eq!(&map, &bincode_deserialized);
2610            prop_assert_eq!(map, schema_deserialized);
2611        }
2612
2613        #[test]
2614        fn test_hash_set_zero_copy(set in proptest::collection::hash_set(any::<StructZeroCopy>(), 0..=100)) {
2615            let bincode_serialized = bincode::serialize(&set).unwrap();
2616            let schema_serialized = serialize(&set).unwrap();
2617            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2618
2619            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2620            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2621            prop_assert_eq!(&set, &bincode_deserialized);
2622            prop_assert_eq!(set, schema_deserialized);
2623        }
2624
2625        #[test]
2626        fn test_hash_set_static(set in proptest::collection::hash_set(any::<StructStatic>(), 0..=100)) {
2627            let bincode_serialized = bincode::serialize(&set).unwrap();
2628            let schema_serialized = serialize(&set).unwrap();
2629            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2630
2631            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2632            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2633            prop_assert_eq!(&set, &bincode_deserialized);
2634            prop_assert_eq!(set, schema_deserialized);
2635        }
2636
2637        #[test]
2638        fn test_hash_set_non_static(set in proptest::collection::hash_set(any::<StructNonStatic>(), 0..=16)) {
2639            let bincode_serialized = bincode::serialize(&set).unwrap();
2640            let schema_serialized = serialize(&set).unwrap();
2641            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2642
2643            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2644            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2645            prop_assert_eq!(&set, &bincode_deserialized);
2646            prop_assert_eq!(set, schema_deserialized);
2647        }
2648
2649        #[test]
2650        fn test_sequences_with_hasher(data in proptest::collection::hash_map(any::<String>(), any::<HashSet<u32>>(), 0..16)) {
2651            #[derive(Default)]
2652            struct SumHasher(u64);
2653
2654            impl BuildHasher for SumHasher {
2655                type Hasher = Self;
2656                fn build_hasher(&self) -> Self::Hasher {
2657                    Self(0)
2658                }
2659            }
2660            impl Hasher for SumHasher {
2661                fn finish(&self) -> u64 {
2662                    self.0
2663                }
2664
2665                fn write(&mut self, bytes: &[u8]) {
2666                    self.0 += bytes.iter().map(|b| *b as u64).sum::<u64>();
2667                }
2668            }
2669
2670            type TestMap = HashMap<String, HashSet<u32, SumHasher>, SumHasher>;
2671            let test_data: TestMap = data.into_iter().map(|(k, v)| (k, HashSet::from_iter(v.into_iter()))).collect();
2672            let wincode_serialized = serialize(&test_data).unwrap();
2673            let bincode_serialized = bincode::serialize(&test_data).unwrap();
2674            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
2675
2676            let wincode_deserialized: TestMap = deserialize(&wincode_serialized).unwrap();
2677            let bincode_deserialized: TestMap = bincode::deserialize(&bincode_serialized).unwrap();
2678            prop_assert_eq!(&test_data, &wincode_deserialized);
2679            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
2680
2681            type RegularMap = HashMap<String, HashSet<u32>>;
2682            let regular_deserialized: RegularMap = deserialize(&wincode_serialized).unwrap();
2683            let regular_serialized = serialize(&regular_deserialized).unwrap();
2684            let test_deserialized: TestMap = deserialize(&regular_serialized).unwrap();
2685            prop_assert_eq!(test_data, test_deserialized);
2686        }
2687
2688
2689        #[test]
2690        fn test_btree_map_zero_copy(map in proptest::collection::btree_map(any::<u8>(), any::<StructZeroCopy>(), 0..=100)) {
2691            let bincode_serialized = bincode::serialize(&map).unwrap();
2692            let schema_serialized = serialize(&map).unwrap();
2693            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2694
2695            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2696            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2697            prop_assert_eq!(&map, &bincode_deserialized);
2698            prop_assert_eq!(map, schema_deserialized);
2699        }
2700
2701        #[test]
2702        fn test_btree_map_static(map in proptest::collection::btree_map(any::<u64>(), any::<StructStatic>(), 0..=100)) {
2703            let bincode_serialized = bincode::serialize(&map).unwrap();
2704            let schema_serialized = serialize(&map).unwrap();
2705            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2706
2707            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2708            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2709            prop_assert_eq!(&map, &bincode_deserialized);
2710            prop_assert_eq!(map, schema_deserialized);
2711        }
2712
2713        #[test]
2714        fn test_btree_map_non_static(map in proptest::collection::btree_map(any::<u64>(), any::<StructNonStatic>(), 0..=16)) {
2715            let bincode_serialized = bincode::serialize(&map).unwrap();
2716            let schema_serialized = serialize(&map).unwrap();
2717            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2718
2719            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2720            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2721            prop_assert_eq!(&map, &bincode_deserialized);
2722            prop_assert_eq!(map, schema_deserialized);
2723        }
2724
2725        #[test]
2726        fn test_btree_set_zero_copy(set in proptest::collection::btree_set(any::<StructZeroCopy>(), 0..=100)) {
2727            let bincode_serialized = bincode::serialize(&set).unwrap();
2728            let schema_serialized = serialize(&set).unwrap();
2729            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2730
2731            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2732            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2733            prop_assert_eq!(&set, &bincode_deserialized);
2734            prop_assert_eq!(set, schema_deserialized);
2735        }
2736
2737        #[test]
2738        fn test_btree_set_static(set in proptest::collection::btree_set(any::<StructStatic>(), 0..=100)) {
2739            let bincode_serialized = bincode::serialize(&set).unwrap();
2740            let schema_serialized = serialize(&set).unwrap();
2741            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2742
2743            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2744            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2745            prop_assert_eq!(&set, &bincode_deserialized);
2746            prop_assert_eq!(set, schema_deserialized);
2747        }
2748
2749        #[test]
2750        fn test_btree_set_non_static(map in proptest::collection::btree_set(any::<StructNonStatic>(), 0..=16)) {
2751            let bincode_serialized = bincode::serialize(&map).unwrap();
2752            let schema_serialized = serialize(&map).unwrap();
2753            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2754
2755            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2756            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2757            prop_assert_eq!(&map, &bincode_deserialized);
2758            prop_assert_eq!(map, schema_deserialized);
2759        }
2760
2761        #[test]
2762        fn test_binary_heap_zero_copy(heap in proptest::collection::binary_heap(any::<StructZeroCopy>(), 0..=100)) {
2763            let bincode_serialized = bincode::serialize(&heap).unwrap();
2764            let schema_serialized = serialize(&heap).unwrap();
2765            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2766
2767            let bincode_deserialized: BinaryHeap<StructZeroCopy> = bincode::deserialize(&bincode_serialized).unwrap();
2768            let schema_deserialized: BinaryHeap<StructZeroCopy> = deserialize(&schema_serialized).unwrap();
2769            prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
2770            prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
2771        }
2772
2773        #[test]
2774        fn test_binary_heap_static(heap in proptest::collection::binary_heap(any::<StructStatic>(), 0..=100)) {
2775            let bincode_serialized = bincode::serialize(&heap).unwrap();
2776            let schema_serialized = serialize(&heap).unwrap();
2777            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2778
2779            let bincode_deserialized: BinaryHeap<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2780            let schema_deserialized: BinaryHeap<StructStatic> = deserialize(&schema_serialized).unwrap();
2781            prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
2782            prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
2783        }
2784
2785        #[test]
2786        fn test_binary_heap_non_static(heap in proptest::collection::binary_heap(any::<StructNonStatic>(), 0..=16)) {
2787            let bincode_serialized = bincode::serialize(&heap).unwrap();
2788            let schema_serialized = serialize(&heap).unwrap();
2789            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2790
2791            let bincode_deserialized: BinaryHeap<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2792            let schema_deserialized: BinaryHeap<StructNonStatic> = deserialize(&schema_serialized).unwrap();
2793            prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
2794            prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
2795        }
2796
2797        #[test]
2798        fn test_linked_list_zero_copy(list in proptest::collection::linked_list(any::<StructZeroCopy>(), 0..=100)) {
2799            let bincode_serialized = bincode::serialize(&list).unwrap();
2800            let schema_serialized = serialize(&list).unwrap();
2801            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2802
2803            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2804            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2805            prop_assert_eq!(&list, &bincode_deserialized);
2806            prop_assert_eq!(list, schema_deserialized);
2807        }
2808
2809        #[test]
2810        fn test_linked_list_static(list in proptest::collection::linked_list(any::<StructStatic>(), 0..=100)) {
2811            let bincode_serialized = bincode::serialize(&list).unwrap();
2812            let schema_serialized = serialize(&list).unwrap();
2813            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2814
2815            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2816            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2817            prop_assert_eq!(&list, &bincode_deserialized);
2818            prop_assert_eq!(list, schema_deserialized);
2819        }
2820
2821        #[test]
2822        fn test_linked_list_non_static(list in proptest::collection::linked_list(any::<StructNonStatic>(), 0..=16)) {
2823            let bincode_serialized = bincode::serialize(&list).unwrap();
2824            let schema_serialized = serialize(&list).unwrap();
2825            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2826
2827            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2828            let schema_deserialized = deserialize(&schema_serialized).unwrap();
2829            prop_assert_eq!(&list, &bincode_deserialized);
2830            prop_assert_eq!(list, schema_deserialized);
2831        }
2832
2833        #[test]
2834        fn test_array_bytes(array in any::<[u8; 32]>()) {
2835            let bincode_serialized = bincode::serialize(&array).unwrap();
2836            let schema_serialized = serialize(&array).unwrap();
2837            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2838
2839            let bincode_deserialized: [u8; 32] = bincode::deserialize(&bincode_serialized).unwrap();
2840            let schema_deserialized: [u8; 32] = deserialize(&schema_serialized).unwrap();
2841            prop_assert_eq!(&array, &bincode_deserialized);
2842            prop_assert_eq!(array, schema_deserialized);
2843        }
2844
2845        #[test]
2846        fn test_array_static(array in any::<[u64; 32]>()) {
2847            let bincode_serialized = bincode::serialize(&array).unwrap();
2848            type Target = [u64; 32];
2849            let schema_serialized = Target::serialize(&array).unwrap();
2850            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2851            let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
2852            let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
2853            prop_assert_eq!(&array, &bincode_deserialized);
2854            prop_assert_eq!(array, schema_deserialized);
2855        }
2856
2857        #[test]
2858        fn test_array_non_static(array in any::<[StructNonStatic; 16]>()) {
2859            let bincode_serialized = bincode::serialize(&array).unwrap();
2860            type Target = [StructNonStatic; 16];
2861            let schema_serialized = Target::serialize(&array).unwrap();
2862            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2863            let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
2864            let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
2865            prop_assert_eq!(&array, &bincode_deserialized);
2866            prop_assert_eq!(array, schema_deserialized);
2867        }
2868
2869        #[test]
2870        fn test_option(option in proptest::option::of(any::<StructStatic>())) {
2871            let bincode_serialized = bincode::serialize(&option).unwrap();
2872            let schema_serialized = serialize(&option).unwrap();
2873
2874            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2875            let bincode_deserialized: Option<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2876            let schema_deserialized: Option<StructStatic> = deserialize(&schema_serialized).unwrap();
2877            prop_assert_eq!(&option, &bincode_deserialized);
2878            prop_assert_eq!(&option, &schema_deserialized);
2879        }
2880
2881        #[test]
2882        fn test_option_container(option in proptest::option::of(any::<[u8; 32]>())) {
2883            let bincode_serialized = bincode::serialize(&option).unwrap();
2884            type Target = Option<[u8; 32]>;
2885            let schema_serialized = Target::serialize(&option).unwrap();
2886            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2887            let bincode_deserialized: Option<[u8; 32]> = bincode::deserialize(&bincode_serialized).unwrap();
2888            let schema_deserialized: Option<[u8; 32]> = Target::deserialize(&schema_serialized).unwrap();
2889            prop_assert_eq!(&option, &bincode_deserialized);
2890            prop_assert_eq!(&option, &schema_deserialized);
2891        }
2892
2893        #[test]
2894        fn test_bool(val in any::<bool>()) {
2895            let bincode_serialized = bincode::serialize(&val).unwrap();
2896            let schema_serialized = serialize(&val).unwrap();
2897            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2898            let bincode_deserialized: bool = bincode::deserialize(&bincode_serialized).unwrap();
2899            let schema_deserialized: bool = deserialize(&schema_serialized).unwrap();
2900            prop_assert_eq!(val, bincode_deserialized);
2901            prop_assert_eq!(val, schema_deserialized);
2902        }
2903
2904        #[test]
2905        fn test_bool_invalid_bit_pattern(val in 2u8..=255) {
2906            let bincode_deserialized: Result<bool,_> = bincode::deserialize(&[val]);
2907            let schema_deserialized: Result<bool,_> = deserialize(&[val]);
2908            prop_assert!(bincode_deserialized.is_err());
2909            prop_assert!(schema_deserialized.is_err());
2910        }
2911
2912        #[test]
2913        fn test_box(s in any::<StructStatic>()) {
2914            let data = Box::new(s);
2915            let bincode_serialized = bincode::serialize(&data).unwrap();
2916            let schema_serialized = serialize(&data).unwrap();
2917            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2918
2919            let bincode_deserialized: Box<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2920            let schema_deserialized: Box<StructStatic> = deserialize(&schema_serialized).unwrap();
2921            prop_assert_eq!(&data, &bincode_deserialized);
2922            prop_assert_eq!(&data, &schema_deserialized);
2923        }
2924
2925        #[test]
2926        fn test_rc(s in any::<StructStatic>()) {
2927            let data = Rc::new(s);
2928            let bincode_serialized = bincode::serialize(&data).unwrap();
2929            let schema_serialized = serialize(&data).unwrap();
2930            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2931
2932            let bincode_deserialized: Rc<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2933            let schema_deserialized: Rc<StructStatic> = deserialize(&schema_serialized).unwrap();
2934            prop_assert_eq!(&data, &bincode_deserialized);
2935            prop_assert_eq!(&data, &schema_deserialized);
2936        }
2937
2938        #[test]
2939        fn test_arc(s in any::<StructStatic>()) {
2940            let data = Arc::new(s);
2941            let bincode_serialized = bincode::serialize(&data).unwrap();
2942            let schema_serialized = serialize(&data).unwrap();
2943            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2944
2945            let bincode_deserialized: Arc<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2946            let schema_deserialized: Arc<StructStatic> = deserialize(&schema_serialized).unwrap();
2947            prop_assert_eq!(&data, &bincode_deserialized);
2948            prop_assert_eq!(&data, &schema_deserialized);
2949        }
2950
2951        #[test]
2952        fn test_boxed_slice_zero_copy(vec in proptest::collection::vec(any::<StructZeroCopy>(), 0..=100)) {
2953            let data = vec.into_boxed_slice();
2954            let bincode_serialized = bincode::serialize(&data).unwrap();
2955            let schema_serialized = serialize(&data).unwrap();
2956            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2957
2958            let bincode_deserialized: Box<[StructZeroCopy]> = bincode::deserialize(&bincode_serialized).unwrap();
2959            let schema_deserialized: Box<[StructZeroCopy]> = deserialize(&schema_serialized).unwrap();
2960            prop_assert_eq!(&data, &bincode_deserialized);
2961            prop_assert_eq!(&data, &schema_deserialized);
2962        }
2963
2964        #[test]
2965        fn test_boxed_slice_static(vec in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
2966            let data = vec.into_boxed_slice();
2967            let bincode_serialized = bincode::serialize(&data).unwrap();
2968            let schema_serialized = serialize(&data).unwrap();
2969            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2970
2971            let bincode_deserialized: Box<[StructStatic]> = bincode::deserialize(&bincode_serialized).unwrap();
2972            let schema_deserialized: Box<[StructStatic]> = deserialize(&schema_serialized).unwrap();
2973            prop_assert_eq!(&data, &bincode_deserialized);
2974            prop_assert_eq!(&data, &schema_deserialized);
2975        }
2976
2977        #[test]
2978        fn test_boxed_slice_non_static(vec in proptest::collection::vec(any::<StructNonStatic>(), 0..=16)) {
2979            let data = vec.into_boxed_slice();
2980            let bincode_serialized = bincode::serialize(&data).unwrap();
2981            type Target = Box<[StructNonStatic]>;
2982            let schema_serialized = serialize(&data).unwrap();
2983            prop_assert_eq!(&bincode_serialized, &schema_serialized);
2984
2985            let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
2986            let schema_deserialized: Target = Target::deserialize(&schema_serialized).unwrap();
2987            prop_assert_eq!(&data, &bincode_deserialized);
2988            prop_assert_eq!(&data, &schema_deserialized);
2989        }
2990
2991        #[test]
2992        fn test_integers(
2993            val in (
2994                any::<u8>(),
2995                any::<i8>(),
2996                any::<u16>(),
2997                any::<i16>(),
2998                any::<u32>(),
2999                any::<i32>(),
3000                any::<usize>(),
3001                any::<isize>(),
3002                any::<u64>(),
3003                any::<i64>(),
3004                any::<u128>(),
3005                any::<i128>()
3006            )
3007        ) {
3008            type Target = (u8, i8, u16, i16, u32, i32, usize, isize, u64, i64, u128, i128);
3009            let bincode_serialized = bincode::serialize(&val).unwrap();
3010            let schema_serialized = serialize(&val).unwrap();
3011            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3012            let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
3013            let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
3014            prop_assert_eq!(val, bincode_deserialized);
3015            prop_assert_eq!(val, schema_deserialized);
3016        }
3017
3018        #[test]
3019        fn test_tuple_zero_copy(
3020            tuple in (
3021                any::<StructZeroCopy>(),
3022                any::<[u8; 32]>(),
3023            )
3024        ) {
3025            let bincode_serialized = bincode::serialize(&tuple).unwrap();
3026            let schema_serialized = serialize(&tuple).unwrap();
3027
3028            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3029            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
3030            let schema_deserialized = deserialize(&schema_serialized).unwrap();
3031            prop_assert_eq!(&tuple, &bincode_deserialized);
3032            prop_assert_eq!(&tuple, &schema_deserialized);
3033
3034        }
3035
3036        #[test]
3037        fn test_tuple_static(
3038            tuple in (
3039                any::<StructStatic>(),
3040                any::<[u8; 32]>(),
3041            )
3042        ) {
3043            let bincode_serialized = bincode::serialize(&tuple).unwrap();
3044            let schema_serialized = serialize(&tuple).unwrap();
3045
3046            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3047            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
3048            let schema_deserialized = deserialize(&schema_serialized).unwrap();
3049            prop_assert_eq!(&tuple, &bincode_deserialized);
3050            prop_assert_eq!(&tuple, &schema_deserialized);
3051
3052        }
3053
3054        #[test]
3055        fn test_tuple_non_static(
3056            tuple in (
3057                any::<StructNonStatic>(),
3058                any::<[u8; 32]>(),
3059                proptest::collection::vec(any::<StructStatic>(), 0..=100),
3060            )
3061        ) {
3062            let bincode_serialized = bincode::serialize(&tuple).unwrap();
3063            type BincodeTarget = (StructNonStatic, [u8; 32], Vec<StructStatic>);
3064            type Target = (StructNonStatic, [u8; 32], Vec<StructStatic>);
3065            let schema_serialized = Target::serialize(&tuple).unwrap();
3066
3067            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3068            let bincode_deserialized: BincodeTarget = bincode::deserialize(&bincode_serialized).unwrap();
3069            let schema_deserialized = Target::deserialize(&schema_serialized).unwrap();
3070            prop_assert_eq!(&tuple, &bincode_deserialized);
3071            prop_assert_eq!(&tuple, &schema_deserialized);
3072
3073        }
3074
3075        #[test]
3076        fn test_str(str in any::<String>()) {
3077            let bincode_serialized = bincode::serialize(&str).unwrap();
3078            let schema_serialized = serialize(&str).unwrap();
3079            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3080            let bincode_deserialized: &str = bincode::deserialize(&bincode_serialized).unwrap();
3081            let schema_deserialized: &str = deserialize(&schema_serialized).unwrap();
3082            prop_assert_eq!(&str, &bincode_deserialized);
3083            prop_assert_eq!(&str, &schema_deserialized);
3084
3085            let bincode_deserialized: String = bincode::deserialize(&bincode_serialized).unwrap();
3086            let schema_deserialized: String = deserialize(&schema_serialized).unwrap();
3087            prop_assert_eq!(&str, &bincode_deserialized);
3088            prop_assert_eq!(&str, &schema_deserialized);
3089        }
3090
3091        #[test]
3092        fn test_struct_zero_copy(val in any::<StructZeroCopy>()) {
3093            let bincode_serialized = bincode::serialize(&val).unwrap();
3094            let schema_serialized = serialize(&val).unwrap();
3095            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3096
3097            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
3098            let schema_deserialized = deserialize(&schema_serialized).unwrap();
3099            prop_assert_eq!(&val, &bincode_deserialized);
3100            prop_assert_eq!(&val, &schema_deserialized);
3101        }
3102
3103        #[test]
3104        fn test_struct_static(val in any::<StructStatic>()) {
3105            let bincode_serialized = bincode::serialize(&val).unwrap();
3106            let schema_serialized = serialize(&val).unwrap();
3107            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3108
3109            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
3110            let schema_deserialized = deserialize(&schema_serialized).unwrap();
3111            prop_assert_eq!(&val, &bincode_deserialized);
3112            prop_assert_eq!(&val, &schema_deserialized);
3113        }
3114
3115        #[test]
3116        fn test_struct_non_static(val in any::<StructNonStatic>()) {
3117            let bincode_serialized = bincode::serialize(&val).unwrap();
3118            let schema_serialized = serialize(&val).unwrap();
3119            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3120
3121            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
3122            let schema_deserialized = deserialize(&schema_serialized).unwrap();
3123            prop_assert_eq!(&val, &bincode_deserialized);
3124            prop_assert_eq!(&val, &schema_deserialized);
3125        }
3126
3127        #[test]
3128        fn test_floats(
3129            val in (
3130                any::<f32>(),
3131                any::<f64>(),
3132            )
3133        ) {
3134            let bincode_serialized = bincode::serialize(&val).unwrap();
3135            let schema_serialized = serialize(&val).unwrap();
3136            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3137
3138            let bincode_deserialized: (f32, f64) = bincode::deserialize(&bincode_serialized).unwrap();
3139            let schema_deserialized: (f32, f64) = deserialize(&schema_serialized).unwrap();
3140            prop_assert_eq!(val, bincode_deserialized);
3141            prop_assert_eq!(val, schema_deserialized);
3142        }
3143    }
3144
3145    #[test]
3146    fn test_struct_zero_copy_refs() {
3147        // Owned zero-copy type.
3148        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
3149        #[wincode(internal)]
3150        #[repr(C)]
3151        struct Zc {
3152            a: u8,
3153            b: [u8; 64],
3154            c: i8,
3155            d: [i8; 64],
3156        }
3157
3158        // `Zc`, mirrored with references.
3159        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
3160        #[wincode(internal)]
3161        #[repr(C)]
3162        struct ZcRefs<'a> {
3163            a: &'a u8,
3164            b: &'a [u8; 64],
3165            c: &'a i8,
3166            d: &'a [i8; 64],
3167        }
3168
3169        // `Zc`, wrapped in a reference.
3170        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
3171        #[wincode(internal)]
3172        #[repr(transparent)]
3173        struct ZcWrapper<'a> {
3174            data: &'a Zc,
3175        }
3176
3177        impl<'a> From<&'a ZcRefs<'a>> for Zc {
3178            fn from(value: &'a ZcRefs<'a>) -> Self {
3179                Self {
3180                    a: *value.a,
3181                    b: *value.b,
3182                    c: *value.c,
3183                    d: *value.d,
3184                }
3185            }
3186        }
3187
3188        proptest!(proptest_cfg(), |(data in any::<Zc>())| {
3189            let serialized = serialize(&data).unwrap();
3190            let deserialized = Zc::deserialize(&serialized).unwrap();
3191            assert_eq!(data, deserialized);
3192
3193            let serialized_ref = serialize(&ZcRefs { a: &data.a, b: &data.b, c: &data.c, d: &data.d }).unwrap();
3194            assert_eq!(serialized_ref, serialized);
3195            let deserialized_ref = ZcRefs::deserialize(&serialized_ref).unwrap();
3196            assert_eq!(data, (&deserialized_ref).into());
3197
3198            let serialized_wrapper = serialize(&ZcWrapper { data: &data }).unwrap();
3199            assert_eq!(serialized_wrapper, serialized);
3200            let deserialized_wrapper = ZcWrapper::deserialize(&serialized_wrapper).unwrap();
3201            assert_eq!(data, *deserialized_wrapper.data);
3202        });
3203    }
3204
3205    #[test]
3206    fn test_zero_copy_ref_with_integer_types() {
3207        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
3208        #[wincode(internal)]
3209        struct ZcRef<'a> {
3210            x: &'a StructZeroCopy,
3211        }
3212
3213        proptest!(proptest_cfg(), |(data in any::<StructZeroCopy>())| {
3214            let serialized = serialize_aligned(&data).unwrap();
3215            let deserialized: ZcRef<'_> = deserialize(&serialized).unwrap();
3216            assert_eq!(data, *deserialized.x);
3217        });
3218    }
3219
3220    #[test]
3221    fn test_zero_copy_enum_with_integer_types() {
3222        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
3223        #[wincode(internal)]
3224        #[wincode(tag_encoding = "u128")]
3225        enum Enum {
3226            A,
3227            B(StructZeroCopy),
3228        }
3229
3230        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
3231        #[wincode(internal)]
3232        #[wincode(tag_encoding = "u128")]
3233        enum EnumRef<'a> {
3234            A,
3235            B(&'a StructZeroCopy),
3236        }
3237
3238        proptest!(proptest_cfg(), |(data in any::<Enum>())| {
3239            let serialized = serialize_aligned(&data).unwrap();
3240            let deserialized: EnumRef<'_> = deserialize(&serialized).unwrap();
3241            match data {
3242                Enum::A => prop_assert!(matches!(deserialized, EnumRef::A)),
3243                Enum::B(x) => prop_assert!(matches!(deserialized, EnumRef::B(y) if &x == y)),
3244            }
3245        });
3246    }
3247
3248    #[test]
3249    fn test_empty_struct() {
3250        #[derive(
3251            Debug,
3252            SchemaWrite,
3253            SchemaRead,
3254            Default,
3255            PartialEq,
3256            Eq,
3257            serde::Serialize,
3258            serde::Deserialize,
3259        )]
3260        #[wincode(internal)]
3261        struct EmptyStruct {}
3262
3263        let empty = EmptyStruct::default();
3264
3265        let bincode_serialized = bincode::serialize(&empty).unwrap();
3266        let schema_serialized = serialize(&empty).unwrap();
3267
3268        // Empty structs should serialize to zero bytes
3269        assert_eq!(bincode_serialized, schema_serialized);
3270        assert_eq!(bincode_serialized.len(), 0);
3271
3272        let bincode_deserialized: EmptyStruct = bincode::deserialize(&bincode_serialized).unwrap();
3273        let schema_deserialized: EmptyStruct = deserialize(&schema_serialized).unwrap();
3274
3275        assert_eq!(empty, bincode_deserialized);
3276        assert_eq!(empty, schema_deserialized);
3277    }
3278
3279    #[test]
3280    fn test_pod_zero_copy() {
3281        #[derive(Debug, PartialEq, Eq, proptest_derive::Arbitrary, Clone, Copy)]
3282        #[repr(transparent)]
3283        struct Address([u8; 64]);
3284
3285        pod_wrapper! {
3286            unsafe struct PodAddress(Address);
3287        }
3288
3289        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
3290        #[wincode(internal)]
3291        #[repr(C)]
3292        struct MyStruct {
3293            #[wincode(with = "PodAddress")]
3294            address: Address,
3295        }
3296
3297        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
3298        #[wincode(internal)]
3299        struct MyStructRef<'a> {
3300            inner: &'a MyStruct,
3301        }
3302
3303        proptest!(proptest_cfg(), |(data in any::<MyStruct>())| {
3304            let serialized = serialize(&data).unwrap();
3305            let deserialized = MyStruct::deserialize(&serialized).unwrap();
3306            assert_eq!(data, deserialized);
3307
3308            let serialized_ref = serialize(&MyStructRef { inner: &data }).unwrap();
3309            assert_eq!(serialized_ref, serialized);
3310            let deserialized_ref = MyStructRef::deserialize(&serialized_ref).unwrap();
3311            assert_eq!(data, *deserialized_ref.inner);
3312        });
3313    }
3314
3315    #[test]
3316    fn test_pod_zero_copy_explicit_ref() {
3317        #[derive(Debug, PartialEq, Eq, proptest_derive::Arbitrary, Clone, Copy)]
3318        #[repr(transparent)]
3319        struct Address([u8; 64]);
3320
3321        pod_wrapper! {
3322            unsafe struct PodAddress(Address);
3323        }
3324
3325        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
3326        #[wincode(internal)]
3327        struct MyStructRef<'a> {
3328            #[wincode(with = "&'a PodAddress")]
3329            address: &'a Address,
3330        }
3331
3332        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
3333        #[wincode(internal)]
3334        struct MyStruct {
3335            #[wincode(with = "PodAddress")]
3336            address: Address,
3337        }
3338
3339        proptest!(proptest_cfg(), |(data in any::<MyStruct>())| {
3340            let serialized = serialize(&data).unwrap();
3341            let deserialized = MyStruct::deserialize(&serialized).unwrap();
3342            assert_eq!(data, deserialized);
3343
3344            let serialized_ref = serialize(&MyStructRef { address: &data.address }).unwrap();
3345            assert_eq!(serialized_ref, serialized);
3346            let deserialized_ref = MyStructRef::deserialize(&serialized_ref).unwrap();
3347            assert_eq!(data.address, *deserialized_ref.address);
3348        });
3349    }
3350
3351    #[test]
3352    fn test_result_basic() {
3353        proptest!(proptest_cfg(), |(value: Result<u64, String>)| {
3354            let wincode_serialized = serialize(&value).unwrap();
3355            let bincode_serialized = bincode::serialize(&value).unwrap();
3356            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3357
3358            let wincode_deserialized: Result<u64, String> = deserialize(&wincode_serialized).unwrap();
3359            let bincode_deserialized: Result<u64, String> = bincode::deserialize(&bincode_serialized).unwrap();
3360            prop_assert_eq!(&value, &wincode_deserialized);
3361            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
3362        });
3363    }
3364
3365    #[test]
3366    fn test_result_bincode_equivalence() {
3367        use serde::{Deserialize, Serialize};
3368
3369        #[derive(
3370            Serialize,
3371            Deserialize,
3372            Debug,
3373            PartialEq,
3374            Clone,
3375            proptest_derive::Arbitrary,
3376            SchemaWrite,
3377            SchemaRead,
3378        )]
3379        #[wincode(internal)]
3380        enum Error {
3381            NotFound,
3382            InvalidInput(String),
3383            Other(u32),
3384        }
3385
3386        proptest!(proptest_cfg(), |(value: Result<Vec<u8>, Error>)| {
3387            let wincode_serialized = serialize(&value).unwrap();
3388            let bincode_serialized = bincode::serialize(&value).unwrap();
3389            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3390
3391            let wincode_deserialized: Result<Vec<u8>, Error> = deserialize(&wincode_serialized).unwrap();
3392            let bincode_deserialized: Result<Vec<u8>, Error> = bincode::deserialize(&bincode_serialized).unwrap();
3393            prop_assert_eq!(&value, &wincode_deserialized);
3394            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
3395        });
3396    }
3397
3398    #[test]
3399    fn test_result_nested() {
3400        proptest!(proptest_cfg(), |(value: Result<Result<u64, String>, u32>)| {
3401            let wincode_serialized = serialize(&value).unwrap();
3402            let bincode_serialized = bincode::serialize(&value).unwrap();
3403            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3404
3405            let wincode_deserialized: Result<Result<u64, String>, u32> = deserialize(&wincode_serialized).unwrap();
3406            let bincode_deserialized: Result<Result<u64, String>, u32> = bincode::deserialize(&bincode_serialized).unwrap();
3407            prop_assert_eq!(&value, &wincode_deserialized);
3408            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
3409        });
3410    }
3411
3412    #[test]
3413    fn test_result_with_complex_types() {
3414        use std::collections::HashMap;
3415
3416        proptest!(proptest_cfg(), |(value: Result<HashMap<String, Vec<u32>>, bool>)| {
3417            let wincode_serialized = serialize(&value).unwrap();
3418            let bincode_serialized = bincode::serialize(&value).unwrap();
3419            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3420
3421            let wincode_deserialized: Result<HashMap<String, Vec<u32>>, bool> = deserialize(&wincode_serialized).unwrap();
3422            let bincode_deserialized: Result<HashMap<String, Vec<u32>>, bool> = bincode::deserialize(&bincode_serialized).unwrap();
3423            prop_assert_eq!(&value, &wincode_deserialized);
3424            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
3425        });
3426    }
3427
3428    #[test]
3429    fn test_result_type_meta_static() {
3430        // Result<u64, u64> should be TypeMeta::Static because both T and E are Static with equal sizes
3431        assert!(matches!(
3432            <Result<u64, u64> as SchemaRead<DefaultConfig>>::TYPE_META,
3433            TypeMeta::Static {
3434                size: 12,
3435                zero_copy: false
3436            }
3437        ));
3438
3439        proptest!(proptest_cfg(), |(value: Result<u64, u64>)| {
3440            let wincode_serialized = serialize(&value).unwrap();
3441            let bincode_serialized = bincode::serialize(&value).unwrap();
3442            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3443
3444            let wincode_deserialized: Result<u64, u64> = deserialize(&wincode_serialized).unwrap();
3445            let bincode_deserialized: Result<u64, u64> = bincode::deserialize(&bincode_serialized).unwrap();
3446            prop_assert_eq!(&value, &wincode_deserialized);
3447            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
3448        });
3449    }
3450
3451    #[test]
3452    fn test_result_type_meta_dynamic() {
3453        // Result<u64, String> should be TypeMeta::Dynamic because String is Dynamic
3454        assert!(matches!(
3455            <Result<u64, String> as SchemaRead<DefaultConfig>>::TYPE_META,
3456            TypeMeta::Dynamic
3457        ));
3458
3459        proptest!(proptest_cfg(), |(value: Result<u64, String>)| {
3460            let wincode_serialized = serialize(&value).unwrap();
3461            let bincode_serialized = bincode::serialize(&value).unwrap();
3462            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3463
3464            let wincode_deserialized: Result<u64, String> = deserialize(&wincode_serialized).unwrap();
3465            let bincode_deserialized: Result<u64, String> = bincode::deserialize(&bincode_serialized).unwrap();
3466            prop_assert_eq!(&value, &wincode_deserialized);
3467            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
3468        });
3469    }
3470
3471    #[test]
3472    fn test_result_type_meta_different_sizes() {
3473        // Result<u64, u32> should be TypeMeta::Dynamic because T and E have different sizes
3474        assert!(matches!(
3475            <Result<u64, u32> as SchemaRead<DefaultConfig>>::TYPE_META,
3476            TypeMeta::Dynamic
3477        ));
3478
3479        proptest!(proptest_cfg(), |(value: Result<u64, u32>)| {
3480            let wincode_serialized = serialize(&value).unwrap();
3481            let bincode_serialized = bincode::serialize(&value).unwrap();
3482            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3483
3484            let wincode_deserialized: Result<u64, u32> = deserialize(&wincode_serialized).unwrap();
3485            let bincode_deserialized: Result<u64, u32> = bincode::deserialize(&bincode_serialized).unwrap();
3486            prop_assert_eq!(&value, &wincode_deserialized);
3487            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
3488        });
3489    }
3490
3491    /// A buffer containing a single instance of type `T`,
3492    /// aligned for `T`.
3493    ///
3494    /// Implements [`Deref`] and [`DerefMut`] for `[u8]` such that it
3495    /// acts like a typical byte buffer, but aligned for `T`.
3496    struct BufAligned {
3497        buf: *mut u8,
3498        layout: Layout,
3499    }
3500
3501    impl Deref for BufAligned {
3502        type Target = [u8];
3503
3504        fn deref(&self) -> &Self::Target {
3505            unsafe { core::slice::from_raw_parts(self.buf as *const u8, self.layout.size()) }
3506        }
3507    }
3508
3509    impl DerefMut for BufAligned {
3510        fn deref_mut(&mut self) -> &mut Self::Target {
3511            unsafe { core::slice::from_raw_parts_mut(self.buf, self.layout.size()) }
3512        }
3513    }
3514
3515    impl Drop for BufAligned {
3516        fn drop(&mut self) {
3517            use alloc::alloc::dealloc;
3518            unsafe { dealloc(self.buf, self.layout) }
3519        }
3520    }
3521
3522    /// Serialize a single instance of type `T` into a buffer aligned for `T`.
3523    fn serialize_aligned<T>(src: &T) -> WriteResult<BufAligned>
3524    where
3525        T: SchemaWrite<DefaultConfig, Src = T>,
3526    {
3527        use alloc::alloc::alloc;
3528        let size = T::size_of(src)?;
3529        let layout = Layout::from_size_align(size, align_of::<T>()).unwrap();
3530        let mem = unsafe { alloc(layout) };
3531        if mem.is_null() {
3532            return Err(crate::WriteError::Custom("could not allocate"));
3533        }
3534        let mut buf = BufAligned { buf: mem, layout };
3535        crate::serialize_into(buf.deref_mut(), src)?;
3536        Ok(buf)
3537    }
3538
3539    #[test]
3540    fn test_zero_copy_mut_roundrip() {
3541        proptest!(proptest_cfg(), |(data: StructZeroCopy, data_rand: StructZeroCopy)| {
3542            let mut serialized = serialize_aligned(&data).unwrap();
3543            let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
3544            prop_assert_eq!(deserialized, data);
3545
3546
3547            // Mutate the serialized data in place
3548            {
3549                let ref_mut = StructZeroCopy::from_bytes_mut(&mut serialized).unwrap();
3550                *ref_mut = data_rand;
3551            }
3552            // Deserialize again on the same serialized data to
3553            // verify the changes were persisted
3554            let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
3555            prop_assert_eq!(deserialized, data_rand);
3556        });
3557    }
3558
3559    #[test]
3560    fn test_deserialize_mut_roundrip() {
3561        proptest!(proptest_cfg(), |(data: StructZeroCopy, data_rand: StructZeroCopy)| {
3562            let mut serialized = serialize_aligned(&data).unwrap();
3563            let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
3564            prop_assert_eq!(deserialized, data);
3565
3566
3567            // Mutate the serialized data in place
3568            {
3569                let ref_mut: &mut StructZeroCopy = deserialize_mut(&mut serialized).unwrap();
3570                *ref_mut = data_rand;
3571            }
3572            // Deserialize again on the same serialized data to
3573            // verify the changes were persisted
3574            let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
3575            prop_assert_eq!(deserialized, data_rand);
3576        });
3577    }
3578
3579    #[test]
3580    fn test_zero_copy_deserialize_ref() {
3581        proptest!(proptest_cfg(), |(data: StructZeroCopy)| {
3582            let serialized = serialize_aligned(&data).unwrap();
3583            let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
3584            prop_assert_eq!(deserialized, data);
3585
3586            let ref_data = StructZeroCopy::from_bytes(&serialized).unwrap();
3587            prop_assert_eq!(ref_data, &data);
3588        });
3589    }
3590
3591    #[test]
3592    fn test_custom_preallocation_size_limit() {
3593        let c = Configuration::default().with_preallocation_size_limit::<64>();
3594        proptest!(proptest_cfg(), |(value in proptest::collection::vec(any::<u8>(), 0..=128))| {
3595            let wincode_serialized = crate::serialize(&value).unwrap();
3596            let wincode_deserialized: Result<Vec<u8>, _> = config::deserialize(&wincode_serialized, c);
3597            if value.len() <= 64 {
3598                prop_assert_eq!(value, wincode_deserialized.unwrap());
3599            } else {
3600                prop_assert!(wincode_deserialized.is_err());
3601            }
3602        });
3603    }
3604
3605    #[test]
3606    fn test_custom_length_encoding() {
3607        let c = Configuration::default().with_length_encoding::<FixIntLen<u32>>();
3608
3609        proptest!(proptest_cfg(), |(value: Vec<u8>)| {
3610            let wincode_serialized = config::serialize(&value, c).unwrap();
3611            let wincode_deserialized: Vec<u8> = config::deserialize(&wincode_serialized, c).unwrap();
3612            let len = value.len();
3613            prop_assert_eq!(len, u32::from_le_bytes(wincode_serialized[0..4].try_into().unwrap()) as usize);
3614            prop_assert_eq!(value, wincode_deserialized);
3615        });
3616    }
3617
3618    #[test]
3619    fn test_duration() {
3620        use core::time::Duration;
3621
3622        proptest!(proptest_cfg(), |(val: Duration)| {
3623            let bincode_serialized = bincode::serialize(&val).unwrap();
3624            let schema_serialized = serialize(&val).unwrap();
3625            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3626
3627            let bincode_deserialized: Duration = bincode::deserialize(&bincode_serialized).unwrap();
3628            let schema_deserialized: Duration = deserialize(&schema_serialized).unwrap();
3629            prop_assert_eq!(val, bincode_deserialized);
3630            prop_assert_eq!(val, schema_deserialized);
3631        });
3632    }
3633
3634    #[test]
3635    fn test_ipv4_addr() {
3636        proptest!(proptest_cfg(), |(addr: Ipv4Addr)| {
3637            let bincode_serialized = bincode::serialize(&addr).unwrap();
3638            let schema_serialized = serialize(&addr).unwrap();
3639            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3640
3641            let bincode_deserialized: Ipv4Addr = bincode::deserialize(&bincode_serialized).unwrap();
3642            let schema_deserialized: Ipv4Addr = deserialize(&schema_serialized).unwrap();
3643            prop_assert_eq!(addr, bincode_deserialized);
3644            prop_assert_eq!(addr, schema_deserialized);
3645        });
3646    }
3647
3648    #[test]
3649    fn test_ipv6_addr() {
3650        proptest!(proptest_cfg(), |(addr: Ipv6Addr)| {
3651            let bincode_serialized = bincode::serialize(&addr).unwrap();
3652            let schema_serialized = serialize(&addr).unwrap();
3653            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3654
3655            let bincode_deserialized: Ipv6Addr = bincode::deserialize(&bincode_serialized).unwrap();
3656            let schema_deserialized: Ipv6Addr = deserialize(&schema_serialized).unwrap();
3657            prop_assert_eq!(addr, bincode_deserialized);
3658            prop_assert_eq!(addr, schema_deserialized);
3659        });
3660    }
3661
3662    #[test]
3663    fn test_ip_addr() {
3664        proptest!(proptest_cfg(), |(addr: IpAddr)| {
3665            let bincode_serialized = bincode::serialize(&addr).unwrap();
3666            let schema_serialized = serialize(&addr).unwrap();
3667            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3668
3669            let bincode_deserialized: IpAddr = bincode::deserialize(&bincode_serialized).unwrap();
3670            let schema_deserialized: IpAddr = deserialize(&schema_serialized).unwrap();
3671            prop_assert_eq!(addr, bincode_deserialized);
3672            prop_assert_eq!(addr, schema_deserialized);
3673        });
3674    }
3675
3676    #[test]
3677    fn test_socket_addr_v4() {
3678        proptest!(proptest_cfg(), |(addr: SocketAddrV4)| {
3679            let bincode_serialized = bincode::serialize(&addr).unwrap();
3680            let schema_serialized = serialize(&addr).unwrap();
3681            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3682
3683            let bincode_deserialized: SocketAddrV4 = bincode::deserialize(&bincode_serialized).unwrap();
3684            let schema_deserialized: SocketAddrV4 = deserialize(&schema_serialized).unwrap();
3685            prop_assert_eq!(addr, bincode_deserialized);
3686            prop_assert_eq!(addr, schema_deserialized);
3687        });
3688    }
3689
3690    #[test]
3691    fn test_socket_addr_v6() {
3692        // serde drops flowinfo and scope_id for SocketAddrV6, so we only verify
3693        // byte compatibility and that both impls deserialize identically.
3694        proptest!(proptest_cfg(), |(addr: SocketAddrV6)| {
3695            let bincode_serialized = bincode::serialize(&addr).unwrap();
3696            let schema_serialized = serialize(&addr).unwrap();
3697            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3698
3699            let bincode_deserialized: SocketAddrV6 = bincode::deserialize(&bincode_serialized).unwrap();
3700            let schema_deserialized: SocketAddrV6 = deserialize(&schema_serialized).unwrap();
3701            prop_assert_eq!(bincode_deserialized, schema_deserialized);
3702        });
3703    }
3704
3705    #[test]
3706    fn test_socket_addr() {
3707        // serde drops flowinfo and scope_id for SocketAddrV6 variants, so we only
3708        // verify byte compatibility and that both impls deserialize identically.
3709        proptest!(proptest_cfg(), |(addr: SocketAddr)| {
3710            let bincode_serialized = bincode::serialize(&addr).unwrap();
3711            let schema_serialized = serialize(&addr).unwrap();
3712            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3713
3714            let bincode_deserialized: SocketAddr = bincode::deserialize(&bincode_serialized).unwrap();
3715            let schema_deserialized: SocketAddr = deserialize(&schema_serialized).unwrap();
3716            prop_assert_eq!(bincode_deserialized, schema_deserialized);
3717        });
3718    }
3719
3720    #[test]
3721    #[cfg(feature = "std")]
3722    fn test_system_time() {
3723        use std::time::{Duration, SystemTime, UNIX_EPOCH};
3724
3725        const MAX_SECS: u64 = i64::MAX as u64 - 1;
3726
3727        proptest!(proptest_cfg(), |(secs in 0u64..=MAX_SECS, nanos in 0u32..1_000_000_000u32)| {
3728            let time = UNIX_EPOCH + Duration::new(secs, nanos);
3729            let bincode_serialized = bincode::serialize(&time).unwrap();
3730            let schema_serialized = serialize(&time).unwrap();
3731            prop_assert_eq!(&bincode_serialized, &schema_serialized);
3732
3733            let bincode_deserialized: SystemTime = bincode::deserialize(&bincode_serialized).unwrap();
3734            let schema_deserialized: SystemTime = deserialize(&schema_serialized).unwrap();
3735            prop_assert_eq!(time, bincode_deserialized);
3736            prop_assert_eq!(time, schema_deserialized);
3737        });
3738    }
3739
3740    #[test]
3741    #[cfg(feature = "std")]
3742    fn test_system_time_before_epoch_errors() {
3743        use std::time::{Duration, UNIX_EPOCH};
3744
3745        let before_epoch = UNIX_EPOCH.checked_sub(Duration::from_secs(1)).unwrap();
3746        assert!(serialize(&before_epoch).is_err());
3747    }
3748
3749    #[test]
3750    fn test_deserialize_exact_accepts_exact_input() {
3751        let bytes = serialize(&123u64).unwrap();
3752        let value: u64 = deserialize_exact(&bytes).unwrap();
3753        assert_eq!(value, 123);
3754    }
3755
3756    #[test]
3757    fn test_deserialize_exact_rejects_trailing_bytes() {
3758        let mut bytes = serialize(&123u64).unwrap();
3759        bytes.push(0xAA);
3760        let err = deserialize_exact::<u64>(&bytes).unwrap_err();
3761        assert!(matches!(err, error::ReadError::TrailingBytes));
3762    }
3763
3764    #[test]
3765    fn test_config_deserialize_exact_rejects_trailing_bytes() {
3766        let config = Configuration::default();
3767        let mut bytes = config::serialize(&123u64, config).unwrap();
3768        bytes.push(0xAA);
3769        let err = config::deserialize_exact::<u64, _>(&bytes, config).unwrap_err();
3770        assert!(matches!(err, error::ReadError::TrailingBytes));
3771    }
3772
3773    #[test]
3774    #[cfg(feature = "std")]
3775    fn test_system_time_overflow_errors() {
3776        use {crate::serialize_into, std::time::SystemTime};
3777
3778        let mut bytes = Vec::with_capacity(size_of::<u64>() + size_of::<u32>());
3779        serialize_into(&mut bytes, &u64::MAX).unwrap();
3780        serialize_into(&mut bytes, &0u32).unwrap();
3781
3782        let result: ReadResult<SystemTime> = deserialize(&bytes);
3783        assert!(result.is_err());
3784    }
3785
3786    #[test]
3787    fn test_nonzero_types() {
3788        proptest!(proptest_cfg(), |(
3789            nz_u8: NonZeroU8,
3790            nz_u16: NonZeroU16,
3791            nz_u32: NonZeroU32,
3792            nz_u64: NonZeroU64,
3793            nz_u128: NonZeroU128,
3794            nz_usize: NonZeroUsize,
3795            nz_i8: NonZeroI8,
3796            nz_i16: NonZeroI16,
3797            nz_i32: NonZeroI32,
3798            nz_i64: NonZeroI64,
3799            nz_i128: NonZeroI128,
3800            nz_isize: NonZeroIsize,
3801        )| {
3802            // Unsigned
3803            let ser = serialize(&nz_u8).unwrap();
3804            let de: NonZeroU8 = deserialize(&ser).unwrap();
3805            prop_assert_eq!(nz_u8, de);
3806
3807            let ser = serialize(&nz_u16).unwrap();
3808            let de: NonZeroU16 = deserialize(&ser).unwrap();
3809            prop_assert_eq!(nz_u16, de);
3810
3811            let ser = serialize(&nz_u32).unwrap();
3812            let de: NonZeroU32 = deserialize(&ser).unwrap();
3813            prop_assert_eq!(nz_u32, de);
3814
3815            let ser = serialize(&nz_u64).unwrap();
3816            let de: NonZeroU64 = deserialize(&ser).unwrap();
3817            prop_assert_eq!(nz_u64, de);
3818
3819            let ser = serialize(&nz_u128).unwrap();
3820            let de: NonZeroU128 = deserialize(&ser).unwrap();
3821            prop_assert_eq!(nz_u128, de);
3822
3823            let ser = serialize(&nz_usize).unwrap();
3824            let de: NonZeroUsize = deserialize(&ser).unwrap();
3825            prop_assert_eq!(nz_usize, de);
3826
3827            // Signed
3828            let ser = serialize(&nz_i8).unwrap();
3829            let de: NonZeroI8 = deserialize(&ser).unwrap();
3830            prop_assert_eq!(nz_i8, de);
3831
3832            let ser = serialize(&nz_i16).unwrap();
3833            let de: NonZeroI16 = deserialize(&ser).unwrap();
3834            prop_assert_eq!(nz_i16, de);
3835
3836            let ser = serialize(&nz_i32).unwrap();
3837            let de: NonZeroI32 = deserialize(&ser).unwrap();
3838            prop_assert_eq!(nz_i32, de);
3839
3840            let ser = serialize(&nz_i64).unwrap();
3841            let de: NonZeroI64 = deserialize(&ser).unwrap();
3842            prop_assert_eq!(nz_i64, de);
3843
3844            let ser = serialize(&nz_i128).unwrap();
3845            let de: NonZeroI128 = deserialize(&ser).unwrap();
3846            prop_assert_eq!(nz_i128, de);
3847
3848            let ser = serialize(&nz_isize).unwrap();
3849            let de: NonZeroIsize = deserialize(&ser).unwrap();
3850            prop_assert_eq!(nz_isize, de);
3851        });
3852    }
3853
3854    #[test]
3855    fn test_nonzero_invalid_zero_value() {
3856        // Test that deserializing a zero value fails
3857        let zero_bytes = serialize(&0u32).unwrap();
3858        let result: ReadResult<NonZeroU32> = deserialize(&zero_bytes);
3859        assert!(
3860            result.is_err(),
3861            "Deserializing zero should fail for NonZeroU32"
3862        );
3863
3864        let zero_bytes = serialize(&0u64).unwrap();
3865        let result: ReadResult<NonZeroU64> = deserialize(&zero_bytes);
3866        assert!(
3867            result.is_err(),
3868            "Deserializing zero should fail for NonZeroU64"
3869        );
3870    }
3871
3872    #[test]
3873    fn test_bound_included_u64() {
3874        proptest!(proptest_cfg(), |(value in any::<u64>())| {
3875            let bound = Bound::Included(value);
3876            let serialized = serialize(&bound).unwrap();
3877            let deserialized: Bound<u64> = deserialize(&serialized).unwrap();
3878            prop_assert_eq!(&bound, &deserialized);
3879        });
3880    }
3881
3882    #[test]
3883    fn test_bound_excluded_u64() {
3884        proptest!(proptest_cfg(), |(value in any::<u64>())| {
3885            let bound = Bound::Excluded(value);
3886            let serialized = serialize(&bound).unwrap();
3887            let deserialized: Bound<u64> = deserialize(&serialized).unwrap();
3888            prop_assert_eq!(&bound, &deserialized);
3889        });
3890    }
3891
3892    #[test]
3893    fn test_bound_included_string() {
3894        proptest!(proptest_cfg(), |(value in any::<String>())| {
3895            let bound = Bound::Included(value);
3896            let serialized = serialize(&bound).unwrap();
3897            let deserialized: Bound<String> = deserialize(&serialized).unwrap();
3898            prop_assert_eq!(&bound, &deserialized);
3899        });
3900    }
3901
3902    #[test]
3903    fn test_bound_excluded_string() {
3904        proptest!(proptest_cfg(), |(value in any::<String>())| {
3905            let bound = Bound::Excluded(value);
3906            let serialized = serialize(&bound).unwrap();
3907            let deserialized: Bound<String> = deserialize(&serialized).unwrap();
3908            prop_assert_eq!(&bound, &deserialized);
3909        });
3910    }
3911
3912    #[test]
3913    fn test_bound_included_bincode_equivalence() {
3914        proptest!(proptest_cfg(), |(value in any::<u64>())| {
3915            let bound = Bound::Included(value);
3916            let wincode_serialized = serialize(&bound).unwrap();
3917            let bincode_serialized = bincode::serialize(&bound).unwrap();
3918            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3919
3920            let wincode_deserialized: Bound<u64> = deserialize(&wincode_serialized).unwrap();
3921            let bincode_deserialized: Bound<u64> = bincode::deserialize(&bincode_serialized).unwrap();
3922            prop_assert_eq!(&bound, &wincode_deserialized);
3923            prop_assert_eq!(&wincode_deserialized, &bincode_deserialized);
3924        });
3925    }
3926
3927    #[test]
3928    fn test_bound_excluded_bincode_equivalence() {
3929        proptest!(proptest_cfg(), |(value in any::<u64>())| {
3930            let bound = Bound::Excluded(value);
3931            let wincode_serialized = serialize(&bound).unwrap();
3932            let bincode_serialized = bincode::serialize(&bound).unwrap();
3933            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3934
3935            let wincode_deserialized: Bound<u64> = deserialize(&wincode_serialized).unwrap();
3936            let bincode_deserialized: Bound<u64> = bincode::deserialize(&bincode_serialized).unwrap();
3937            prop_assert_eq!(&bound, &wincode_deserialized);
3938            prop_assert_eq!(&wincode_deserialized, &bincode_deserialized);
3939        });
3940    }
3941
3942    #[test]
3943    fn test_range_u64() {
3944        proptest!(proptest_cfg(), |(start in any::<u64>(), end in any::<u64>())| {
3945            let range = Range { start, end };
3946            let serialized = serialize(&range).unwrap();
3947            let deserialized: Range<u64> = deserialize(&serialized).unwrap();
3948            prop_assert_eq!(range.start, deserialized.start);
3949            prop_assert_eq!(range.end, deserialized.end);
3950        });
3951    }
3952
3953    #[test]
3954    fn test_range_string() {
3955        proptest!(proptest_cfg(), |(start in any::<String>(), end in any::<String>())| {
3956            let range = Range { start, end };
3957            let serialized = serialize(&range).unwrap();
3958            let deserialized: Range<String> = deserialize(&serialized).unwrap();
3959            prop_assert_eq!(&range.start, &deserialized.start);
3960            prop_assert_eq!(&range.end, &deserialized.end);
3961        });
3962    }
3963
3964    #[test]
3965    fn test_range_bincode_equivalence() {
3966        proptest!(proptest_cfg(), |(start in any::<u64>(), end in any::<u64>())| {
3967            let range = Range { start, end };
3968            let wincode_serialized = serialize(&range).unwrap();
3969            let bincode_serialized = bincode::serialize(&range).unwrap();
3970            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
3971
3972            let wincode_deserialized: Range<u64> = deserialize(&wincode_serialized).unwrap(); //happens here
3973            let bincode_deserialized: Range<u64> = bincode::deserialize(&bincode_serialized).unwrap();
3974            prop_assert_eq!(range.start, wincode_deserialized.start);
3975            prop_assert_eq!(range.end, wincode_deserialized.end);
3976            prop_assert_eq!(wincode_deserialized.start, bincode_deserialized.start);
3977            prop_assert_eq!(wincode_deserialized.end, bincode_deserialized.end);
3978        });
3979    }
3980
3981    #[test]
3982    fn test_range_inclusive_u64() {
3983        proptest!(proptest_cfg(), |(start in any::<u64>(), end in any::<u64>())| {
3984            let range = RangeInclusive::new(start, end);
3985            let serialized = serialize(&range).unwrap();
3986            let deserialized: RangeInclusive<u64> = deserialize(&serialized).unwrap();
3987            prop_assert_eq!(range.start(), deserialized.start());
3988            prop_assert_eq!(range.end(), deserialized.end());
3989        });
3990    }
3991
3992    #[test]
3993    fn test_range_inclusive_string() {
3994        proptest!(proptest_cfg(), |(start in any::<String>(), end in any::<String>())| {
3995            let range = RangeInclusive::new(start, end );
3996            let serialized = serialize(&range).unwrap();
3997            let deserialized: RangeInclusive<String> = deserialize(&serialized).unwrap();
3998            prop_assert_eq!(&range.start(), &deserialized.start());
3999            prop_assert_eq!(&range.end(), &deserialized.end());
4000        });
4001    }
4002
4003    #[test]
4004    fn test_range_inclusive_bincode_equivalence() {
4005        proptest!(proptest_cfg(), |(start in any::<u64>(), end in any::<u64>())| {
4006            let range = RangeInclusive::new(start, end );
4007            let wincode_serialized = serialize(&range).unwrap();
4008            let bincode_serialized = bincode::serialize(&range).unwrap();
4009            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
4010
4011            let wincode_deserialized: RangeInclusive<u64> = deserialize(&wincode_serialized).unwrap();
4012            let bincode_deserialized: RangeInclusive<u64> = bincode::deserialize(&bincode_serialized).unwrap();
4013            prop_assert_eq!(range.start(), wincode_deserialized.start());
4014            prop_assert_eq!(range.end(), wincode_deserialized.end());
4015            prop_assert_eq!(wincode_deserialized.start(), bincode_deserialized.start());
4016            prop_assert_eq!(wincode_deserialized.end(), bincode_deserialized.end());
4017        });
4018    }
4019
4020    #[test]
4021    fn test_range_vec_u64() {
4022        proptest!(proptest_cfg(), |(ranges: Vec<Range<u64>>)| {
4023            let serialized = serialize(&ranges).unwrap();
4024            let bincode_serialized = bincode::serialize(&ranges).unwrap();
4025            prop_assert_eq!(&serialized, &bincode_serialized);
4026
4027            let deserialized: Vec<Range<u64>> = deserialize(&serialized).unwrap();
4028            let bincode_deserialized: Vec<Range<u64>> = bincode::deserialize(&bincode_serialized).unwrap();
4029            prop_assert_eq!(deserialized, bincode_deserialized);
4030        });
4031    }
4032
4033    #[test]
4034    fn test_range_inclusive_vec_u64() {
4035        proptest!(proptest_cfg(), |(ranges: Vec<RangeInclusive<u64>>)| {
4036            let serialized = serialize(&ranges).unwrap();
4037            let bincode_serialized = bincode::serialize(&ranges).unwrap();
4038            prop_assert_eq!(&serialized, &bincode_serialized);
4039
4040            let deserialized: Vec<RangeInclusive<u64>> = deserialize(&serialized).unwrap();
4041            let bincode_deserialized: Vec<RangeInclusive<u64>> = bincode::deserialize(&bincode_serialized).unwrap();
4042            prop_assert_eq!(deserialized, bincode_deserialized);
4043        });
4044    }
4045
4046    #[test]
4047    fn test_bound_vec_u64() {
4048        proptest!(proptest_cfg(), |(bounds: Vec<Bound<u64>>)| {
4049            let serialized = serialize(&bounds).unwrap();
4050            let bincode_serialized = bincode::serialize(&bounds).unwrap();
4051            prop_assert_eq!(&serialized, &bincode_serialized);
4052
4053            let deserialized: Vec<Bound<u64>> = deserialize(&serialized).unwrap();
4054            let bincode_deserialized: Vec<Bound<u64>> = bincode::deserialize(&bincode_serialized).unwrap();
4055            prop_assert_eq!(deserialized, bincode_deserialized);
4056        });
4057    }
4058
4059    #[test]
4060    fn test_byte_order_configuration() {
4061        let c = Configuration::default().with_big_endian();
4062        let bincode_c = bincode::DefaultOptions::new()
4063            .with_big_endian()
4064            .with_fixint_encoding();
4065
4066        proptest!(proptest_cfg(), |(value: Vec<u64>)| {
4067            let bincode_serialized = bincode_c.serialize(&value).unwrap();
4068            let serialized = config::serialize(&value, c).unwrap();
4069            prop_assert_eq!(&bincode_serialized, &serialized);
4070
4071            let deserialized: Vec<u64> = config::deserialize(&serialized, c).unwrap();
4072            let len = value.len();
4073            prop_assert_eq!(len, u64::from_be_bytes(serialized[0..8].try_into().unwrap()) as usize);
4074
4075            if !value.is_empty() {
4076                for (i, chunk) in serialized[8..].chunks(8).enumerate() {
4077                    let val = u64::from_be_bytes(chunk.try_into().unwrap());
4078                    prop_assert_eq!(val, value[i]);
4079                }
4080            }
4081
4082            prop_assert_eq!(value, deserialized);
4083        });
4084    }
4085
4086    #[test]
4087    fn test_duration_nanos_normalization() {
4088        use core::time::Duration;
4089
4090        proptest!(proptest_cfg(), |(secs in 0u64..u64::MAX/2, nanos in 1_000_000_000u32..=u32::MAX)| {
4091            let mut bytes: Vec<u8> = Vec::with_capacity(size_of::<u64>() + size_of::<u32>());
4092            crate::serialize_into(&mut bytes, &secs).unwrap();
4093            crate::serialize_into(&mut bytes, &nanos).unwrap();
4094
4095            let result: Duration = deserialize(&bytes).unwrap();
4096            let expected = Duration::new(secs, nanos);
4097            prop_assert_eq!(result, expected);
4098        });
4099    }
4100
4101    #[test]
4102    fn test_custom_length_encoding_and_byte_order() {
4103        let c = Configuration::default()
4104            .with_length_encoding::<FixIntLen<u32>>()
4105            .with_big_endian();
4106
4107        proptest!(proptest_cfg(), |(value: Vec<u8>)| {
4108            let serialized = config::serialize(&value, c).unwrap();
4109            let deserialized: Vec<u8> = config::deserialize(&serialized, c).unwrap();
4110            let len = value.len();
4111            prop_assert_eq!(len, u32::from_be_bytes(serialized[0..4].try_into().unwrap()) as usize);
4112            prop_assert_eq!(value, deserialized);
4113        });
4114    }
4115
4116    #[test]
4117    fn test_custom_primitive_length_encoding() {
4118        let c = Configuration::default().with_length_encoding::<u32>();
4119
4120        proptest!(proptest_cfg(), |(value: Vec<u8>)| {
4121            let serialized = config::serialize(&value, c).unwrap();
4122            let deserialized: Vec<u8> = config::deserialize(&serialized, c).unwrap();
4123            let len = value.len();
4124            prop_assert_eq!(len, u32::from_le_bytes(serialized[0..4].try_into().unwrap()) as usize);
4125            prop_assert_eq!(value, deserialized);
4126        });
4127    }
4128
4129    #[test]
4130    fn test_duration_overflow() {
4131        use core::time::Duration;
4132
4133        let mut bytes = Vec::with_capacity(size_of::<u64>() + size_of::<u32>());
4134        crate::serialize_into(&mut bytes, &u64::MAX).unwrap();
4135        crate::serialize_into(&mut bytes, &1_000_000_000u32).unwrap();
4136
4137        let result: error::ReadResult<Duration> = deserialize(&bytes);
4138        assert!(result.is_err());
4139    }
4140
4141    #[test]
4142    fn test_all_integers_with_custom_byte_order() {
4143        let c = Configuration::default().with_big_endian();
4144        let bincode_c = bincode::DefaultOptions::new()
4145            .with_big_endian()
4146            .with_fixint_encoding();
4147
4148        proptest!(proptest_cfg(), |(value: (u16, u32, u64, u128, i16, i32, i64, i128, usize, isize))| {
4149            let bincode_serialized = bincode_c.serialize(&value).unwrap();
4150            let serialized = config::serialize(&value, c).unwrap();
4151            prop_assert_eq!(&bincode_serialized, &serialized);
4152            let deserialized: (u16, u32, u64, u128, i16, i32, i64, i128, usize, isize) = config::deserialize(&serialized, c).unwrap();
4153            prop_assert_eq!(value, deserialized);
4154        });
4155    }
4156
4157    #[test]
4158    fn test_all_integers_with_varint() {
4159        let c = Configuration::default().with_varint_encoding();
4160        let bincode_c = bincode::DefaultOptions::new().with_varint_encoding();
4161
4162        proptest!(proptest_cfg(), |(value: (u16, u32, u64, u128, i16, i32, i64, i128, usize, isize))| {
4163            let bincode_serialized = bincode_c.serialize(&value).unwrap();
4164            let serialized = config::serialize(&value, c).unwrap();
4165            prop_assert_eq!(&bincode_serialized, &serialized);
4166            prop_assert_eq!(bincode_c.serialized_size(&value).unwrap(), config::serialized_size(&value, c).unwrap());
4167
4168            let deserialized: (u16, u32, u64, u128, i16, i32, i64, i128, usize, isize) = config::deserialize(&serialized, c).unwrap();
4169            prop_assert_eq!(value, deserialized);
4170        });
4171    }
4172
4173    #[test]
4174    fn test_all_integers_with_varint_big_endian() {
4175        let c = Configuration::default()
4176            .with_varint_encoding()
4177            .with_big_endian();
4178        let bincode_c = bincode::DefaultOptions::new()
4179            .with_varint_encoding()
4180            .with_big_endian();
4181
4182        proptest!(proptest_cfg(), |(value: (u16, u32, u64, u128, i16, i32, i64, i128, usize, isize))| {
4183            let bincode_serialized = bincode_c.serialize(&value).unwrap();
4184            let serialized = config::serialize(&value, c).unwrap();
4185            prop_assert_eq!(&bincode_serialized, &serialized);
4186            prop_assert_eq!(bincode_c.serialized_size(&value).unwrap(), config::serialized_size(&value, c).unwrap());
4187
4188            let deserialized: (u16, u32, u64, u128, i16, i32, i64, i128, usize, isize) = config::deserialize(&serialized, c).unwrap();
4189            prop_assert_eq!(value, deserialized);
4190        });
4191    }
4192
4193    #[test]
4194    fn test_varint_boundaries() {
4195        let c = Configuration::default().with_varint_encoding();
4196        let bincode_c = bincode::DefaultOptions::new().with_varint_encoding();
4197
4198        fn assert_varint_roundtrip<T, C, O>(val: T, c: C, bincode_c: O)
4199        where
4200            C: Config + Copy,
4201            O: Options + Copy,
4202            T: serde::Serialize
4203                + for<'de> Deserialize<'de>
4204                + PartialEq
4205                + core::fmt::Debug
4206                + SchemaWrite<C, Src = T>
4207                + for<'de> SchemaRead<'de, C, Dst = T>,
4208        {
4209            let bincode_serialized = bincode_c.serialize(&val).unwrap();
4210            let serialized = config::serialize(&val, c).unwrap();
4211            assert_eq!(bincode_serialized, serialized);
4212            assert_eq!(
4213                bincode_c.serialized_size(&val).unwrap(),
4214                config::serialized_size(&val, c).unwrap()
4215            );
4216            let deserialized: T = config::deserialize(&serialized, c).unwrap();
4217            assert_eq!(val, deserialized);
4218        }
4219
4220        for val in [0u16, 1, 250, 251, 252, u16::MAX] {
4221            assert_varint_roundtrip(val, c, bincode_c);
4222        }
4223
4224        for val in [
4225            0u32,
4226            1,
4227            250,
4228            251,
4229            252,
4230            u16::MAX as u32,
4231            u16::MAX as u32 + 1,
4232            u32::MAX,
4233        ] {
4234            assert_varint_roundtrip(val, c, bincode_c);
4235        }
4236
4237        for val in [
4238            0u64,
4239            1,
4240            250,
4241            251,
4242            252,
4243            u16::MAX as u64,
4244            u16::MAX as u64 + 1,
4245            u32::MAX as u64,
4246            u32::MAX as u64 + 1,
4247            u64::MAX,
4248        ] {
4249            assert_varint_roundtrip(val, c, bincode_c);
4250        }
4251
4252        for val in [
4253            0u128,
4254            1,
4255            250,
4256            251,
4257            252,
4258            u16::MAX as u128,
4259            u16::MAX as u128 + 1,
4260            u32::MAX as u128,
4261            u32::MAX as u128 + 1,
4262            u64::MAX as u128,
4263            u64::MAX as u128 + 1,
4264            u128::MAX,
4265        ] {
4266            assert_varint_roundtrip(val, c, bincode_c);
4267        }
4268
4269        for val in [0i16, 1, -1, 2, -2, i16::MIN, i16::MAX] {
4270            assert_varint_roundtrip(val, c, bincode_c);
4271        }
4272
4273        for val in [0i32, 1, -1, 2, -2, i32::MIN, i32::MAX] {
4274            assert_varint_roundtrip(val, c, bincode_c);
4275        }
4276
4277        for val in [0i64, 1, -1, 2, -2, i64::MIN, i64::MAX] {
4278            assert_varint_roundtrip(val, c, bincode_c);
4279        }
4280
4281        for val in [0i128, 1, -1, 2, -2, i128::MIN, i128::MAX] {
4282            assert_varint_roundtrip(val, c, bincode_c);
4283        }
4284    }
4285
4286    #[test]
4287    fn test_floats_with_custom_byte_order() {
4288        let c = Configuration::default().with_big_endian();
4289        let bincode_c = bincode::DefaultOptions::new()
4290            .with_big_endian()
4291            .with_fixint_encoding();
4292
4293        proptest!(proptest_cfg(), |(value: (f32, f64))| {
4294            let bincode_serialized = bincode_c.serialize(&value).unwrap();
4295            let serialized = config::serialize(&value, c).unwrap();
4296            prop_assert_eq!(&bincode_serialized, &serialized);
4297            let deserialized: (f32, f64) = config::deserialize(&serialized, c).unwrap();
4298            prop_assert_eq!(value, deserialized);
4299        });
4300    }
4301
4302    #[test]
4303    fn test_generic_struct() {
4304        #[derive(
4305            SchemaWrite,
4306            SchemaRead,
4307            serde::Serialize,
4308            serde::Deserialize,
4309            Debug,
4310            PartialEq,
4311            Eq,
4312            proptest_derive::Arbitrary,
4313        )]
4314        #[wincode(internal)]
4315        struct GenT<T> {
4316            inner: T,
4317        }
4318
4319        assert_eq!(
4320            <GenT<u64> as SchemaWrite<DefaultConfig>>::TYPE_META,
4321            TypeMeta::Static {
4322                size: 8,
4323                zero_copy: false
4324            }
4325        );
4326
4327        assert_eq!(
4328            <GenT<String> as SchemaWrite<DefaultConfig>>::TYPE_META,
4329            TypeMeta::Dynamic,
4330        );
4331
4332        proptest!(proptest_cfg(), |(value: GenT<u64>)| {
4333            let serialized = serialize(&value).unwrap();
4334            let bincode_serialized = bincode::serialize(&value).unwrap();
4335            prop_assert_eq!(&serialized, &bincode_serialized);
4336            let deserialized: GenT<u64> = deserialize(&serialized).unwrap();
4337            let bincode_deserialized: GenT<u64> = bincode::deserialize(&bincode_serialized).unwrap();
4338            prop_assert_eq!(&deserialized, &bincode_deserialized);
4339            prop_assert_eq!(value, deserialized);
4340        });
4341    }
4342
4343    #[test]
4344    fn test_generic_struct_two_params() {
4345        #[derive(
4346            SchemaWrite,
4347            SchemaRead,
4348            serde::Serialize,
4349            serde::Deserialize,
4350            Debug,
4351            PartialEq,
4352            Eq,
4353            proptest_derive::Arbitrary,
4354        )]
4355        #[wincode(internal)]
4356        struct GenT<T, U> {
4357            t: T,
4358            u: U,
4359        }
4360
4361        assert_eq!(
4362            <GenT<u64, u64> as SchemaWrite<DefaultConfig>>::TYPE_META,
4363            TypeMeta::Static {
4364                size: 16,
4365                zero_copy: false
4366            }
4367        );
4368
4369        assert_eq!(
4370            <GenT<String, u64> as SchemaWrite<DefaultConfig>>::TYPE_META,
4371            TypeMeta::Dynamic,
4372        );
4373
4374        proptest!(proptest_cfg(), |(value: GenT<u64, u64>)| {
4375            let serialized = serialize(&value).unwrap();
4376            let bincode_serialized = bincode::serialize(&value).unwrap();
4377            prop_assert_eq!(&serialized, &bincode_serialized);
4378            let deserialized: GenT<u64, u64> = deserialize(&serialized).unwrap();
4379            let bincode_deserialized: GenT<u64, u64> = bincode::deserialize(&bincode_serialized).unwrap();
4380            prop_assert_eq!(&deserialized, &bincode_deserialized);
4381            prop_assert_eq!(value, deserialized);
4382        });
4383    }
4384
4385    #[test]
4386    fn test_generic_struct_repr_transparent() {
4387        #[derive(
4388            SchemaWrite,
4389            SchemaRead,
4390            serde::Serialize,
4391            serde::Deserialize,
4392            Debug,
4393            PartialEq,
4394            Eq,
4395            proptest_derive::Arbitrary,
4396        )]
4397        #[wincode(internal)]
4398        #[repr(transparent)]
4399        struct GenT<T> {
4400            inner: T,
4401        }
4402
4403        assert_eq!(
4404            <GenT<u64> as SchemaWrite<DefaultConfig>>::TYPE_META,
4405            TypeMeta::Static {
4406                size: 8,
4407                zero_copy: true
4408            }
4409        );
4410
4411        proptest!(proptest_cfg(), |(value: GenT<u64>)| {
4412            let serialized = serialize(&value).unwrap();
4413            let bincode_serialized = bincode::serialize(&value).unwrap();
4414            prop_assert_eq!(&serialized, &bincode_serialized);
4415            let deserialized: GenT<u64> = deserialize(&serialized).unwrap();
4416            let bincode_deserialized: GenT<u64> = bincode::deserialize(&bincode_serialized).unwrap();
4417            prop_assert_eq!(&deserialized, &bincode_deserialized);
4418            prop_assert_eq!(value, deserialized);
4419        });
4420    }
4421
4422    #[test]
4423    fn test_generic_struct_with_existing_bound() {
4424        #[derive(
4425            SchemaWrite,
4426            SchemaRead,
4427            serde::Serialize,
4428            serde::Deserialize,
4429            Debug,
4430            PartialEq,
4431            Eq,
4432            proptest_derive::Arbitrary,
4433        )]
4434        #[wincode(internal)]
4435        #[repr(transparent)]
4436        struct GenT<T: Copy> {
4437            inner: T,
4438        }
4439
4440        proptest!(proptest_cfg(), |(value: GenT<u64>)| {
4441            let serialized = serialize(&value).unwrap();
4442            let bincode_serialized = bincode::serialize(&value).unwrap();
4443            prop_assert_eq!(&serialized, &bincode_serialized);
4444            let deserialized: GenT<u64> = deserialize(&serialized).unwrap();
4445            let bincode_deserialized: GenT<u64> = bincode::deserialize(&bincode_serialized).unwrap();
4446            prop_assert_eq!(&deserialized, &bincode_deserialized);
4447            prop_assert_eq!(value, deserialized);
4448        });
4449    }
4450
4451    #[test]
4452    fn test_generic_enum() {
4453        #[derive(
4454            SchemaWrite,
4455            SchemaRead,
4456            serde::Serialize,
4457            serde::Deserialize,
4458            Debug,
4459            PartialEq,
4460            Eq,
4461            proptest_derive::Arbitrary,
4462        )]
4463        #[wincode(internal)]
4464        enum GenT<T> {
4465            A(T),
4466            B(u8),
4467        }
4468
4469        assert_eq!(
4470            <GenT<u8> as SchemaWrite<DefaultConfig>>::TYPE_META,
4471            TypeMeta::Static {
4472                size: size_of::<u32>() + 1,
4473                zero_copy: false
4474            }
4475        );
4476
4477        assert_eq!(
4478            <GenT<u64> as SchemaWrite<DefaultConfig>>::TYPE_META,
4479            TypeMeta::Dynamic,
4480        );
4481
4482        proptest!(proptest_cfg(), |(value: GenT<u64>)| {
4483            let serialized = serialize(&value).unwrap();
4484            let bincode_serialized = bincode::serialize(&value).unwrap();
4485            prop_assert_eq!(&serialized, &bincode_serialized);
4486            let deserialized: GenT<u64> = deserialize(&serialized).unwrap();
4487            let bincode_deserialized: GenT<u64> = bincode::deserialize(&bincode_serialized).unwrap();
4488            prop_assert_eq!(&deserialized, &bincode_deserialized);
4489            prop_assert_eq!(value, deserialized);
4490        });
4491    }
4492
4493    #[test]
4494    fn test_recursive_type() {
4495        #[derive(
4496            SchemaWrite, SchemaRead, PartialEq, Debug, serde::Serialize, serde::Deserialize,
4497        )]
4498        #[wincode(internal)]
4499        pub enum Value {
4500            Usize(usize),
4501            List(Vec<Value>),
4502        }
4503
4504        let val = Value::List(vec![Value::Usize(0), Value::List(vec![Value::Usize(1)])]);
4505        let bincode_serialized = bincode::serialize(&val).unwrap();
4506        let serialized = serialize(&val).unwrap();
4507        assert_eq!(&bincode_serialized, &serialized);
4508
4509        let deserialized: Value = deserialize(&serialized).unwrap();
4510        let bincode_deserialized: Value = bincode::deserialize(&bincode_serialized).unwrap();
4511        assert_eq!(&val, &bincode_deserialized);
4512        assert_eq!(val, deserialized);
4513    }
4514
4515    #[test]
4516    fn test_cow_str() {
4517        proptest!(proptest_cfg(), |(value: Cow<str>)| {
4518            let serialized = serialize(&value).unwrap();
4519            let bincode_serialized = bincode::serialize(&value).unwrap();
4520            prop_assert_eq!(&serialized, &bincode_serialized);
4521            let deserialized: Cow<str> = deserialize(&serialized).unwrap();
4522            let bincode_deserialized: Cow<str> = bincode::deserialize(&bincode_serialized).unwrap();
4523            prop_assert_eq!(&deserialized, &bincode_deserialized);
4524            prop_assert_eq!(value, deserialized);
4525        });
4526    }
4527
4528    #[test]
4529    fn test_cow_bytes() {
4530        proptest!(proptest_cfg(), |(value: Cow<[u8]>)| {
4531            let serialized = serialize(&value).unwrap();
4532            let bincode_serialized = bincode::serialize(&value).unwrap();
4533            prop_assert_eq!(&serialized, &bincode_serialized);
4534            let deserialized: Cow<[u8]> = deserialize(&serialized).unwrap();
4535            let bincode_deserialized: Cow<[u8]> = bincode::deserialize(&bincode_serialized).unwrap();
4536            prop_assert_eq!(&deserialized, &bincode_deserialized);
4537            prop_assert_eq!(value, deserialized);
4538        });
4539    }
4540
4541    #[test]
4542    fn test_cow_bytes_owned() {
4543        proptest!(proptest_cfg(), |(value: Cow<[u8]>)| {
4544            let serialized = serialize(&value).unwrap();
4545            let bincode_serialized = bincode::serialize(&value).unwrap();
4546            prop_assert_eq!(&serialized, &bincode_serialized);
4547            let deserialized = <Cow<[u8]> as SchemaRead<DefaultConfig>>
4548                ::get(NoBorrowReader::new(&serialized)).unwrap();
4549            let bincode_deserialized: Cow<[u8]> = bincode::deserialize_from(bincode_serialized.as_slice()).unwrap();
4550            prop_assert_eq!(&deserialized, &bincode_deserialized);
4551            prop_assert_eq!(value, deserialized);
4552        });
4553    }
4554
4555    #[test]
4556    fn test_cow_str_owned() {
4557        proptest!(proptest_cfg(), |(value: Cow<str>)| {
4558            let serialized = serialize(&value).unwrap();
4559            let bincode_serialized = bincode::serialize(&value).unwrap();
4560            prop_assert_eq!(&serialized, &bincode_serialized);
4561            let deserialized = <Cow<str> as SchemaRead<DefaultConfig>>
4562                ::get(NoBorrowReader::new(&serialized)).unwrap();
4563            let bincode_deserialized: Cow<str> = bincode::deserialize_from(bincode_serialized.as_slice()).unwrap();
4564            prop_assert_eq!(&deserialized, &bincode_deserialized);
4565            prop_assert_eq!(value, deserialized);
4566        });
4567    }
4568
4569    #[test]
4570    fn test_cow_ctx() {
4571        #[derive(Debug, PartialEq)]
4572        struct MaybeBorrowed<'a> {
4573            len: u8,
4574            data: Cow<'a, [u8]>,
4575        }
4576
4577        unsafe impl<'a, C: ConfigCore> SchemaWrite<C> for MaybeBorrowed<'a> {
4578            type Src = Self;
4579
4580            fn size_of(src: &Self::Src) -> WriteResult<usize> {
4581                Ok(1 + src.data.len())
4582            }
4583
4584            fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
4585                writer.write(&[src.data.len() as u8])?;
4586                writer.write(&src.data)?;
4587                Ok(())
4588            }
4589        }
4590
4591        unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for MaybeBorrowed<'de> {
4592            type Dst = Self;
4593
4594            fn read(
4595                mut reader: impl Reader<'de>,
4596                dst: &mut MaybeUninit<Self::Dst>,
4597            ) -> ReadResult<()> {
4598                let len = reader.take_byte()?;
4599                let cow = <Cow<'de, [u8]> as SchemaReadContext<C, _>>::get_with_context(
4600                    context::Len(len as usize),
4601                    reader,
4602                )?;
4603                dst.write(MaybeBorrowed { len, data: cow });
4604                Ok(())
4605            }
4606        }
4607
4608        proptest!(proptest_cfg(), |(value in proptest::collection::vec(any::<u8>(), 0..=64))| {
4609            let value = MaybeBorrowed {
4610                len: value.len() as u8,
4611                data: Cow::Owned(value),
4612            };
4613
4614            let serialized = serialize(&value).unwrap();
4615
4616            let deserialized = <MaybeBorrowed as SchemaRead<DefaultConfig>>
4617                ::get(NoBorrowReader::new(&serialized)).unwrap();
4618            prop_assert!(matches!(deserialized.data, Cow::Owned(_)));
4619            prop_assert_eq!(&value, &deserialized);
4620
4621            let deserialized: MaybeBorrowed = deserialize(&serialized).unwrap();
4622            prop_assert!(matches!(deserialized.data, Cow::Borrowed(_)));
4623            prop_assert_eq!(value, deserialized);
4624        });
4625    }
4626}