wincode/schema/
mod.rs

1//! Schema traits.
2//!
3//! # Example
4//!
5//! ```
6//! # #[cfg(all(feature = "solana-short-vec", feature = "alloc"))] {
7//! # use rand::prelude::*;
8//! # use wincode::{Serialize, Deserialize, len::{BincodeLen, ShortU16Len}, containers::{self, Pod}};
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//! # #[derive(SchemaWrite, SchemaRead, serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
22//! struct MyStruct {
23//!     #[wincode(with = "containers::Vec<Pod<_>, BincodeLen>")]
24//!     signature: Vec<Signature>,
25//!     #[serde(with = "solana_short_vec")]
26//!     #[wincode(with = "containers::Vec<Pod<_>, ShortU16Len>")]
27//!     address: Vec<Address>,
28//! }
29//!
30//! let my_struct = MyStruct {
31//!     signature: (0..10).map(|_| Signature(array::from_fn(|_| random()))).collect(),
32//!     address: (0..10).map(|_| Address(array::from_fn(|_| random()))).collect(),
33//! };
34//! let bincode_serialized = bincode::serialize(&my_struct).unwrap();
35//! let wincode_serialized = wincode::serialize(&my_struct).unwrap();
36//! assert_eq!(bincode_serialized, wincode_serialized);
37//!
38//! let bincode_deserialized: MyStruct = bincode::deserialize(&bincode_serialized).unwrap();
39//! let wincode_deserialized: MyStruct = wincode::deserialize(&wincode_serialized).unwrap();
40//! assert_eq!(bincode_deserialized, wincode_deserialized);
41//! # }
42//! ```
43use {
44    crate::{
45        error::{ReadResult, WriteResult},
46        io::*,
47        len::SeqLen,
48    },
49    core::mem::MaybeUninit,
50};
51
52pub mod containers;
53mod impls;
54
55/// Indicates what kind of assumptions can be made when encoding or decoding a type.
56///
57/// Readers and writers may use this to optimize their behavior.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum TypeMeta {
60    /// The type has a statically known serialized size.
61    ///
62    /// Specifying this variant can have significant performance benefits, as it can allow
63    /// writers to prefetch larger chunks of memory such that subsequent read/write operations
64    /// in those chunks can be performed at once without intermediate bounds checks.
65    ///
66    /// Specifying this variant incorrectly will almost certainly result in a panic at runtime.
67    ///
68    /// Take care not to specify this on variable length types, like `Vec` or `String`, as their
69    /// serialized size will vary based on their length.
70    Static {
71        /// The static serialized size of the type.
72        size: usize,
73        /// Whether the type is eligible for zero-copy encoding/decoding.
74        ///
75        /// This indicates that the type has no invalid bit patterns, no layout requirements, no endianness
76        /// checks, etc. This is a very strong claim that should be used judiciously.
77        ///
78        /// Specifying this incorrectly may trigger UB.
79        zero_copy: bool,
80    },
81    /// The type has a dynamic size, and no optimizations can be made.
82    Dynamic,
83}
84
85/// Types that can be written (serialized) to a [`Writer`].
86pub trait SchemaWrite {
87    type Src: ?Sized;
88
89    const TYPE_META: TypeMeta = TypeMeta::Dynamic;
90
91    /// Get the serialized size of `Self::Src`.
92    fn size_of(src: &Self::Src) -> WriteResult<usize>;
93    /// Write `Self::Src` to `writer`.
94    fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()>;
95}
96
97/// Types that can be read (deserialized) from a [`Reader`].
98pub trait SchemaRead<'de> {
99    type Dst;
100
101    const TYPE_META: TypeMeta = TypeMeta::Dynamic;
102
103    /// Read into `dst` from `reader`.
104    ///
105    /// # Safety
106    ///
107    /// - Implementation must properly initialize the `Self::Dst`.
108    fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()>;
109
110    /// Read `Self::Dst` from `reader` into a new `Self::Dst`.
111    #[inline(always)]
112    fn get(reader: &mut impl Reader<'de>) -> ReadResult<Self::Dst> {
113        let mut value = MaybeUninit::uninit();
114        Self::read(reader, &mut value)?;
115        // SAFETY: `read` must properly initialize the `Self::Dst`.
116        Ok(unsafe { value.assume_init() })
117    }
118}
119
120/// A type that can be read (deserialized) from a [`Reader`] without borrowing from it.
121pub trait SchemaReadOwned: for<'de> SchemaRead<'de> {}
122impl<T> SchemaReadOwned for T where T: for<'de> SchemaRead<'de> {}
123
124#[inline(always)]
125#[allow(clippy::arithmetic_side_effects)]
126fn size_of_elem_iter<'a, T, Len>(
127    value: impl ExactSizeIterator<Item = &'a T::Src>,
128) -> WriteResult<usize>
129where
130    Len: SeqLen,
131    T: SchemaWrite + 'a,
132{
133    if let TypeMeta::Static { size, .. } = T::TYPE_META {
134        return Ok(Len::write_bytes_needed(value.len())? + size * value.len());
135    }
136    // Extremely unlikely a type-in-memory's size will overflow usize::MAX.
137    Ok(Len::write_bytes_needed(value.len())?
138        + (value
139            .map(T::size_of)
140            .try_fold(0usize, |acc, x| x.map(|x| acc + x))?))
141}
142
143#[inline(always)]
144#[allow(clippy::arithmetic_side_effects)]
145/// Variant of [`size_of_elem_iter`] specialized for slices, which can opt into
146/// an optimized implementation for bytes (`u8`s).
147fn size_of_elem_slice<T, Len>(value: &[T::Src]) -> WriteResult<usize>
148where
149    Len: SeqLen,
150    T: SchemaWrite,
151    T::Src: Sized,
152{
153    size_of_elem_iter::<T, Len>(value.iter())
154}
155
156#[inline(always)]
157fn write_elem_iter<'a, T, Len>(
158    writer: &mut impl Writer,
159    src: impl ExactSizeIterator<Item = &'a T::Src>,
160) -> WriteResult<()>
161where
162    Len: SeqLen,
163    T: SchemaWrite + 'a,
164{
165    if let TypeMeta::Static { size, .. } = T::TYPE_META {
166        #[allow(clippy::arithmetic_side_effects)]
167        let needed = Len::write_bytes_needed(src.len())? + size * src.len();
168        // SAFETY: `needed` is the size of the encoded length plus the size of the items.
169        // `Len::write` and len writes of `T::Src` will write `needed` bytes,
170        // fully initializing the trusted window.
171        let mut writer = unsafe { writer.as_trusted_for(needed) }?;
172        Len::write(&mut writer, src.len())?;
173        for item in src {
174            T::write(&mut writer, item)?;
175        }
176        writer.finish()?;
177        return Ok(());
178    }
179
180    Len::write(writer, src.len())?;
181    for item in src {
182        T::write(writer, item)?;
183    }
184    Ok(())
185}
186
187#[inline(always)]
188#[allow(clippy::arithmetic_side_effects)]
189/// Variant of [`write_elem_iter`] specialized for slices, which can opt into
190/// an optimized implementation for bytes (`u8`s).
191fn write_elem_slice<T, Len>(writer: &mut impl Writer, src: &[T::Src]) -> WriteResult<()>
192where
193    Len: SeqLen,
194    T: SchemaWrite,
195    T::Src: Sized,
196{
197    if let TypeMeta::Static {
198        size,
199        zero_copy: true,
200    } = T::TYPE_META
201    {
202        let needed = Len::write_bytes_needed(src.len())? + src.len() * size;
203        // SAFETY: `needed` is the size of the encoded length plus the size of the slice (bytes).
204        // `Len::write` and `writer.write(src)` will write `needed` bytes,
205        // fully initializing the trusted window.
206        let writer = &mut unsafe { writer.as_trusted_for(needed) }?;
207        Len::write(writer, src.len())?;
208        // SAFETY: `T::Src` is zero-copy eligible (no invalid bit patterns, no layout requirements, no endianness checks, etc.).
209        unsafe { writer.write_slice_t(src)? };
210        writer.finish()?;
211        return Ok(());
212    }
213    write_elem_iter::<T, Len>(writer, src.iter())
214}
215
216#[cfg(all(test, feature = "std", feature = "derive"))]
217mod tests {
218    #![allow(clippy::arithmetic_side_effects, deprecated)]
219
220    use {
221        crate::{
222            containers::{self, Elem, Pod},
223            deserialize,
224            error::{self, invalid_tag_encoding},
225            io::{Reader, Writer},
226            proptest_config::proptest_cfg,
227            serialize, Deserialize, ReadResult, SchemaRead, SchemaWrite, Serialize, TypeMeta,
228            WriteResult,
229        },
230        core::marker::PhantomData,
231        proptest::prelude::*,
232        std::{
233            cell::Cell,
234            collections::{BinaryHeap, VecDeque},
235            mem::MaybeUninit,
236            rc::Rc,
237            result::Result,
238            sync::Arc,
239        },
240    };
241
242    #[derive(
243        serde::Serialize,
244        serde::Deserialize,
245        Debug,
246        PartialEq,
247        Eq,
248        Ord,
249        PartialOrd,
250        SchemaWrite,
251        SchemaRead,
252        proptest_derive::Arbitrary,
253        Hash,
254    )]
255    #[wincode(internal)]
256    #[repr(C)]
257    struct StructZeroCopy {
258        byte: u8,
259        ar: [u8; 32],
260    }
261
262    #[derive(
263        serde::Serialize,
264        serde::Deserialize,
265        Debug,
266        PartialEq,
267        Eq,
268        Ord,
269        PartialOrd,
270        SchemaWrite,
271        SchemaRead,
272        proptest_derive::Arbitrary,
273        Hash,
274    )]
275    #[wincode(internal)]
276    struct StructStatic {
277        a: u64,
278        b: bool,
279        e: [u8; 32],
280    }
281
282    #[derive(
283        serde::Serialize,
284        serde::Deserialize,
285        Debug,
286        PartialEq,
287        Eq,
288        Ord,
289        PartialOrd,
290        SchemaWrite,
291        SchemaRead,
292        proptest_derive::Arbitrary,
293        Hash,
294    )]
295    #[wincode(internal)]
296    struct StructNonStatic {
297        a: u64,
298        b: bool,
299        e: String,
300    }
301
302    #[test]
303    fn struct_zero_copy_derive_size() {
304        let expected = TypeMeta::Static {
305            size: size_of::<u8>() + size_of::<[u8; 32]>(),
306            zero_copy: true,
307        };
308        assert_eq!(<StructZeroCopy as SchemaWrite>::TYPE_META, expected);
309        assert_eq!(<StructZeroCopy as SchemaRead<'_>>::TYPE_META, expected);
310    }
311
312    #[test]
313    fn struct_zero_copy_transparent_derive_size() {
314        #[derive(SchemaWrite, SchemaRead)]
315        #[wincode(internal)]
316        #[repr(transparent)]
317        struct Address([u8; 32]);
318
319        let expected = TypeMeta::Static {
320            size: size_of::<[u8; 32]>(),
321            zero_copy: true,
322        };
323        assert_eq!(<Address as SchemaWrite>::TYPE_META, expected);
324        assert_eq!(<Address as SchemaRead<'_>>::TYPE_META, expected);
325    }
326
327    #[test]
328    fn struct_static_derive_size() {
329        let expected = TypeMeta::Static {
330            size: size_of::<u64>() + size_of::<bool>() + size_of::<[u8; 32]>(),
331            zero_copy: false,
332        };
333        assert_eq!(<StructStatic as SchemaWrite>::TYPE_META, expected);
334        assert_eq!(<StructStatic as SchemaRead<'_>>::TYPE_META, expected);
335    }
336
337    #[test]
338    fn struct_non_static_derive_size() {
339        let expected = TypeMeta::Dynamic;
340        assert_eq!(<StructNonStatic as SchemaWrite>::TYPE_META, expected);
341        assert_eq!(<StructNonStatic as SchemaRead<'_>>::TYPE_META, expected);
342    }
343
344    thread_local! {
345        /// TL counter for tracking drops (or lack thereof -- a leak).
346        static TL_DROP_COUNT: Cell<isize> = const { Cell::new(0) };
347    }
348
349    fn get_tl_drop_count() -> isize {
350        TL_DROP_COUNT.with(|cell| cell.get())
351    }
352
353    fn tl_drop_count_inc() {
354        TL_DROP_COUNT.with(|cell| cell.set(cell.get() + 1));
355    }
356
357    fn tl_drop_count_dec() {
358        TL_DROP_COUNT.with(|cell| cell.set(cell.get() - 1));
359    }
360
361    fn tl_drop_count_reset() {
362        TL_DROP_COUNT.with(|cell| cell.set(0));
363    }
364
365    #[must_use]
366    #[derive(Debug)]
367    /// Guard for test set up that will ensure that the TL counter is 0 at the start and end of the test.
368    struct TLDropGuard;
369
370    impl TLDropGuard {
371        fn new() -> Self {
372            assert_eq!(
373                get_tl_drop_count(),
374                0,
375                "TL counter drifted from zero -- another test may have leaked"
376            );
377            Self
378        }
379    }
380
381    impl Drop for TLDropGuard {
382        #[track_caller]
383        fn drop(&mut self) {
384            let v = get_tl_drop_count();
385            if !std::thread::panicking() {
386                assert_eq!(
387                    v, 0,
388                    "TL counter drifted from zero -- this test might have leaked"
389                );
390            }
391            tl_drop_count_reset();
392        }
393    }
394
395    #[derive(Debug, PartialEq, Eq)]
396    /// A `SchemaWrite` and `SchemaRead` that will increment the TL counter when constructed.
397    struct DropCounted;
398
399    impl Arbitrary for DropCounted {
400        type Parameters = ();
401        type Strategy = Just<Self>;
402        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
403            Just(Self::new())
404        }
405    }
406
407    impl DropCounted {
408        const TAG_BYTE: u8 = 0;
409
410        fn new() -> Self {
411            tl_drop_count_inc();
412            Self
413        }
414    }
415
416    impl Clone for DropCounted {
417        fn clone(&self) -> Self {
418            tl_drop_count_inc();
419            Self
420        }
421    }
422
423    impl Drop for DropCounted {
424        fn drop(&mut self) {
425            tl_drop_count_dec();
426        }
427    }
428
429    impl SchemaWrite for DropCounted {
430        type Src = Self;
431
432        const TYPE_META: TypeMeta = TypeMeta::Static {
433            size: 1,
434            zero_copy: false,
435        };
436
437        fn size_of(_src: &Self::Src) -> WriteResult<usize> {
438            Ok(1)
439        }
440        fn write(writer: &mut impl Writer, _src: &Self::Src) -> WriteResult<()> {
441            u8::write(writer, &Self::TAG_BYTE)?;
442            Ok(())
443        }
444    }
445
446    impl<'de> SchemaRead<'de> for DropCounted {
447        type Dst = Self;
448
449        const TYPE_META: TypeMeta = TypeMeta::Static {
450            size: 1,
451            zero_copy: false,
452        };
453
454        fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
455            reader.consume(1)?;
456            // This will increment the counter.
457            dst.write(DropCounted::new());
458            Ok(())
459        }
460    }
461
462    /// A `SchemaRead` that will always error on read.
463    #[derive(Debug, Clone, Copy, PartialEq, Eq, proptest_derive::Arbitrary)]
464    struct ErrorsOnRead;
465
466    impl ErrorsOnRead {
467        const TAG_BYTE: u8 = 1;
468    }
469
470    impl SchemaWrite for ErrorsOnRead {
471        type Src = Self;
472
473        const TYPE_META: TypeMeta = TypeMeta::Static {
474            size: 1,
475            zero_copy: false,
476        };
477
478        fn size_of(_src: &Self::Src) -> WriteResult<usize> {
479            Ok(1)
480        }
481
482        fn write(writer: &mut impl Writer, _src: &Self::Src) -> WriteResult<()> {
483            u8::write(writer, &Self::TAG_BYTE)
484        }
485    }
486
487    impl<'de> SchemaRead<'de> for ErrorsOnRead {
488        type Dst = Self;
489
490        const TYPE_META: TypeMeta = TypeMeta::Static {
491            size: 1,
492            zero_copy: false,
493        };
494
495        fn read(
496            reader: &mut impl Reader<'de>,
497            _dst: &mut MaybeUninit<Self::Dst>,
498        ) -> ReadResult<()> {
499            reader.consume(1)?;
500            Err(error::ReadError::PointerSizedReadError)
501        }
502    }
503
504    #[derive(Debug, Clone, PartialEq, Eq, proptest_derive::Arbitrary)]
505    enum DropCountedMaybeError {
506        DropCounted(DropCounted),
507        ErrorsOnRead(ErrorsOnRead),
508    }
509
510    impl SchemaWrite for DropCountedMaybeError {
511        type Src = Self;
512
513        const TYPE_META: TypeMeta = TypeMeta::Static {
514            size: 1,
515            zero_copy: false,
516        };
517
518        fn size_of(src: &Self::Src) -> WriteResult<usize> {
519            match src {
520                DropCountedMaybeError::DropCounted(v) => DropCounted::size_of(v),
521                DropCountedMaybeError::ErrorsOnRead(v) => ErrorsOnRead::size_of(v),
522            }
523        }
524
525        fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
526            match src {
527                DropCountedMaybeError::DropCounted(v) => DropCounted::write(writer, v),
528                DropCountedMaybeError::ErrorsOnRead(v) => ErrorsOnRead::write(writer, v),
529            }
530        }
531    }
532
533    impl<'de> SchemaRead<'de> for DropCountedMaybeError {
534        type Dst = Self;
535
536        const TYPE_META: TypeMeta = TypeMeta::Static {
537            size: 1,
538            zero_copy: false,
539        };
540
541        fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
542            let byte = u8::get(reader)?;
543            match byte {
544                DropCounted::TAG_BYTE => {
545                    dst.write(DropCountedMaybeError::DropCounted(DropCounted::new()));
546                    Ok(())
547                }
548                ErrorsOnRead::TAG_BYTE => Err(error::ReadError::PointerSizedReadError),
549                _ => Err(invalid_tag_encoding(byte as usize)),
550            }
551        }
552    }
553
554    #[test]
555    fn drop_count_sanity() {
556        let _guard = TLDropGuard::new();
557        // Ensure our incrementing counter works
558        let serialized = { serialize(&[DropCounted::new(), DropCounted::new()]).unwrap() };
559        let _deserialized: [DropCounted; 2] = deserialize(&serialized).unwrap();
560        assert_eq!(get_tl_drop_count(), 2);
561    }
562
563    #[test]
564    fn drop_count_maybe_error_sanity() {
565        let _guard = TLDropGuard::new();
566        let serialized =
567            { serialize(&[DropCountedMaybeError::DropCounted(DropCounted::new())]).unwrap() };
568        let _deserialized: [DropCountedMaybeError; 1] = deserialize(&serialized).unwrap();
569        assert_eq!(get_tl_drop_count(), 1);
570
571        let serialized = {
572            serialize(&[
573                DropCountedMaybeError::DropCounted(DropCounted::new()),
574                DropCountedMaybeError::ErrorsOnRead(ErrorsOnRead),
575            ])
576            .unwrap()
577        };
578        let _deserialized: ReadResult<[DropCountedMaybeError; 2]> = deserialize(&serialized);
579    }
580
581    /// Test that the derive macro handles drops of initialized fields on partially initialized structs.
582    #[test]
583    fn test_struct_derive_handles_partial_drop() {
584        /// Represents a struct that would leak if the derive macro didn't handle drops of initialized fields
585        /// on error.
586        #[derive(SchemaWrite, SchemaRead, proptest_derive::Arbitrary, Debug, PartialEq, Eq)]
587        #[wincode(internal)]
588        struct CouldLeak {
589            data: DropCountedMaybeError,
590            data2: DropCountedMaybeError,
591            data3: DropCountedMaybeError,
592        }
593
594        let _guard = TLDropGuard::new();
595        proptest!(proptest_cfg(), |(could_leak: CouldLeak)| {
596            let serialized = serialize(&could_leak).unwrap();
597            let deserialized = CouldLeak::deserialize(&serialized);
598            if let Ok(deserialized) = deserialized {
599                prop_assert_eq!(could_leak, deserialized);
600            }
601        });
602    }
603
604    /// Test that the derive macro handles drops of initialized fields on partially initialized enums.
605    #[test]
606    fn test_enum_derive_handles_partial_drop() {
607        /// Represents an enum that would leak if the derive macro didn't handle drops of initialized fields
608        /// on error.
609        #[derive(SchemaWrite, SchemaRead, proptest_derive::Arbitrary, Debug, PartialEq, Eq)]
610        #[wincode(internal)]
611        enum CouldLeak {
612            A {
613                a: DropCountedMaybeError,
614                b: DropCountedMaybeError,
615            },
616            B(
617                DropCountedMaybeError,
618                DropCountedMaybeError,
619                DropCountedMaybeError,
620            ),
621            C(DropCountedMaybeError),
622            D,
623        }
624
625        let _guard = TLDropGuard::new();
626        proptest!(proptest_cfg(), |(could_leak: CouldLeak)| {
627            let serialized = serialize(&could_leak).unwrap();
628            let deserialized = CouldLeak::deserialize(&serialized);
629            if let Ok(deserialized) = deserialized {
630                prop_assert_eq!(could_leak, deserialized);
631            }
632        });
633    }
634
635    #[test]
636    fn test_tuple_handles_partial_drop() {
637        let _guard = TLDropGuard::new();
638        let serialized =
639            { serialize(&(DropCounted::new(), DropCounted::new(), ErrorsOnRead)).unwrap() };
640        let deserialized = <(DropCounted, DropCounted, ErrorsOnRead)>::deserialize(&serialized);
641        assert!(deserialized.is_err());
642    }
643
644    #[test]
645    fn test_vec_handles_partial_drop() {
646        let _guard = TLDropGuard::new();
647        proptest!(proptest_cfg(), |(vec in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100))| {
648            let serialized = serialize(&vec).unwrap();
649            let deserialized = <Vec<DropCountedMaybeError>>::deserialize(&serialized);
650            if let Ok(deserialized) = deserialized {
651                prop_assert_eq!(vec, deserialized);
652            }
653        });
654    }
655
656    #[test]
657    fn test_vec_deque_handles_partial_drop() {
658        let _guard = TLDropGuard::new();
659        proptest!(proptest_cfg(), |(vec in proptest::collection::vec_deque(any::<DropCountedMaybeError>(), 0..100))| {
660            let serialized = serialize(&vec).unwrap();
661            let deserialized = <VecDeque<DropCountedMaybeError>>::deserialize(&serialized);
662            if let Ok(deserialized) = deserialized {
663                prop_assert_eq!(vec, deserialized);
664            }
665        });
666    }
667
668    #[test]
669    fn test_boxed_slice_handles_partial_drop() {
670        let _guard = TLDropGuard::new();
671        proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(|vec| vec.into_boxed_slice()))| {
672            let serialized = serialize(&slice).unwrap();
673            let deserialized = <Box<[DropCountedMaybeError]>>::deserialize(&serialized);
674            if let Ok(deserialized) = deserialized {
675                prop_assert_eq!(slice, deserialized);
676            }
677        });
678    }
679
680    #[test]
681    fn test_rc_slice_handles_partial_drop() {
682        let _guard = TLDropGuard::new();
683        proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(Rc::from))| {
684            let serialized = serialize(&slice).unwrap();
685            let deserialized = <Rc<[DropCountedMaybeError]>>::deserialize(&serialized);
686            if let Ok(deserialized) = deserialized {
687                prop_assert_eq!(slice, deserialized);
688            }
689        });
690    }
691
692    #[test]
693    fn test_arc_slice_handles_partial_drop() {
694        let _guard = TLDropGuard::new();
695        proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(Arc::from))| {
696            let serialized = serialize(&slice).unwrap();
697            let deserialized = <Arc<[DropCountedMaybeError]>>::deserialize(&serialized);
698            if let Ok(deserialized) = deserialized {
699                prop_assert_eq!(slice, deserialized);
700            }
701        });
702    }
703
704    #[test]
705    fn test_arc_handles_drop() {
706        let _guard = TLDropGuard::new();
707        proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Rc::from))| {
708            let serialized = serialize(&data).unwrap();
709            let deserialized = deserialize(&serialized);
710            if let Ok(deserialized) = deserialized {
711                prop_assert_eq!(data, deserialized);
712            }
713        });
714    }
715
716    #[test]
717    fn test_rc_handles_drop() {
718        let _guard = TLDropGuard::new();
719        proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Rc::from))| {
720            let serialized = serialize(&data).unwrap();
721            let deserialized = deserialize(&serialized);
722            if let Ok(deserialized) = deserialized {
723                prop_assert_eq!(data, deserialized);
724            }
725        });
726    }
727
728    #[test]
729    fn test_box_handles_drop() {
730        let _guard = TLDropGuard::new();
731        proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Box::new))| {
732            let serialized = serialize(&data).unwrap();
733            let deserialized = deserialize(&serialized);
734            if let Ok(deserialized) = deserialized {
735                prop_assert_eq!(data, deserialized);
736            }
737        });
738    }
739
740    #[test]
741    fn test_array_handles_partial_drop() {
742        let _guard = TLDropGuard::new();
743
744        proptest!(proptest_cfg(), |(array in proptest::array::uniform32(any::<DropCountedMaybeError>()))| {
745            let serialized = serialize(&array).unwrap();
746            let deserialized = <[DropCountedMaybeError; 32]>::deserialize(&serialized);
747            if let Ok(deserialized) = deserialized {
748                prop_assert_eq!(array, deserialized);
749            }
750        });
751    }
752
753    #[test]
754    fn test_struct_with_reference_equivalence() {
755        #[derive(
756            SchemaWrite, SchemaRead, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize,
757        )]
758        #[wincode(internal)]
759        struct WithReference<'a> {
760            data: &'a str,
761            id: u64,
762        }
763
764        proptest!(proptest_cfg(), |(s in any::<String>(), id in any::<u64>())| {
765            let serialized = serialize(&WithReference { data: &s, id }).unwrap();
766            let bincode_serialized = bincode::serialize(&WithReference { data: &s, id }).unwrap();
767            prop_assert_eq!(&serialized, &bincode_serialized);
768            let deserialized: WithReference = deserialize(&serialized).unwrap();
769            let bincode_deserialized: WithReference = bincode::deserialize(&bincode_serialized).unwrap();
770            prop_assert_eq!(deserialized, bincode_deserialized);
771        });
772    }
773
774    #[test]
775    fn test_enum_equivalence() {
776        #[derive(
777            SchemaWrite,
778            SchemaRead,
779            Debug,
780            PartialEq,
781            Eq,
782            serde::Serialize,
783            serde::Deserialize,
784            Clone,
785            proptest_derive::Arbitrary,
786        )]
787        #[wincode(internal)]
788        enum Enum {
789            A { name: String, id: u64 },
790            B(String, #[wincode(with = "containers::Vec<Pod<_>>")] Vec<u8>),
791            C,
792        }
793
794        proptest!(proptest_cfg(), |(e: Enum)| {
795            let serialized = serialize(&e).unwrap();
796            let bincode_serialized = bincode::serialize(&e).unwrap();
797            prop_assert_eq!(&serialized, &bincode_serialized);
798            let deserialized: Enum = deserialize(&serialized).unwrap();
799            let bincode_deserialized: Enum = bincode::deserialize(&bincode_serialized).unwrap();
800            prop_assert_eq!(deserialized, bincode_deserialized);
801        });
802    }
803
804    #[test]
805    fn enum_with_tag_encoding_roundtrip() {
806        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
807        #[wincode(internal, tag_encoding = "u8")]
808        enum Enum {
809            A { name: String, id: u64 },
810            B(String, Vec<u8>),
811            C,
812        }
813
814        proptest!(proptest_cfg(), |(e: Enum)| {
815            let serialized = serialize(&e).unwrap();
816            let deserialized: Enum = deserialize(&serialized).unwrap();
817            prop_assert_eq!(deserialized, e);
818        });
819    }
820
821    #[test]
822    fn enum_with_custom_tag_roundtrip() {
823        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
824        #[wincode(internal)]
825        enum Enum {
826            #[wincode(tag = 5)]
827            A { name: String, id: u64 },
828            #[wincode(tag = 8)]
829            B(String, Vec<u8>),
830            #[wincode(tag = 13)]
831            C,
832        }
833
834        proptest!(proptest_cfg(), |(e: Enum)| {
835            let serialized = serialize(&e).unwrap();
836            let deserialized: Enum = deserialize(&serialized).unwrap();
837            prop_assert_eq!(deserialized, e);
838        });
839
840        proptest!(proptest_cfg(), |(e: Enum)| {
841            let serialized = serialize(&e).unwrap();
842            let int: u32 = match e {
843                Enum::A { .. } => 5,
844                Enum::B(..) => 8,
845                Enum::C => 13,
846            };
847            prop_assert_eq!(&int.to_le_bytes(), &serialized[..4]);
848        });
849    }
850
851    #[test]
852    fn unit_enum_with_tag_encoding_static_size() {
853        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq)]
854        #[wincode(internal, tag_encoding = "u8")]
855        enum Enum {
856            A,
857            B,
858            C,
859        }
860
861        assert!(matches!(
862            <Enum as SchemaWrite>::TYPE_META,
863            TypeMeta::Static {
864                size: 1,
865                zero_copy: false
866            }
867        ));
868
869        assert!(matches!(
870            <Enum as SchemaRead<'_>>::TYPE_META,
871            TypeMeta::Static {
872                size: 1,
873                zero_copy: false
874            }
875        ));
876    }
877
878    #[test]
879    fn unit_enum_with_static_size() {
880        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq)]
881        #[wincode(internal)]
882        enum Enum {
883            A,
884            B,
885            C,
886        }
887
888        assert!(matches!(
889            <Enum as SchemaWrite>::TYPE_META,
890            TypeMeta::Static {
891                size: 4,
892                zero_copy: false
893            }
894        ));
895
896        assert!(matches!(
897            <Enum as SchemaRead<'_>>::TYPE_META,
898            TypeMeta::Static {
899                size: 4,
900                zero_copy: false
901            }
902        ));
903    }
904
905    #[test]
906    fn enum_tag_encoding() {
907        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
908        #[wincode(internal, tag_encoding = "u8")]
909        enum EnumU8 {
910            A,
911            B,
912            C,
913        }
914
915        proptest!(proptest_cfg(), |(e: EnumU8)| {
916            let serialized = serialize(&e).unwrap();
917            let int = e as u8;
918            prop_assert_eq!(&int.to_le_bytes(), &serialized[..]);
919        });
920
921        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
922        #[wincode(internal, tag_encoding = "u8")]
923        enum EnumTupleU8 {
924            A(u64),
925            B(StructStatic),
926            C(StructNonStatic),
927        }
928
929        proptest!(proptest_cfg(), |(e: EnumTupleU8)| {
930            let serialized = serialize(&e).unwrap();
931            let int: u8 = match e {
932                EnumTupleU8::A(_) => 0,
933                EnumTupleU8::B(_) => 1,
934                EnumTupleU8::C(_) => 2,
935            };
936            prop_assert_eq!(&int.to_le_bytes(), &serialized[..1]);
937        });
938
939        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
940        #[wincode(internal, tag_encoding = "u8")]
941        enum EnumRecordU8 {
942            A { id: u64 },
943            B { data: StructStatic },
944            C { data: StructNonStatic },
945        }
946
947        proptest!(proptest_cfg(), |(e: EnumRecordU8)| {
948            let serialized = serialize(&e).unwrap();
949            let int: u8 = match e {
950                EnumRecordU8::A { .. } => 0,
951                EnumRecordU8::B { .. } => 1,
952                EnumRecordU8::C { .. } => 2,
953            };
954            prop_assert_eq!(&int.to_le_bytes(), &serialized[..1]);
955        });
956    }
957
958    #[test]
959    fn enum_static_uniform_variants() {
960        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
961        #[wincode(internal)]
962        enum Enum {
963            A {
964                a: u64,
965            },
966            B {
967                x: u32,
968                y: u32,
969            },
970            C {
971                a: u8,
972                b: u8,
973                c: u8,
974                d: u8,
975                e: u8,
976                f: u8,
977                g: u8,
978                h: u8,
979            },
980        }
981
982        assert_eq!(
983            <Enum as SchemaWrite>::TYPE_META,
984            TypeMeta::Static {
985                // (account for discriminant u32)
986                size: 8 + 4,
987                zero_copy: false
988            }
989        );
990        assert_eq!(
991            <Enum as SchemaRead<'_>>::TYPE_META,
992            TypeMeta::Static {
993                // (account for discriminant u32)
994                size: 8 + 4,
995                zero_copy: false
996            }
997        );
998
999        proptest!(proptest_cfg(), |(e: Enum)| {
1000            let serialized = serialize(&e).unwrap();
1001            let deserialized: Enum = deserialize(&serialized).unwrap();
1002            prop_assert_eq!(deserialized, e);
1003        });
1004    }
1005
1006    #[test]
1007    fn enum_dynamic_non_uniform_variants() {
1008        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1009        #[wincode(internal)]
1010        enum Enum {
1011            A { a: u64 },
1012            B { x: u32, y: u32 },
1013            C { a: u8, b: u8 },
1014        }
1015
1016        assert_eq!(<Enum as SchemaWrite>::TYPE_META, TypeMeta::Dynamic);
1017        assert_eq!(<Enum as SchemaRead<'_>>::TYPE_META, TypeMeta::Dynamic);
1018
1019        proptest!(proptest_cfg(), |(e: Enum)| {
1020            let serialized = serialize(&e).unwrap();
1021            let deserialized: Enum = deserialize(&serialized).unwrap();
1022            prop_assert_eq!(deserialized, e);
1023        });
1024    }
1025
1026    #[test]
1027    fn enum_single_variant_type_meta_pass_thru() {
1028        #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1029        #[wincode(internal)]
1030        enum Enum {
1031            A { a: u8, b: [u8; 32] },
1032        }
1033
1034        // Single variant enums should use the `TypeMeta` of the variant, but the zero-copy
1035        // flag should be `false`, due to the discriminant having potentially invalid bit patterns.
1036        assert_eq!(
1037            <Enum as SchemaWrite>::TYPE_META,
1038            TypeMeta::Static {
1039                size: 1 + 32 + 4,
1040                zero_copy: false
1041            }
1042        );
1043        assert_eq!(
1044            <Enum as SchemaRead<'_>>::TYPE_META,
1045            TypeMeta::Static {
1046                size: 1 + 32 + 4,
1047                zero_copy: false
1048            }
1049        );
1050    }
1051
1052    #[test]
1053    fn enum_unit_and_non_unit_dynamic() {
1054        #[derive(
1055            SchemaWrite,
1056            SchemaRead,
1057            Debug,
1058            PartialEq,
1059            proptest_derive::Arbitrary,
1060            serde::Serialize,
1061            serde::Deserialize,
1062        )]
1063        #[wincode(internal)]
1064        enum Enum {
1065            Unit,
1066            NonUnit(u8),
1067        }
1068
1069        assert_eq!(<Enum as SchemaWrite>::TYPE_META, TypeMeta::Dynamic);
1070        assert_eq!(<Enum as SchemaRead<'_>>::TYPE_META, TypeMeta::Dynamic);
1071
1072        proptest!(proptest_cfg(), |(e: Enum)| {
1073            let serialized = serialize(&e).unwrap();
1074            let bincode_serialized = bincode::serialize(&e).unwrap();
1075            prop_assert_eq!(&serialized, &bincode_serialized);
1076
1077            let deserialized: Enum = deserialize(&serialized).unwrap();
1078            let bincode_deserialized: Enum = bincode::deserialize(&bincode_serialized).unwrap();
1079            prop_assert_eq!(&deserialized, &bincode_deserialized);
1080            prop_assert_eq!(deserialized, e);
1081        });
1082    }
1083
1084    #[test]
1085    fn test_phantom_data() {
1086        let val = PhantomData::<StructStatic>;
1087        let serialized = serialize(&val).unwrap();
1088        let bincode_serialized = bincode::serialize(&val).unwrap();
1089        assert_eq!(&serialized, &bincode_serialized);
1090        assert_eq!(
1091            PhantomData::<StructStatic>::size_of(&val).unwrap(),
1092            bincode::serialized_size(&val).unwrap() as usize
1093        );
1094        let deserialized: PhantomData<StructStatic> = deserialize(&serialized).unwrap();
1095        let bincode_deserialized: PhantomData<StructStatic> =
1096            bincode::deserialize(&bincode_serialized).unwrap();
1097        assert_eq!(deserialized, bincode_deserialized);
1098    }
1099
1100    #[test]
1101    fn test_unit() {
1102        let serialized = serialize(&()).unwrap();
1103        let bincode_serialized = bincode::serialize(&()).unwrap();
1104        assert_eq!(&serialized, &bincode_serialized);
1105        assert_eq!(
1106            <()>::size_of(&()).unwrap(),
1107            bincode::serialized_size(&()).unwrap() as usize
1108        );
1109        assert!(deserialize::<()>(&serialized).is_ok());
1110        assert!(bincode::deserialize::<()>(&bincode_serialized).is_ok());
1111    }
1112
1113    #[test]
1114    fn test_borrowed_bytes() {
1115        #[derive(
1116            SchemaWrite, SchemaRead, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize,
1117        )]
1118        #[wincode(internal)]
1119        struct BorrowedBytes<'a> {
1120            bytes: &'a [u8],
1121        }
1122
1123        proptest!(proptest_cfg(), |(bytes in proptest::collection::vec(any::<u8>(), 0..=100))| {
1124            let val = BorrowedBytes { bytes: &bytes };
1125            let bincode_serialized = bincode::serialize(&val).unwrap();
1126            let schema_serialized = serialize(&val).unwrap();
1127            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1128            let bincode_deserialized: BorrowedBytes = bincode::deserialize(&bincode_serialized).unwrap();
1129            let schema_deserialized: BorrowedBytes = deserialize(&schema_serialized).unwrap();
1130            prop_assert_eq!(&val, &bincode_deserialized);
1131            prop_assert_eq!(val, schema_deserialized);
1132        });
1133    }
1134
1135    #[test]
1136    fn test_boxed_slice_pod_drop() {
1137        #[derive(proptest_derive::Arbitrary, Debug, Clone, Copy)]
1138        #[allow(dead_code)]
1139        struct Signature([u8; 64]);
1140
1141        type Target = containers::Box<[Pod<Signature>]>;
1142        proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<Signature>(), 1..=32).prop_map(|vec| vec.into_boxed_slice()))| {
1143            let serialized = Target::serialize(&slice).unwrap();
1144            // Deliberately trigger the drop with a failed deserialization
1145            // This test is specifically to get miri to exercise the drop logic
1146            let deserialized = Target::deserialize(&serialized[..serialized.len() - 32]);
1147            prop_assert!(deserialized.is_err());
1148        });
1149    }
1150
1151    #[test]
1152    fn test_zero_copy_padding_disqualification() {
1153        #[derive(SchemaWrite, SchemaRead)]
1154        #[wincode(internal)]
1155        #[repr(C, align(4))]
1156        struct Padded {
1157            a: u8,
1158        }
1159
1160        assert!(matches!(
1161            <Padded as SchemaWrite>::TYPE_META,
1162            TypeMeta::Static {
1163                // Serialized size is still the size of the byte, not the in-memory size.
1164                size: 1,
1165                // Padding disqualifies the type from zero-copy optimization.
1166                zero_copy: false
1167            }
1168        ));
1169
1170        assert!(matches!(
1171            <Padded as SchemaRead<'_>>::TYPE_META,
1172            TypeMeta::Static {
1173                // Serialized size is still the size of the byte, not the in-memory size.
1174                size: 1,
1175                // Padding disqualifies the type from zero-copy optimization.
1176                zero_copy: false
1177            }
1178        ));
1179    }
1180
1181    proptest! {
1182        #![proptest_config(proptest_cfg())]
1183
1184        #[test]
1185        fn test_char(val in any::<char>()) {
1186            let bincode_serialized = bincode::serialize(&val).unwrap();
1187            let schema_serialized = serialize(&val).unwrap();
1188            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1189            prop_assert_eq!(char::size_of(&val).unwrap(), bincode::serialized_size(&val).unwrap() as usize);
1190
1191            let bincode_deserialized: char = bincode::deserialize(&bincode_serialized).unwrap();
1192            let schema_deserialized: char = deserialize(&schema_serialized).unwrap();
1193            prop_assert_eq!(val, bincode_deserialized);
1194            prop_assert_eq!(val, schema_deserialized);
1195        }
1196
1197        #[test]
1198        fn test_elem_compat(val in any::<StructStatic>()) {
1199            let bincode_serialized = bincode::serialize(&val).unwrap();
1200            let schema_serialized = <Elem<StructStatic>>::serialize(&val).unwrap();
1201            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1202
1203            let bincode_deserialized: StructStatic = bincode::deserialize(&bincode_serialized).unwrap();
1204            let schema_deserialized: StructStatic = <Elem<StructStatic>>::deserialize(&schema_serialized).unwrap();
1205            prop_assert_eq!(&val, &bincode_deserialized);
1206            prop_assert_eq!(val, schema_deserialized);
1207        }
1208
1209        #[test]
1210        fn test_elem_vec_compat(val in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
1211            let bincode_serialized = bincode::serialize(&val).unwrap();
1212            let schema_serialized = <containers::Vec<Elem<StructStatic>>>::serialize(&val).unwrap();
1213            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1214
1215            let bincode_deserialized: Vec<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1216            let schema_deserialized = <containers::Vec<Elem<StructStatic>>>::deserialize(&schema_serialized).unwrap();
1217            prop_assert_eq!(&val, &bincode_deserialized);
1218            prop_assert_eq!(val, schema_deserialized);
1219        }
1220
1221        #[test]
1222        fn test_vec_elem_static(vec in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
1223            let bincode_serialized = bincode::serialize(&vec).unwrap();
1224            let schema_serialized = serialize(&vec).unwrap();
1225            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1226
1227            let bincode_deserialized: Vec<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1228            let schema_deserialized: Vec<StructStatic> = deserialize(&schema_serialized).unwrap();
1229            prop_assert_eq!(&vec, &bincode_deserialized);
1230            prop_assert_eq!(vec, schema_deserialized);
1231        }
1232
1233        #[test]
1234        fn test_vec_elem_zero_copy(vec in proptest::collection::vec(any::<StructZeroCopy>(), 0..=100)) {
1235            let bincode_serialized = bincode::serialize(&vec).unwrap();
1236            let schema_serialized = serialize(&vec).unwrap();
1237            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1238
1239            let bincode_deserialized: Vec<StructZeroCopy> = bincode::deserialize(&bincode_serialized).unwrap();
1240            let schema_deserialized: Vec<StructZeroCopy> = deserialize(&schema_serialized).unwrap();
1241            prop_assert_eq!(&vec, &bincode_deserialized);
1242            prop_assert_eq!(vec, schema_deserialized);
1243        }
1244
1245
1246        #[test]
1247        fn test_vec_elem_non_static(vec in proptest::collection::vec(any::<StructNonStatic>(), 0..=16)) {
1248            let bincode_serialized = bincode::serialize(&vec).unwrap();
1249            let schema_serialized = serialize(&vec).unwrap();
1250            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1251
1252            let bincode_deserialized: Vec<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1253            let schema_deserialized: Vec<StructNonStatic> = deserialize(&schema_serialized).unwrap();
1254            prop_assert_eq!(&vec, &bincode_deserialized);
1255            prop_assert_eq!(vec, schema_deserialized);
1256        }
1257
1258        #[test]
1259        fn test_vec_elem_bytes(vec in proptest::collection::vec(any::<u8>(), 0..=100)) {
1260            let bincode_serialized = bincode::serialize(&vec).unwrap();
1261            let schema_serialized = serialize(&vec).unwrap();
1262            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1263
1264            let bincode_deserialized: Vec<u8> = bincode::deserialize(&bincode_serialized).unwrap();
1265            let schema_deserialized: Vec<u8> = deserialize(&schema_serialized).unwrap();
1266            prop_assert_eq!(&vec, &bincode_deserialized);
1267            prop_assert_eq!(vec, schema_deserialized);
1268        }
1269
1270        #[test]
1271        fn test_serialize_slice(slice in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
1272            let bincode_serialized = bincode::serialize(slice.as_slice()).unwrap();
1273            let schema_serialized = serialize(slice.as_slice()).unwrap();
1274            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1275        }
1276
1277        #[test]
1278        fn test_vec_pod(vec in proptest::collection::vec(any::<[u8; 32]>(), 0..=100)) {
1279            let bincode_serialized = bincode::serialize(&vec).unwrap();
1280            let schema_serialized = serialize(&vec).unwrap();
1281            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1282
1283            let bincode_deserialized: Vec<[u8; 32]> = bincode::deserialize(&bincode_serialized).unwrap();
1284            let schema_deserialized: Vec<[u8; 32]> = deserialize(&schema_serialized).unwrap();
1285            prop_assert_eq!(&vec, &bincode_deserialized);
1286            prop_assert_eq!(vec, schema_deserialized);
1287        }
1288
1289        #[test]
1290        fn test_vec_deque_elem_static(vec in proptest::collection::vec_deque(any::<StructStatic>(), 0..=100)) {
1291            let bincode_serialized = bincode::serialize(&vec).unwrap();
1292            let schema_serialized = serialize(&vec).unwrap();
1293            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1294
1295            let bincode_deserialized: VecDeque<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1296            let schema_deserialized: VecDeque<StructStatic> = deserialize(&schema_serialized).unwrap();
1297            prop_assert_eq!(&vec, &bincode_deserialized);
1298            prop_assert_eq!(vec, schema_deserialized);
1299        }
1300
1301        #[test]
1302        fn test_vec_deque_elem_non_static(vec in proptest::collection::vec_deque(any::<StructNonStatic>(), 0..=16)) {
1303            let bincode_serialized = bincode::serialize(&vec).unwrap();
1304            let schema_serialized = serialize(&vec).unwrap();
1305            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1306
1307            let bincode_deserialized: VecDeque<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1308            let schema_deserialized: VecDeque<StructNonStatic> = deserialize(&schema_serialized).unwrap();
1309            prop_assert_eq!(&vec, &bincode_deserialized);
1310            prop_assert_eq!(vec, schema_deserialized);
1311        }
1312
1313        #[test]
1314        fn test_vec_deque_elem_bytes(vec in proptest::collection::vec_deque(any::<u8>(), 0..=100)) {
1315            let bincode_serialized = bincode::serialize(&vec).unwrap();
1316            let schema_serialized = serialize(&vec).unwrap();
1317            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1318
1319            let bincode_deserialized: VecDeque<u8> = bincode::deserialize(&bincode_serialized).unwrap();
1320            let schema_deserialized: VecDeque<u8> = deserialize(&schema_serialized).unwrap();
1321            prop_assert_eq!(&vec, &bincode_deserialized);
1322            prop_assert_eq!(vec, schema_deserialized);
1323        }
1324
1325        #[test]
1326        fn test_hash_map_zero_copy(map in proptest::collection::hash_map(any::<u8>(), any::<StructZeroCopy>(), 0..=100)) {
1327            let bincode_serialized = bincode::serialize(&map).unwrap();
1328            let schema_serialized = serialize(&map).unwrap();
1329            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1330
1331            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1332            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1333            prop_assert_eq!(&map, &bincode_deserialized);
1334            prop_assert_eq!(map, schema_deserialized);
1335        }
1336
1337        #[test]
1338        fn test_hash_map_static(map in proptest::collection::hash_map(any::<u64>(), any::<StructStatic>(), 0..=100)) {
1339            let bincode_serialized = bincode::serialize(&map).unwrap();
1340            let schema_serialized = serialize(&map).unwrap();
1341            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1342
1343            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1344            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1345            prop_assert_eq!(&map, &bincode_deserialized);
1346            prop_assert_eq!(map, schema_deserialized);
1347        }
1348
1349
1350        #[test]
1351        fn test_hash_map_non_static(map in proptest::collection::hash_map(any::<u64>(), any::<StructNonStatic>(), 0..=16)) {
1352            let bincode_serialized = bincode::serialize(&map).unwrap();
1353            let schema_serialized = serialize(&map).unwrap();
1354            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1355
1356            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1357            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1358            prop_assert_eq!(&map, &bincode_deserialized);
1359            prop_assert_eq!(map, schema_deserialized);
1360        }
1361
1362        #[test]
1363        fn test_hash_set_zero_copy(set in proptest::collection::hash_set(any::<StructZeroCopy>(), 0..=100)) {
1364            let bincode_serialized = bincode::serialize(&set).unwrap();
1365            let schema_serialized = serialize(&set).unwrap();
1366            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1367
1368            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1369            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1370            prop_assert_eq!(&set, &bincode_deserialized);
1371            prop_assert_eq!(set, schema_deserialized);
1372        }
1373
1374        #[test]
1375        fn test_hash_set_static(set in proptest::collection::hash_set(any::<StructStatic>(), 0..=100)) {
1376            let bincode_serialized = bincode::serialize(&set).unwrap();
1377            let schema_serialized = serialize(&set).unwrap();
1378            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1379
1380            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1381            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1382            prop_assert_eq!(&set, &bincode_deserialized);
1383            prop_assert_eq!(set, schema_deserialized);
1384        }
1385
1386        #[test]
1387        fn test_hash_set_non_static(set in proptest::collection::hash_set(any::<StructNonStatic>(), 0..=16)) {
1388            let bincode_serialized = bincode::serialize(&set).unwrap();
1389            let schema_serialized = serialize(&set).unwrap();
1390            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1391
1392            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1393            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1394            prop_assert_eq!(&set, &bincode_deserialized);
1395            prop_assert_eq!(set, schema_deserialized);
1396        }
1397
1398        #[test]
1399        fn test_btree_map_zero_copy(map in proptest::collection::btree_map(any::<u8>(), any::<StructZeroCopy>(), 0..=100)) {
1400            let bincode_serialized = bincode::serialize(&map).unwrap();
1401            let schema_serialized = serialize(&map).unwrap();
1402            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1403
1404            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1405            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1406            prop_assert_eq!(&map, &bincode_deserialized);
1407            prop_assert_eq!(map, schema_deserialized);
1408        }
1409
1410        #[test]
1411        fn test_btree_map_static(map in proptest::collection::btree_map(any::<u64>(), any::<StructStatic>(), 0..=100)) {
1412            let bincode_serialized = bincode::serialize(&map).unwrap();
1413            let schema_serialized = serialize(&map).unwrap();
1414            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1415
1416            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1417            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1418            prop_assert_eq!(&map, &bincode_deserialized);
1419            prop_assert_eq!(map, schema_deserialized);
1420        }
1421
1422        #[test]
1423        fn test_btree_map_non_static(map in proptest::collection::btree_map(any::<u64>(), any::<StructNonStatic>(), 0..=16)) {
1424            let bincode_serialized = bincode::serialize(&map).unwrap();
1425            let schema_serialized = serialize(&map).unwrap();
1426            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1427
1428            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1429            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1430            prop_assert_eq!(&map, &bincode_deserialized);
1431            prop_assert_eq!(map, schema_deserialized);
1432        }
1433
1434        #[test]
1435        fn test_btree_set_zero_copy(set in proptest::collection::btree_set(any::<StructZeroCopy>(), 0..=100)) {
1436            let bincode_serialized = bincode::serialize(&set).unwrap();
1437            let schema_serialized = serialize(&set).unwrap();
1438            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1439
1440            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1441            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1442            prop_assert_eq!(&set, &bincode_deserialized);
1443            prop_assert_eq!(set, schema_deserialized);
1444        }
1445
1446        #[test]
1447        fn test_btree_set_static(set in proptest::collection::btree_set(any::<StructStatic>(), 0..=100)) {
1448            let bincode_serialized = bincode::serialize(&set).unwrap();
1449            let schema_serialized = serialize(&set).unwrap();
1450            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1451
1452            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1453            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1454            prop_assert_eq!(&set, &bincode_deserialized);
1455            prop_assert_eq!(set, schema_deserialized);
1456        }
1457
1458        #[test]
1459        fn test_btree_set_non_static(map in proptest::collection::btree_set(any::<StructNonStatic>(), 0..=16)) {
1460            let bincode_serialized = bincode::serialize(&map).unwrap();
1461            let schema_serialized = serialize(&map).unwrap();
1462            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1463
1464            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1465            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1466            prop_assert_eq!(&map, &bincode_deserialized);
1467            prop_assert_eq!(map, schema_deserialized);
1468        }
1469
1470        #[test]
1471        fn test_binary_heap_zero_copy(heap in proptest::collection::binary_heap(any::<StructZeroCopy>(), 0..=100)) {
1472            let bincode_serialized = bincode::serialize(&heap).unwrap();
1473            let schema_serialized = serialize(&heap).unwrap();
1474            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1475
1476            let bincode_deserialized: BinaryHeap<StructZeroCopy> = bincode::deserialize(&bincode_serialized).unwrap();
1477            let schema_deserialized: BinaryHeap<StructZeroCopy> = deserialize(&schema_serialized).unwrap();
1478            prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
1479            prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
1480        }
1481
1482        #[test]
1483        fn test_binary_heap_static(heap in proptest::collection::binary_heap(any::<StructStatic>(), 0..=100)) {
1484            let bincode_serialized = bincode::serialize(&heap).unwrap();
1485            let schema_serialized = serialize(&heap).unwrap();
1486            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1487
1488            let bincode_deserialized: BinaryHeap<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1489            let schema_deserialized: BinaryHeap<StructStatic> = deserialize(&schema_serialized).unwrap();
1490            prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
1491            prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
1492        }
1493
1494
1495        #[test]
1496        fn test_binary_heap_non_static(heap in proptest::collection::binary_heap(any::<StructNonStatic>(), 0..=16)) {
1497            let bincode_serialized = bincode::serialize(&heap).unwrap();
1498            let schema_serialized = serialize(&heap).unwrap();
1499            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1500
1501            let bincode_deserialized: BinaryHeap<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1502            let schema_deserialized: BinaryHeap<StructNonStatic> = deserialize(&schema_serialized).unwrap();
1503            prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
1504            prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
1505        }
1506
1507        #[test]
1508        fn test_linked_list_zero_copy(list in proptest::collection::linked_list(any::<StructZeroCopy>(), 0..=100)) {
1509            let bincode_serialized = bincode::serialize(&list).unwrap();
1510            let schema_serialized = serialize(&list).unwrap();
1511            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1512
1513            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1514            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1515            prop_assert_eq!(&list, &bincode_deserialized);
1516            prop_assert_eq!(list, schema_deserialized);
1517        }
1518
1519        #[test]
1520        fn test_linked_list_static(list in proptest::collection::linked_list(any::<StructStatic>(), 0..=100)) {
1521            let bincode_serialized = bincode::serialize(&list).unwrap();
1522            let schema_serialized = serialize(&list).unwrap();
1523            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1524
1525            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1526            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1527            prop_assert_eq!(&list, &bincode_deserialized);
1528            prop_assert_eq!(list, schema_deserialized);
1529        }
1530
1531        #[test]
1532        fn test_linked_list_non_static(list in proptest::collection::linked_list(any::<StructNonStatic>(), 0..=16)) {
1533            let bincode_serialized = bincode::serialize(&list).unwrap();
1534            let schema_serialized = serialize(&list).unwrap();
1535            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1536
1537            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1538            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1539            prop_assert_eq!(&list, &bincode_deserialized);
1540            prop_assert_eq!(list, schema_deserialized);
1541        }
1542
1543        #[test]
1544        fn test_array_bytes(array in any::<[u8; 32]>()) {
1545            let bincode_serialized = bincode::serialize(&array).unwrap();
1546            let schema_serialized = serialize(&array).unwrap();
1547            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1548
1549            let bincode_deserialized: [u8; 32] = bincode::deserialize(&bincode_serialized).unwrap();
1550            let schema_deserialized: [u8; 32] = deserialize(&schema_serialized).unwrap();
1551            prop_assert_eq!(&array, &bincode_deserialized);
1552            prop_assert_eq!(array, schema_deserialized);
1553        }
1554
1555        #[test]
1556        fn test_array_static(array in any::<[u64; 32]>()) {
1557            let bincode_serialized = bincode::serialize(&array).unwrap();
1558            type Target = [u64; 32];
1559            let schema_serialized = Target::serialize(&array).unwrap();
1560            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1561            let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
1562            let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
1563            prop_assert_eq!(&array, &bincode_deserialized);
1564            prop_assert_eq!(array, schema_deserialized);
1565        }
1566
1567        #[test]
1568        fn test_array_non_static(array in any::<[StructNonStatic; 16]>()) {
1569            let bincode_serialized = bincode::serialize(&array).unwrap();
1570            type Target = [StructNonStatic; 16];
1571            let schema_serialized = Target::serialize(&array).unwrap();
1572            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1573            let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
1574            let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
1575            prop_assert_eq!(&array, &bincode_deserialized);
1576            prop_assert_eq!(array, schema_deserialized);
1577        }
1578
1579        #[test]
1580        fn test_option(option in proptest::option::of(any::<StructStatic>())) {
1581            let bincode_serialized = bincode::serialize(&option).unwrap();
1582            let schema_serialized = serialize(&option).unwrap();
1583
1584            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1585            let bincode_deserialized: Option<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1586            let schema_deserialized: Option<StructStatic> = deserialize(&schema_serialized).unwrap();
1587            prop_assert_eq!(&option, &bincode_deserialized);
1588            prop_assert_eq!(&option, &schema_deserialized);
1589        }
1590
1591        #[test]
1592        fn test_option_container(option in proptest::option::of(any::<[u8; 32]>())) {
1593            let bincode_serialized = bincode::serialize(&option).unwrap();
1594            type Target = Option<Pod<[u8; 32]>>;
1595            let schema_serialized = Target::serialize(&option).unwrap();
1596            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1597            let bincode_deserialized: Option<[u8; 32]> = bincode::deserialize(&bincode_serialized).unwrap();
1598            let schema_deserialized: Option<[u8; 32]> = Target::deserialize(&schema_serialized).unwrap();
1599            prop_assert_eq!(&option, &bincode_deserialized);
1600            prop_assert_eq!(&option, &schema_deserialized);
1601        }
1602
1603        #[test]
1604        fn test_bool(val in any::<bool>()) {
1605            let bincode_serialized = bincode::serialize(&val).unwrap();
1606            let schema_serialized = serialize(&val).unwrap();
1607            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1608            let bincode_deserialized: bool = bincode::deserialize(&bincode_serialized).unwrap();
1609            let schema_deserialized: bool = deserialize(&schema_serialized).unwrap();
1610            prop_assert_eq!(val, bincode_deserialized);
1611            prop_assert_eq!(val, schema_deserialized);
1612        }
1613
1614        #[test]
1615        fn test_bool_invalid_bit_pattern(val in 2u8..=255) {
1616            let bincode_deserialized: Result<bool,_> = bincode::deserialize(&[val]);
1617            let schema_deserialized: Result<bool,_> = deserialize(&[val]);
1618            prop_assert!(bincode_deserialized.is_err());
1619            prop_assert!(schema_deserialized.is_err());
1620        }
1621
1622        #[test]
1623        fn test_box(s in any::<StructStatic>()) {
1624            let data = Box::new(s);
1625            let bincode_serialized = bincode::serialize(&data).unwrap();
1626            let schema_serialized = serialize(&data).unwrap();
1627            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1628
1629            let bincode_deserialized: Box<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1630            let schema_deserialized: Box<StructStatic> = deserialize(&schema_serialized).unwrap();
1631            prop_assert_eq!(&data, &bincode_deserialized);
1632            prop_assert_eq!(&data, &schema_deserialized);
1633        }
1634
1635        #[test]
1636        fn test_rc(s in any::<StructStatic>()) {
1637            let data = Rc::new(s);
1638            let bincode_serialized = bincode::serialize(&data).unwrap();
1639            let schema_serialized = serialize(&data).unwrap();
1640            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1641
1642            let bincode_deserialized: Rc<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1643            let schema_deserialized: Rc<StructStatic> = deserialize(&schema_serialized).unwrap();
1644            prop_assert_eq!(&data, &bincode_deserialized);
1645            prop_assert_eq!(&data, &schema_deserialized);
1646        }
1647
1648        #[test]
1649        fn test_arc(s in any::<StructStatic>()) {
1650            let data = Arc::new(s);
1651            let bincode_serialized = bincode::serialize(&data).unwrap();
1652            let schema_serialized = serialize(&data).unwrap();
1653            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1654
1655            let bincode_deserialized: Arc<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1656            let schema_deserialized: Arc<StructStatic> = deserialize(&schema_serialized).unwrap();
1657            prop_assert_eq!(&data, &bincode_deserialized);
1658            prop_assert_eq!(&data, &schema_deserialized);
1659        }
1660
1661        #[test]
1662        fn test_boxed_slice_zero_copy(vec in proptest::collection::vec(any::<StructZeroCopy>(), 0..=100)) {
1663            let data = vec.into_boxed_slice();
1664            let bincode_serialized = bincode::serialize(&data).unwrap();
1665            let schema_serialized = serialize(&data).unwrap();
1666            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1667
1668            let bincode_deserialized: Box<[StructZeroCopy]> = bincode::deserialize(&bincode_serialized).unwrap();
1669            let schema_deserialized: Box<[StructZeroCopy]> = deserialize(&schema_serialized).unwrap();
1670            prop_assert_eq!(&data, &bincode_deserialized);
1671            prop_assert_eq!(&data, &schema_deserialized);
1672        }
1673
1674        #[test]
1675        fn test_boxed_slice_static(vec in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
1676            let data = vec.into_boxed_slice();
1677            let bincode_serialized = bincode::serialize(&data).unwrap();
1678            let schema_serialized = serialize(&data).unwrap();
1679            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1680
1681            let bincode_deserialized: Box<[StructStatic]> = bincode::deserialize(&bincode_serialized).unwrap();
1682            let schema_deserialized: Box<[StructStatic]> = deserialize(&schema_serialized).unwrap();
1683            prop_assert_eq!(&data, &bincode_deserialized);
1684            prop_assert_eq!(&data, &schema_deserialized);
1685        }
1686
1687        #[test]
1688        fn test_boxed_slice_non_static(vec in proptest::collection::vec(any::<StructNonStatic>(), 0..=16)) {
1689            let data = vec.into_boxed_slice();
1690            let bincode_serialized = bincode::serialize(&data).unwrap();
1691            type Target = Box<[StructNonStatic]>;
1692            let schema_serialized = serialize(&data).unwrap();
1693            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1694
1695            let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
1696            let schema_deserialized: Target = Target::deserialize(&schema_serialized).unwrap();
1697            prop_assert_eq!(&data, &bincode_deserialized);
1698            prop_assert_eq!(&data, &schema_deserialized);
1699        }
1700
1701        #[test]
1702        fn test_integers(
1703            val in (
1704                any::<u8>(),
1705                any::<i8>(),
1706                any::<u16>(),
1707                any::<i16>(),
1708                any::<u32>(),
1709                any::<i32>(),
1710                any::<usize>(),
1711                any::<isize>(),
1712                any::<u64>(),
1713                any::<i64>(),
1714                any::<u128>(),
1715                any::<i128>()
1716            )
1717        ) {
1718            type Target = (u8, i8, u16, i16, u32, i32, usize, isize, u64, i64, u128, i128);
1719            let bincode_serialized = bincode::serialize(&val).unwrap();
1720            let schema_serialized = serialize(&val).unwrap();
1721            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1722            let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
1723            let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
1724            prop_assert_eq!(val, bincode_deserialized);
1725            prop_assert_eq!(val, schema_deserialized);
1726        }
1727
1728        #[test]
1729        fn test_tuple_zero_copy(
1730            tuple in (
1731                any::<StructZeroCopy>(),
1732                any::<[u8; 32]>(),
1733            )
1734        ) {
1735            let bincode_serialized = bincode::serialize(&tuple).unwrap();
1736            let schema_serialized = serialize(&tuple).unwrap();
1737
1738            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1739            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1740            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1741            prop_assert_eq!(&tuple, &bincode_deserialized);
1742            prop_assert_eq!(&tuple, &schema_deserialized);
1743
1744        }
1745
1746        #[test]
1747        fn test_tuple_static(
1748            tuple in (
1749                any::<StructStatic>(),
1750                any::<[u8; 32]>(),
1751            )
1752        ) {
1753            let bincode_serialized = bincode::serialize(&tuple).unwrap();
1754            let schema_serialized = serialize(&tuple).unwrap();
1755
1756            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1757            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1758            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1759            prop_assert_eq!(&tuple, &bincode_deserialized);
1760            prop_assert_eq!(&tuple, &schema_deserialized);
1761
1762        }
1763
1764        #[test]
1765        fn test_tuple_non_static(
1766            tuple in (
1767                any::<StructNonStatic>(),
1768                any::<[u8; 32]>(),
1769                proptest::collection::vec(any::<StructStatic>(), 0..=100),
1770            )
1771        ) {
1772            let bincode_serialized = bincode::serialize(&tuple).unwrap();
1773            type BincodeTarget = (StructNonStatic, [u8; 32], Vec<StructStatic>);
1774            type Target = (StructNonStatic, Pod<[u8; 32]>, Vec<StructStatic>);
1775            let schema_serialized = Target::serialize(&tuple).unwrap();
1776
1777            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1778            let bincode_deserialized: BincodeTarget = bincode::deserialize(&bincode_serialized).unwrap();
1779            let schema_deserialized = Target::deserialize(&schema_serialized).unwrap();
1780            prop_assert_eq!(&tuple, &bincode_deserialized);
1781            prop_assert_eq!(&tuple, &schema_deserialized);
1782
1783        }
1784
1785        #[test]
1786        fn test_str(str in any::<String>()) {
1787            let bincode_serialized = bincode::serialize(&str).unwrap();
1788            let schema_serialized = serialize(&str).unwrap();
1789            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1790            let bincode_deserialized: &str = bincode::deserialize(&bincode_serialized).unwrap();
1791            let schema_deserialized: &str = deserialize(&schema_serialized).unwrap();
1792            prop_assert_eq!(&str, &bincode_deserialized);
1793            prop_assert_eq!(&str, &schema_deserialized);
1794
1795            let bincode_deserialized: String = bincode::deserialize(&bincode_serialized).unwrap();
1796            let schema_deserialized: String = deserialize(&schema_serialized).unwrap();
1797            prop_assert_eq!(&str, &bincode_deserialized);
1798            prop_assert_eq!(&str, &schema_deserialized);
1799        }
1800
1801        #[test]
1802        fn test_struct_zero_copy(val in any::<StructZeroCopy>()) {
1803            let bincode_serialized = bincode::serialize(&val).unwrap();
1804            let schema_serialized = serialize(&val).unwrap();
1805            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1806
1807            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1808            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1809            prop_assert_eq!(&val, &bincode_deserialized);
1810            prop_assert_eq!(&val, &schema_deserialized);
1811        }
1812
1813        #[test]
1814        fn test_struct_static(val in any::<StructStatic>()) {
1815            let bincode_serialized = bincode::serialize(&val).unwrap();
1816            let schema_serialized = serialize(&val).unwrap();
1817            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1818
1819            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1820            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1821            prop_assert_eq!(&val, &bincode_deserialized);
1822            prop_assert_eq!(&val, &schema_deserialized);
1823        }
1824
1825        #[test]
1826        fn test_struct_non_static(val in any::<StructNonStatic>()) {
1827            let bincode_serialized = bincode::serialize(&val).unwrap();
1828            let schema_serialized = serialize(&val).unwrap();
1829            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1830
1831            let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1832            let schema_deserialized = deserialize(&schema_serialized).unwrap();
1833            prop_assert_eq!(&val, &bincode_deserialized);
1834            prop_assert_eq!(&val, &schema_deserialized);
1835        }
1836
1837        #[test]
1838        fn test_floats(
1839            val in (
1840                any::<f32>(),
1841                any::<f64>(),
1842            )
1843        ) {
1844            let bincode_serialized = bincode::serialize(&val).unwrap();
1845            let schema_serialized = serialize(&val).unwrap();
1846            prop_assert_eq!(&bincode_serialized, &schema_serialized);
1847
1848            let bincode_deserialized: (f32, f64) = bincode::deserialize(&bincode_serialized).unwrap();
1849            let schema_deserialized: (f32, f64) = deserialize(&schema_serialized).unwrap();
1850            prop_assert_eq!(val, bincode_deserialized);
1851            prop_assert_eq!(val, schema_deserialized);
1852        }
1853    }
1854
1855    #[test]
1856    fn test_result_basic() {
1857        proptest!(proptest_cfg(), |(value: Result<u64, String>)| {
1858            let wincode_serialized = serialize(&value).unwrap();
1859            let bincode_serialized = bincode::serialize(&value).unwrap();
1860            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
1861
1862            let wincode_deserialized: Result<u64, String> = deserialize(&wincode_serialized).unwrap();
1863            let bincode_deserialized: Result<u64, String> = bincode::deserialize(&bincode_serialized).unwrap();
1864            prop_assert_eq!(&value, &wincode_deserialized);
1865            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
1866        });
1867    }
1868
1869    #[test]
1870    fn test_result_bincode_equivalence() {
1871        use serde::{Deserialize, Serialize};
1872
1873        #[derive(
1874            Serialize,
1875            Deserialize,
1876            Debug,
1877            PartialEq,
1878            Clone,
1879            proptest_derive::Arbitrary,
1880            SchemaWrite,
1881            SchemaRead,
1882        )]
1883        #[wincode(internal)]
1884        enum Error {
1885            NotFound,
1886            InvalidInput(String),
1887            Other(u32),
1888        }
1889
1890        proptest!(proptest_cfg(), |(value: Result<Vec<u8>, Error>)| {
1891            let wincode_serialized = serialize(&value).unwrap();
1892            let bincode_serialized = bincode::serialize(&value).unwrap();
1893            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
1894
1895            let wincode_deserialized: Result<Vec<u8>, Error> = deserialize(&wincode_serialized).unwrap();
1896            let bincode_deserialized: Result<Vec<u8>, Error> = bincode::deserialize(&bincode_serialized).unwrap();
1897            prop_assert_eq!(&value, &wincode_deserialized);
1898            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
1899        });
1900    }
1901
1902    #[test]
1903    fn test_result_nested() {
1904        proptest!(proptest_cfg(), |(value: Result<Result<u64, String>, u32>)| {
1905            let wincode_serialized = serialize(&value).unwrap();
1906            let bincode_serialized = bincode::serialize(&value).unwrap();
1907            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
1908
1909            let wincode_deserialized: Result<Result<u64, String>, u32> = deserialize(&wincode_serialized).unwrap();
1910            let bincode_deserialized: Result<Result<u64, String>, u32> = bincode::deserialize(&bincode_serialized).unwrap();
1911            prop_assert_eq!(&value, &wincode_deserialized);
1912            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
1913        });
1914    }
1915
1916    #[test]
1917    fn test_result_with_complex_types() {
1918        use std::collections::HashMap;
1919
1920        proptest!(proptest_cfg(), |(value: Result<HashMap<String, Vec<u32>>, bool>)| {
1921            let wincode_serialized = serialize(&value).unwrap();
1922            let bincode_serialized = bincode::serialize(&value).unwrap();
1923            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
1924
1925            let wincode_deserialized: Result<HashMap<String, Vec<u32>>, bool> = deserialize(&wincode_serialized).unwrap();
1926            let bincode_deserialized: Result<HashMap<String, Vec<u32>>, bool> = bincode::deserialize(&bincode_serialized).unwrap();
1927            prop_assert_eq!(&value, &wincode_deserialized);
1928            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
1929        });
1930    }
1931
1932    #[test]
1933    fn test_result_type_meta_static() {
1934        // Result<u64, u64> should be TypeMeta::Static because both T and E are Static with equal sizes
1935        assert!(matches!(
1936            <Result<u64, u64> as SchemaRead>::TYPE_META,
1937            TypeMeta::Static {
1938                size: 12,
1939                zero_copy: false
1940            }
1941        ));
1942
1943        proptest!(proptest_cfg(), |(value: Result<u64, u64>)| {
1944            let wincode_serialized = serialize(&value).unwrap();
1945            let bincode_serialized = bincode::serialize(&value).unwrap();
1946            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
1947
1948            let wincode_deserialized: Result<u64, u64> = deserialize(&wincode_serialized).unwrap();
1949            let bincode_deserialized: Result<u64, u64> = bincode::deserialize(&bincode_serialized).unwrap();
1950            prop_assert_eq!(&value, &wincode_deserialized);
1951            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
1952        });
1953    }
1954
1955    #[test]
1956    fn test_result_type_meta_dynamic() {
1957        // Result<u64, String> should be TypeMeta::Dynamic because String is Dynamic
1958        assert!(matches!(
1959            <Result<u64, String> as SchemaRead>::TYPE_META,
1960            TypeMeta::Dynamic
1961        ));
1962
1963        proptest!(proptest_cfg(), |(value: Result<u64, String>)| {
1964            let wincode_serialized = serialize(&value).unwrap();
1965            let bincode_serialized = bincode::serialize(&value).unwrap();
1966            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
1967
1968            let wincode_deserialized: Result<u64, String> = deserialize(&wincode_serialized).unwrap();
1969            let bincode_deserialized: Result<u64, String> = bincode::deserialize(&bincode_serialized).unwrap();
1970            prop_assert_eq!(&value, &wincode_deserialized);
1971            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
1972        });
1973    }
1974
1975    #[test]
1976    fn test_result_type_meta_different_sizes() {
1977        // Result<u64, u32> should be TypeMeta::Dynamic because T and E have different sizes
1978        assert!(matches!(
1979            <Result<u64, u32> as SchemaRead>::TYPE_META,
1980            TypeMeta::Dynamic
1981        ));
1982
1983        proptest!(proptest_cfg(), |(value: Result<u64, u32>)| {
1984            let wincode_serialized = serialize(&value).unwrap();
1985            let bincode_serialized = bincode::serialize(&value).unwrap();
1986            prop_assert_eq!(&wincode_serialized, &bincode_serialized);
1987
1988            let wincode_deserialized: Result<u64, u32> = deserialize(&wincode_serialized).unwrap();
1989            let bincode_deserialized: Result<u64, u32> = bincode::deserialize(&bincode_serialized).unwrap();
1990            prop_assert_eq!(&value, &wincode_deserialized);
1991            prop_assert_eq!(wincode_deserialized, bincode_deserialized);
1992        });
1993    }
1994}