1use {
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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum TypeMeta {
60 Static {
71 size: usize,
73 zero_copy: bool,
80 },
81 Dynamic,
83}
84
85impl TypeMeta {
86 #[inline(always)]
87 pub(crate) const fn size_assert_zero_copy(self) -> usize {
88 match self {
89 TypeMeta::Static {
90 size,
91 zero_copy: true,
92 } => size,
93 _ => panic!("Type is not zero-copy"),
94 }
95 }
96}
97
98pub trait SchemaWrite {
100 type Src: ?Sized;
101
102 const TYPE_META: TypeMeta = TypeMeta::Dynamic;
103
104 fn size_of(src: &Self::Src) -> WriteResult<usize>;
106 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()>;
108}
109
110pub trait SchemaRead<'de> {
112 type Dst;
113
114 const TYPE_META: TypeMeta = TypeMeta::Dynamic;
115
116 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()>;
122
123 #[inline(always)]
125 fn get(reader: &mut impl Reader<'de>) -> ReadResult<Self::Dst> {
126 let mut value = MaybeUninit::uninit();
127 Self::read(reader, &mut value)?;
128 Ok(unsafe { value.assume_init() })
130 }
131}
132
133pub unsafe trait ZeroCopy: 'static {
145 #[inline(always)]
169 fn from_bytes<'de>(mut bytes: &'de [u8]) -> ReadResult<&'de Self>
170 where
171 Self: SchemaRead<'de, Dst = Self> + Sized,
172 {
173 <&Self as SchemaRead<'de>>::get(&mut bytes)
174 }
175
176 #[inline(always)]
203 fn from_bytes_mut<'de>(mut bytes: &'de mut [u8]) -> ReadResult<&'de mut Self>
204 where
205 Self: SchemaRead<'de, Dst = Self> + Sized,
206 {
207 <&mut Self as SchemaRead<'de>>::get(&mut bytes)
208 }
209}
210
211pub trait SchemaReadOwned: for<'de> SchemaRead<'de> {}
213impl<T> SchemaReadOwned for T where T: for<'de> SchemaRead<'de> {}
214
215#[inline(always)]
216#[allow(clippy::arithmetic_side_effects)]
217fn size_of_elem_iter<'a, T, Len>(
218 value: impl ExactSizeIterator<Item = &'a T::Src>,
219) -> WriteResult<usize>
220where
221 Len: SeqLen,
222 T: SchemaWrite + 'a,
223{
224 if let TypeMeta::Static { size, .. } = T::TYPE_META {
225 return Ok(Len::write_bytes_needed(value.len())? + size * value.len());
226 }
227 Ok(Len::write_bytes_needed(value.len())?
229 + (value
230 .map(T::size_of)
231 .try_fold(0usize, |acc, x| x.map(|x| acc + x))?))
232}
233
234#[inline(always)]
235#[allow(clippy::arithmetic_side_effects)]
236fn size_of_elem_slice<T, Len>(value: &[T::Src]) -> WriteResult<usize>
239where
240 Len: SeqLen,
241 T: SchemaWrite,
242 T::Src: Sized,
243{
244 size_of_elem_iter::<T, Len>(value.iter())
245}
246
247#[inline(always)]
248fn write_elem_iter<'a, T, Len>(
249 writer: &mut impl Writer,
250 src: impl ExactSizeIterator<Item = &'a T::Src>,
251) -> WriteResult<()>
252where
253 Len: SeqLen,
254 T: SchemaWrite + 'a,
255{
256 if let TypeMeta::Static { size, .. } = T::TYPE_META {
257 #[allow(clippy::arithmetic_side_effects)]
258 let needed = Len::write_bytes_needed(src.len())? + size * src.len();
259 let mut writer = unsafe { writer.as_trusted_for(needed) }?;
263 Len::write(&mut writer, src.len())?;
264 for item in src {
265 T::write(&mut writer, item)?;
266 }
267 writer.finish()?;
268 return Ok(());
269 }
270
271 Len::write(writer, src.len())?;
272 for item in src {
273 T::write(writer, item)?;
274 }
275 Ok(())
276}
277
278#[inline(always)]
279#[allow(clippy::arithmetic_side_effects)]
280fn write_elem_slice<T, Len>(writer: &mut impl Writer, src: &[T::Src]) -> WriteResult<()>
283where
284 Len: SeqLen,
285 T: SchemaWrite,
286 T::Src: Sized,
287{
288 if let TypeMeta::Static {
289 size,
290 zero_copy: true,
291 } = T::TYPE_META
292 {
293 let needed = Len::write_bytes_needed(src.len())? + src.len() * size;
294 let writer = &mut unsafe { writer.as_trusted_for(needed) }?;
298 Len::write(writer, src.len())?;
299 unsafe { writer.write_slice_t(src)? };
301 writer.finish()?;
302 return Ok(());
303 }
304 write_elem_iter::<T, Len>(writer, src.iter())
305}
306
307#[cfg(all(test, feature = "std", feature = "derive"))]
308mod tests {
309 #![allow(clippy::arithmetic_side_effects, deprecated)]
310
311 use {
312 crate::{
313 containers::{self, Elem, Pod},
314 deserialize, deserialize_mut,
315 error::{self, invalid_tag_encoding},
316 io::{Reader, Writer},
317 proptest_config::proptest_cfg,
318 serialize, Deserialize, ReadResult, SchemaRead, SchemaWrite, Serialize, TypeMeta,
319 WriteResult, ZeroCopy,
320 },
321 core::{marker::PhantomData, ptr},
322 proptest::prelude::*,
323 std::{
324 cell::Cell,
325 collections::{BinaryHeap, VecDeque},
326 mem::MaybeUninit,
327 ops::{Deref, DerefMut},
328 rc::Rc,
329 result::Result,
330 sync::Arc,
331 },
332 };
333
334 #[cfg(target_endian = "little")]
335 #[derive(
336 serde::Serialize,
337 serde::Deserialize,
338 Debug,
339 PartialEq,
340 Eq,
341 Ord,
342 PartialOrd,
343 SchemaWrite,
344 SchemaRead,
345 proptest_derive::Arbitrary,
346 Hash,
347 Clone,
348 Copy,
349 )]
350 #[wincode(internal)]
351 #[repr(C)]
352 struct StructZeroCopy {
353 a: u128,
354 b: i128,
355 c: u64,
356 d: i64,
357 e: u32,
358 f: i32,
359 ar1: [u8; 8],
360 g: u16,
361 h: i16,
362 ar2: [u8; 12],
363 i: u8,
364 j: i8,
365 ar3: [u8; 14],
366 }
367
368 #[cfg(not(target_endian = "little"))]
369 #[derive(
370 serde::Serialize,
371 serde::Deserialize,
372 Debug,
373 PartialEq,
374 Eq,
375 Ord,
376 PartialOrd,
377 SchemaWrite,
378 SchemaRead,
379 proptest_derive::Arbitrary,
380 Hash,
381 Clone,
382 Copy,
383 )]
384 #[wincode(internal)]
385 #[repr(C)]
386 struct StructZeroCopy {
387 byte: u8,
388 ar: [u8; 32],
389 }
390
391 #[derive(
392 serde::Serialize,
393 serde::Deserialize,
394 Debug,
395 PartialEq,
396 Eq,
397 Ord,
398 PartialOrd,
399 SchemaWrite,
400 SchemaRead,
401 proptest_derive::Arbitrary,
402 Hash,
403 )]
404 #[wincode(internal)]
405 struct StructStatic {
406 a: u64,
407 b: bool,
408 e: [u8; 32],
409 }
410
411 #[derive(
412 serde::Serialize,
413 serde::Deserialize,
414 Debug,
415 PartialEq,
416 Eq,
417 Ord,
418 PartialOrd,
419 SchemaWrite,
420 SchemaRead,
421 proptest_derive::Arbitrary,
422 Hash,
423 )]
424 #[wincode(internal)]
425 struct StructNonStatic {
426 a: u64,
427 b: bool,
428 e: String,
429 }
430
431 #[test]
432 fn struct_zero_copy_derive_size() {
433 #[cfg(target_endian = "little")]
434 let size = size_of::<u128>()
435 + size_of::<i128>()
436 + size_of::<u64>()
437 + size_of::<i64>()
438 + size_of::<u32>()
439 + size_of::<i32>()
440 + size_of::<[u8; 8]>()
441 + size_of::<u16>()
442 + size_of::<i16>()
443 + size_of::<[u8; 12]>()
444 + size_of::<u8>()
445 + size_of::<i8>()
446 + size_of::<[u8; 14]>();
447 #[cfg(not(target_endian = "little"))]
448 let size = size_of::<u8>() + size_of::<[u8; 32]>();
449 let expected = TypeMeta::Static {
450 size,
451 zero_copy: true,
452 };
453 assert_eq!(<StructZeroCopy as SchemaWrite>::TYPE_META, expected);
454 assert_eq!(<StructZeroCopy as SchemaRead<'_>>::TYPE_META, expected);
455 }
456
457 #[test]
458 fn struct_zero_copy_transparent_derive_size() {
459 #[derive(SchemaWrite, SchemaRead)]
460 #[wincode(internal)]
461 #[repr(transparent)]
462 struct Address([u8; 32]);
463
464 let expected = TypeMeta::Static {
465 size: size_of::<[u8; 32]>(),
466 zero_copy: true,
467 };
468 assert_eq!(<Address as SchemaWrite>::TYPE_META, expected);
469 assert_eq!(<Address as SchemaRead<'_>>::TYPE_META, expected);
470 }
471
472 #[test]
473 fn struct_static_derive_size() {
474 let expected = TypeMeta::Static {
475 size: size_of::<u64>() + size_of::<bool>() + size_of::<[u8; 32]>(),
476 zero_copy: false,
477 };
478 assert_eq!(<StructStatic as SchemaWrite>::TYPE_META, expected);
479 assert_eq!(<StructStatic as SchemaRead<'_>>::TYPE_META, expected);
480 }
481
482 #[test]
483 fn struct_non_static_derive_size() {
484 let expected = TypeMeta::Dynamic;
485 assert_eq!(<StructNonStatic as SchemaWrite>::TYPE_META, expected);
486 assert_eq!(<StructNonStatic as SchemaRead<'_>>::TYPE_META, expected);
487 }
488
489 thread_local! {
490 static TL_DROP_COUNT: Cell<isize> = const { Cell::new(0) };
492 }
493
494 fn get_tl_drop_count() -> isize {
495 TL_DROP_COUNT.with(|cell| cell.get())
496 }
497
498 fn tl_drop_count_inc() {
499 TL_DROP_COUNT.with(|cell| cell.set(cell.get() + 1));
500 }
501
502 fn tl_drop_count_dec() {
503 TL_DROP_COUNT.with(|cell| cell.set(cell.get() - 1));
504 }
505
506 fn tl_drop_count_reset() {
507 TL_DROP_COUNT.with(|cell| cell.set(0));
508 }
509
510 #[must_use]
511 #[derive(Debug)]
512 struct TLDropGuard;
514
515 impl TLDropGuard {
516 fn new() -> Self {
517 assert_eq!(
518 get_tl_drop_count(),
519 0,
520 "TL counter drifted from zero -- another test may have leaked"
521 );
522 Self
523 }
524 }
525
526 impl Drop for TLDropGuard {
527 #[track_caller]
528 fn drop(&mut self) {
529 let v = get_tl_drop_count();
530 if !std::thread::panicking() {
531 assert_eq!(
532 v, 0,
533 "TL counter drifted from zero -- this test might have leaked"
534 );
535 }
536 tl_drop_count_reset();
537 }
538 }
539
540 #[derive(Debug, PartialEq, Eq)]
541 struct DropCounted;
543
544 impl Arbitrary for DropCounted {
545 type Parameters = ();
546 type Strategy = Just<Self>;
547 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
548 Just(Self::new())
549 }
550 }
551
552 impl DropCounted {
553 const TAG_BYTE: u8 = 0;
554
555 fn new() -> Self {
556 tl_drop_count_inc();
557 Self
558 }
559 }
560
561 impl Clone for DropCounted {
562 fn clone(&self) -> Self {
563 tl_drop_count_inc();
564 Self
565 }
566 }
567
568 impl Drop for DropCounted {
569 fn drop(&mut self) {
570 tl_drop_count_dec();
571 }
572 }
573
574 impl SchemaWrite for DropCounted {
575 type Src = Self;
576
577 const TYPE_META: TypeMeta = TypeMeta::Static {
578 size: 1,
579 zero_copy: false,
580 };
581
582 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
583 Ok(1)
584 }
585 fn write(writer: &mut impl Writer, _src: &Self::Src) -> WriteResult<()> {
586 u8::write(writer, &Self::TAG_BYTE)?;
587 Ok(())
588 }
589 }
590
591 impl<'de> SchemaRead<'de> for DropCounted {
592 type Dst = Self;
593
594 const TYPE_META: TypeMeta = TypeMeta::Static {
595 size: 1,
596 zero_copy: false,
597 };
598
599 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
600 reader.consume(1)?;
601 dst.write(DropCounted::new());
603 Ok(())
604 }
605 }
606
607 #[derive(Debug, Clone, Copy, PartialEq, Eq, proptest_derive::Arbitrary)]
609 struct ErrorsOnRead;
610
611 impl ErrorsOnRead {
612 const TAG_BYTE: u8 = 1;
613 }
614
615 impl SchemaWrite for ErrorsOnRead {
616 type Src = Self;
617
618 const TYPE_META: TypeMeta = TypeMeta::Static {
619 size: 1,
620 zero_copy: false,
621 };
622
623 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
624 Ok(1)
625 }
626
627 fn write(writer: &mut impl Writer, _src: &Self::Src) -> WriteResult<()> {
628 u8::write(writer, &Self::TAG_BYTE)
629 }
630 }
631
632 impl<'de> SchemaRead<'de> for ErrorsOnRead {
633 type Dst = Self;
634
635 const TYPE_META: TypeMeta = TypeMeta::Static {
636 size: 1,
637 zero_copy: false,
638 };
639
640 fn read(
641 reader: &mut impl Reader<'de>,
642 _dst: &mut MaybeUninit<Self::Dst>,
643 ) -> ReadResult<()> {
644 reader.consume(1)?;
645 Err(error::ReadError::PointerSizedReadError)
646 }
647 }
648
649 #[derive(Debug, Clone, PartialEq, Eq, proptest_derive::Arbitrary)]
650 enum DropCountedMaybeError {
651 DropCounted(DropCounted),
652 ErrorsOnRead(ErrorsOnRead),
653 }
654
655 impl SchemaWrite for DropCountedMaybeError {
656 type Src = Self;
657
658 const TYPE_META: TypeMeta = TypeMeta::Static {
659 size: 1,
660 zero_copy: false,
661 };
662
663 fn size_of(src: &Self::Src) -> WriteResult<usize> {
664 match src {
665 DropCountedMaybeError::DropCounted(v) => DropCounted::size_of(v),
666 DropCountedMaybeError::ErrorsOnRead(v) => ErrorsOnRead::size_of(v),
667 }
668 }
669
670 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
671 match src {
672 DropCountedMaybeError::DropCounted(v) => DropCounted::write(writer, v),
673 DropCountedMaybeError::ErrorsOnRead(v) => ErrorsOnRead::write(writer, v),
674 }
675 }
676 }
677
678 impl<'de> SchemaRead<'de> for DropCountedMaybeError {
679 type Dst = Self;
680
681 const TYPE_META: TypeMeta = TypeMeta::Static {
682 size: 1,
683 zero_copy: false,
684 };
685
686 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
687 let byte = u8::get(reader)?;
688 match byte {
689 DropCounted::TAG_BYTE => {
690 dst.write(DropCountedMaybeError::DropCounted(DropCounted::new()));
691 Ok(())
692 }
693 ErrorsOnRead::TAG_BYTE => Err(error::ReadError::PointerSizedReadError),
694 _ => Err(invalid_tag_encoding(byte as usize)),
695 }
696 }
697 }
698
699 #[test]
700 fn drop_count_sanity() {
701 let _guard = TLDropGuard::new();
702 let serialized = { serialize(&[DropCounted::new(), DropCounted::new()]).unwrap() };
704 let _deserialized: [DropCounted; 2] = deserialize(&serialized).unwrap();
705 assert_eq!(get_tl_drop_count(), 2);
706 }
707
708 #[test]
709 fn drop_count_maybe_error_sanity() {
710 let _guard = TLDropGuard::new();
711 let serialized =
712 { serialize(&[DropCountedMaybeError::DropCounted(DropCounted::new())]).unwrap() };
713 let _deserialized: [DropCountedMaybeError; 1] = deserialize(&serialized).unwrap();
714 assert_eq!(get_tl_drop_count(), 1);
715
716 let serialized = {
717 serialize(&[
718 DropCountedMaybeError::DropCounted(DropCounted::new()),
719 DropCountedMaybeError::ErrorsOnRead(ErrorsOnRead),
720 ])
721 .unwrap()
722 };
723 let _deserialized: ReadResult<[DropCountedMaybeError; 2]> = deserialize(&serialized);
724 }
725
726 #[test]
728 fn test_struct_derive_handles_partial_drop() {
729 #[derive(SchemaWrite, SchemaRead, proptest_derive::Arbitrary, Debug, PartialEq, Eq)]
732 #[wincode(internal)]
733 struct CouldLeak {
734 data: DropCountedMaybeError,
735 data2: DropCountedMaybeError,
736 data3: DropCountedMaybeError,
737 }
738
739 let _guard = TLDropGuard::new();
740 proptest!(proptest_cfg(), |(could_leak: CouldLeak)| {
741 let serialized = serialize(&could_leak).unwrap();
742 let deserialized = CouldLeak::deserialize(&serialized);
743 if let Ok(deserialized) = deserialized {
744 prop_assert_eq!(could_leak, deserialized);
745 }
746 });
747 }
748
749 #[test]
751 fn test_vec_of_references_borrows_from_input() {
752 #[derive(
753 SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary, Clone, Copy,
754 )]
755 #[wincode(internal)]
756 #[repr(transparent)]
757 struct BigBytes([u8; 512]);
758 proptest!(proptest_cfg(), |(vec in proptest::collection::vec(any::<BigBytes>(), 0..=8))| {
759 let bytes = serialize(&vec).unwrap();
761 let borrowed: Vec<&BigBytes> = deserialize(&bytes).unwrap();
762
763 prop_assert_eq!(borrowed.len(), vec.len());
764 let start = bytes.as_ptr().addr();
765 let end = start + bytes.len();
766 for (i, r) in borrowed.iter().enumerate() {
767 prop_assert_eq!(**r, vec[i]);
769 let p = ptr::from_ref(*r).addr();
771 prop_assert!(p >= start && p < end);
772 }
773 });
774 }
775
776 #[test]
778 fn test_boxed_slice_of_references_borrows_from_input() {
779 #[derive(
780 SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary, Clone, Copy,
781 )]
782 #[wincode(internal)]
783 #[repr(transparent)]
784 struct BigBytes([u8; 512]);
785 proptest!(proptest_cfg(), |(vec in proptest::collection::vec(any::<BigBytes>(), 0..=8))| {
786 let boxed: Box<[BigBytes]> = vec.into_boxed_slice();
787 let bytes = serialize(&boxed).unwrap();
788 let borrowed: Box<[&BigBytes]> = deserialize(&bytes).unwrap();
789
790 prop_assert_eq!(borrowed.len(), boxed.len());
791 let start = bytes.as_ptr().addr();
792 let end = start + bytes.len();
793 for (i, &r) in borrowed.iter().enumerate() {
794 prop_assert_eq!(*r, boxed[i]);
795 let p = ptr::from_ref(r).addr();
796 prop_assert!(p >= start && p < end);
797 }
798 });
799 }
800
801 #[test]
803 fn test_enum_derive_handles_partial_drop() {
804 #[derive(SchemaWrite, SchemaRead, proptest_derive::Arbitrary, Debug, PartialEq, Eq)]
807 #[wincode(internal)]
808 enum CouldLeak {
809 A {
810 a: DropCountedMaybeError,
811 b: DropCountedMaybeError,
812 },
813 B(
814 DropCountedMaybeError,
815 DropCountedMaybeError,
816 DropCountedMaybeError,
817 ),
818 C(DropCountedMaybeError),
819 D,
820 }
821
822 let _guard = TLDropGuard::new();
823 proptest!(proptest_cfg(), |(could_leak: CouldLeak)| {
824 let serialized = serialize(&could_leak).unwrap();
825 let deserialized = CouldLeak::deserialize(&serialized);
826 if let Ok(deserialized) = deserialized {
827 prop_assert_eq!(could_leak, deserialized);
828 }
829 });
830 }
831
832 #[test]
833 fn test_tuple_handles_partial_drop() {
834 let _guard = TLDropGuard::new();
835 let serialized =
836 { serialize(&(DropCounted::new(), DropCounted::new(), ErrorsOnRead)).unwrap() };
837 let deserialized = <(DropCounted, DropCounted, ErrorsOnRead)>::deserialize(&serialized);
838 assert!(deserialized.is_err());
839 }
840
841 #[test]
842 fn test_vec_handles_partial_drop() {
843 let _guard = TLDropGuard::new();
844 proptest!(proptest_cfg(), |(vec in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100))| {
845 let serialized = serialize(&vec).unwrap();
846 let deserialized = <Vec<DropCountedMaybeError>>::deserialize(&serialized);
847 if let Ok(deserialized) = deserialized {
848 prop_assert_eq!(vec, deserialized);
849 }
850 });
851 }
852
853 #[test]
854 fn test_vec_deque_handles_partial_drop() {
855 let _guard = TLDropGuard::new();
856 proptest!(proptest_cfg(), |(vec in proptest::collection::vec_deque(any::<DropCountedMaybeError>(), 0..100))| {
857 let serialized = serialize(&vec).unwrap();
858 let deserialized = <VecDeque<DropCountedMaybeError>>::deserialize(&serialized);
859 if let Ok(deserialized) = deserialized {
860 prop_assert_eq!(vec, deserialized);
861 }
862 });
863 }
864
865 #[test]
866 fn test_boxed_slice_handles_partial_drop() {
867 let _guard = TLDropGuard::new();
868 proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(|vec| vec.into_boxed_slice()))| {
869 let serialized = serialize(&slice).unwrap();
870 let deserialized = <Box<[DropCountedMaybeError]>>::deserialize(&serialized);
871 if let Ok(deserialized) = deserialized {
872 prop_assert_eq!(slice, deserialized);
873 }
874 });
875 }
876
877 #[test]
878 fn test_rc_slice_handles_partial_drop() {
879 let _guard = TLDropGuard::new();
880 proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(Rc::from))| {
881 let serialized = serialize(&slice).unwrap();
882 let deserialized = <Rc<[DropCountedMaybeError]>>::deserialize(&serialized);
883 if let Ok(deserialized) = deserialized {
884 prop_assert_eq!(slice, deserialized);
885 }
886 });
887 }
888
889 #[test]
890 fn test_arc_slice_handles_partial_drop() {
891 let _guard = TLDropGuard::new();
892 proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<DropCountedMaybeError>(), 0..100).prop_map(Arc::from))| {
893 let serialized = serialize(&slice).unwrap();
894 let deserialized = <Arc<[DropCountedMaybeError]>>::deserialize(&serialized);
895 if let Ok(deserialized) = deserialized {
896 prop_assert_eq!(slice, deserialized);
897 }
898 });
899 }
900
901 #[test]
902 fn test_arc_handles_drop() {
903 let _guard = TLDropGuard::new();
904 proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Rc::from))| {
905 let serialized = serialize(&data).unwrap();
906 let deserialized = deserialize(&serialized);
907 if let Ok(deserialized) = deserialized {
908 prop_assert_eq!(data, deserialized);
909 }
910 });
911 }
912
913 #[test]
914 fn test_rc_handles_drop() {
915 let _guard = TLDropGuard::new();
916 proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Rc::from))| {
917 let serialized = serialize(&data).unwrap();
918 let deserialized = deserialize(&serialized);
919 if let Ok(deserialized) = deserialized {
920 prop_assert_eq!(data, deserialized);
921 }
922 });
923 }
924
925 #[test]
926 fn test_box_handles_drop() {
927 let _guard = TLDropGuard::new();
928 proptest!(proptest_cfg(), |(data in any::<DropCountedMaybeError>().prop_map(Box::new))| {
929 let serialized = serialize(&data).unwrap();
930 let deserialized = deserialize(&serialized);
931 if let Ok(deserialized) = deserialized {
932 prop_assert_eq!(data, deserialized);
933 }
934 });
935 }
936
937 #[test]
938 fn test_array_handles_partial_drop() {
939 let _guard = TLDropGuard::new();
940
941 proptest!(proptest_cfg(), |(array in proptest::array::uniform32(any::<DropCountedMaybeError>()))| {
942 let serialized = serialize(&array).unwrap();
943 let deserialized = <[DropCountedMaybeError; 32]>::deserialize(&serialized);
944 if let Ok(deserialized) = deserialized {
945 prop_assert_eq!(array, deserialized);
946 }
947 });
948 }
949
950 #[test]
951 fn test_struct_extensions_builder_handles_partial_drop() {
952 #[derive(SchemaWrite, SchemaRead, Debug, proptest_derive::Arbitrary)]
953 #[wincode(internal, struct_extensions)]
954 struct Test {
955 a: DropCounted,
956 b: DropCounted,
957 c: DropCounted,
958 }
959
960 {
961 let _guard = TLDropGuard::new();
962 proptest!(proptest_cfg(), |(test: Test)| {
963 let serialized = serialize(&test).unwrap();
964 let mut test = MaybeUninit::<Test>::uninit();
965 let reader = &mut serialized.as_slice();
966 let mut builder = TestUninitBuilder::from_maybe_uninit_mut(&mut test);
967 builder.read_a(reader)?.read_b(reader)?;
968 prop_assert!(!builder.is_init());
969 });
971 }
972
973 #[derive(SchemaWrite, SchemaRead, Debug, proptest_derive::Arbitrary)]
974 #[wincode(internal, struct_extensions)]
975 struct TestTuple(DropCounted, DropCounted);
977
978 {
979 let _guard = TLDropGuard::new();
980 proptest!(proptest_cfg(), |(test: TestTuple)| {
981 let serialized = serialize(&test).unwrap();
982 let mut test = MaybeUninit::<TestTuple>::uninit();
983 let reader = &mut serialized.as_slice();
984 let mut builder = TestTupleUninitBuilder::from_maybe_uninit_mut(&mut test);
985 builder.read_0(reader)?;
986 prop_assert!(!builder.is_init());
987 });
989 }
990 }
991
992 #[test]
993 fn test_struct_extensions_nested_builder_handles_partial_drop() {
994 #[derive(SchemaWrite, SchemaRead, Debug, proptest_derive::Arbitrary)]
995 #[wincode(internal, struct_extensions)]
996 struct Inner {
997 a: DropCounted,
998 b: DropCounted,
999 c: DropCounted,
1000 }
1001
1002 #[derive(SchemaWrite, SchemaRead, Debug, proptest_derive::Arbitrary)]
1003 #[wincode(internal, struct_extensions)]
1004 struct Test {
1005 inner: Inner,
1006 b: DropCounted,
1007 }
1008
1009 {
1010 let _guard = TLDropGuard::new();
1011 proptest!(proptest_cfg(), |(test: Test)| {
1012 let serialized = serialize(&test).unwrap();
1013 let mut test = MaybeUninit::<Test>::uninit();
1014 let reader = &mut serialized.as_slice();
1015 let mut outer_builder = TestUninitBuilder::from_maybe_uninit_mut(&mut test);
1016 unsafe {
1017 outer_builder.init_inner_with(|inner| {
1018 let mut inner_builder = InnerUninitBuilder::from_maybe_uninit_mut(inner);
1019 inner_builder.read_a(reader)?;
1020 inner_builder.read_b(reader)?;
1021 inner_builder.read_c(reader)?;
1022 assert!(inner_builder.is_init());
1023 inner_builder.finish();
1024 Ok(())
1025 })?;
1026 }
1027 });
1029 }
1030 }
1031
1032 #[test]
1033 fn test_struct_extensions_nested_fully_initialized() {
1034 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1035 #[wincode(internal, struct_extensions)]
1036 struct Inner {
1037 a: DropCounted,
1038 b: DropCounted,
1039 c: DropCounted,
1040 }
1041
1042 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1043 #[wincode(internal, struct_extensions)]
1044 struct Test {
1045 inner: Inner,
1046 b: DropCounted,
1047 }
1048
1049 {
1050 let _guard = TLDropGuard::new();
1051 proptest!(proptest_cfg(), |(test: Test)| {
1052 let serialized = serialize(&test).unwrap();
1053 let mut uninit = MaybeUninit::<Test>::uninit();
1054 let reader = &mut serialized.as_slice();
1055 let mut outer_builder = TestUninitBuilder::from_maybe_uninit_mut(&mut uninit);
1056 unsafe {
1057 outer_builder.init_inner_with(|inner| {
1058 let mut inner_builder = InnerUninitBuilder::from_maybe_uninit_mut(inner);
1059 inner_builder.read_a(reader)?;
1060 inner_builder.read_b(reader)?;
1061 inner_builder.read_c(reader)?;
1062 assert!(inner_builder.is_init());
1063 inner_builder.finish();
1064 Ok(())
1065 })?;
1066 }
1067 outer_builder.read_b(reader)?;
1068 prop_assert!(outer_builder.is_init());
1069 outer_builder.finish();
1070 let init = unsafe { uninit.assume_init() };
1071 prop_assert_eq!(test, init);
1072 });
1073 }
1074 }
1075
1076 #[test]
1077 fn test_struct_extensions() {
1078 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1079 #[wincode(internal, struct_extensions)]
1080 struct Test {
1081 a: Vec<u8>,
1082 b: [u8; 32],
1083 c: u64,
1084 }
1085
1086 proptest!(proptest_cfg(), |(test: Test)| {
1087 let serialized = serialize(&test).unwrap();
1088 let mut uninit = MaybeUninit::<Test>::uninit();
1089 let reader = &mut serialized.as_slice();
1090 let mut builder = TestUninitBuilder::from_maybe_uninit_mut(&mut uninit);
1091 builder
1092 .read_a(reader)?
1093 .read_b(reader)?
1094 .write_c(test.c);
1095 prop_assert!(builder.is_init());
1096 builder.finish();
1097 let init = unsafe { uninit.assume_init() };
1098 prop_assert_eq!(test, init);
1099 });
1100 }
1101
1102 #[test]
1103 fn test_struct_extensions_with_container() {
1104 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1105 #[wincode(internal, struct_extensions)]
1106 struct Test {
1107 #[wincode(with = "containers::Vec<Pod<_>>")]
1108 a: Vec<u8>,
1109 #[wincode(with = "containers::Pod<_>")]
1110 b: [u8; 32],
1111 c: u64,
1112 }
1113
1114 proptest!(proptest_cfg(), |(test: Test)| {
1115 let mut uninit = MaybeUninit::<Test>::uninit();
1116 let mut builder = TestUninitBuilder::from_maybe_uninit_mut(&mut uninit);
1117 builder
1118 .write_a(test.a.clone())
1119 .write_b(test.b)
1120 .write_c(test.c);
1121 prop_assert!(builder.is_init());
1122 let init_mut = unsafe { builder.into_assume_init_mut() };
1123 prop_assert_eq!(&test, init_mut);
1124 let init = unsafe { uninit.assume_init() };
1126 prop_assert_eq!(test, init);
1127 });
1128 }
1129
1130 #[test]
1131 fn test_struct_extensions_with_reference() {
1132 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1133 #[wincode(internal)]
1134 struct Test {
1135 a: Vec<u8>,
1136 b: Option<String>,
1137 }
1138
1139 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
1140 #[wincode(internal, struct_extensions)]
1141 struct TestRef<'a> {
1142 a: &'a [u8],
1143 b: Option<&'a str>,
1144 }
1145
1146 proptest!(proptest_cfg(), |(test: Test)| {
1147 let mut uninit = MaybeUninit::<TestRef>::uninit();
1148 let mut builder = TestRefUninitBuilder::from_maybe_uninit_mut(&mut uninit);
1149 builder
1150 .write_a(test.a.as_slice())
1151 .write_b(test.b.as_deref());
1152 prop_assert!(builder.is_init());
1153 builder.finish();
1154 let init = unsafe { uninit.assume_init() };
1155 prop_assert_eq!(test.a.as_slice(), init.a);
1156 prop_assert_eq!(test.b.as_deref(), init.b);
1157 });
1158 }
1159
1160 #[test]
1161 fn test_struct_extensions_with_mapped_type() {
1162 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1163 #[wincode(internal)]
1164 struct Test {
1165 a: Vec<u8>,
1166 b: [u8; 32],
1167 c: u64,
1168 }
1169
1170 #[derive(SchemaWrite, SchemaRead)]
1171 #[wincode(internal, from = "Test", struct_extensions)]
1172 struct TestMapped {
1173 a: containers::Vec<containers::Pod<u8>>,
1174 b: containers::Pod<[u8; 32]>,
1175 c: u64,
1176 }
1177
1178 proptest!(proptest_cfg(), |(test: Test)| {
1179 let mut uninit = MaybeUninit::<Test>::uninit();
1180 let mut builder = TestMappedUninitBuilder::from_maybe_uninit_mut(&mut uninit);
1181 builder
1182 .write_a(test.a.clone())
1183 .write_b(test.b)
1184 .write_c(test.c);
1185 prop_assert!(builder.is_init());
1186 builder.finish();
1187 let init = unsafe { uninit.assume_init() };
1188 prop_assert_eq!(test, init);
1189 });
1190 }
1191
1192 #[test]
1193 fn test_struct_extensions_builder_fully_initialized() {
1194 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1195 #[wincode(internal, struct_extensions)]
1196 struct Test {
1197 a: DropCounted,
1198 b: DropCounted,
1199 c: DropCounted,
1200 }
1201
1202 {
1203 let _guard = TLDropGuard::new();
1204 proptest!(proptest_cfg(), |(test: Test)| {
1205 let serialized = serialize(&test).unwrap();
1206 let mut uninit = MaybeUninit::<Test>::uninit();
1207 let reader = &mut serialized.as_slice();
1208 let mut builder = TestUninitBuilder::from_maybe_uninit_mut(&mut uninit);
1209 builder
1210 .read_a(reader)?
1211 .read_b(reader)?
1212 .read_c(reader)?;
1213 prop_assert!(builder.is_init());
1214 let init = unsafe { builder.into_assume_init_mut() };
1215 prop_assert_eq!(&test, init);
1216
1217 let init = unsafe { uninit.assume_init() };
1218 prop_assert_eq!(test, init);
1219 });
1220 }
1221
1222 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
1223 #[wincode(internal, struct_extensions)]
1224 struct TestTuple(DropCounted, DropCounted);
1226
1227 {
1228 let _guard = TLDropGuard::new();
1229 proptest!(proptest_cfg(), |(test: TestTuple)| {
1230 let serialized = serialize(&test).unwrap();
1231 let mut uninit = MaybeUninit::<TestTuple>::uninit();
1232 let reader = &mut serialized.as_slice();
1233 let mut builder = TestTupleUninitBuilder::from_maybe_uninit_mut(&mut uninit);
1234 builder
1235 .read_0(reader)?
1236 .read_1(reader)?;
1237 assert!(builder.is_init());
1238 builder.finish();
1239
1240 let init = unsafe { uninit.assume_init() };
1241 prop_assert_eq!(test, init);
1242 });
1243 }
1244 }
1245
1246 #[test]
1247 fn test_struct_with_reference_equivalence() {
1248 #[derive(
1249 SchemaWrite, SchemaRead, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize,
1250 )]
1251 #[wincode(internal)]
1252 struct WithReference<'a> {
1253 data: &'a str,
1254 id: u64,
1255 }
1256
1257 proptest!(proptest_cfg(), |(s in any::<String>(), id in any::<u64>())| {
1258 let serialized = serialize(&WithReference { data: &s, id }).unwrap();
1259 let bincode_serialized = bincode::serialize(&WithReference { data: &s, id }).unwrap();
1260 prop_assert_eq!(&serialized, &bincode_serialized);
1261 let deserialized: WithReference = deserialize(&serialized).unwrap();
1262 let bincode_deserialized: WithReference = bincode::deserialize(&bincode_serialized).unwrap();
1263 prop_assert_eq!(deserialized, bincode_deserialized);
1264 });
1265 }
1266
1267 #[test]
1268 fn test_enum_equivalence() {
1269 #[derive(
1270 SchemaWrite,
1271 SchemaRead,
1272 Debug,
1273 PartialEq,
1274 Eq,
1275 serde::Serialize,
1276 serde::Deserialize,
1277 Clone,
1278 proptest_derive::Arbitrary,
1279 )]
1280 #[wincode(internal)]
1281 enum Enum {
1282 A { name: String, id: u64 },
1283 B(String, #[wincode(with = "containers::Vec<Pod<_>>")] Vec<u8>),
1284 C,
1285 }
1286
1287 proptest!(proptest_cfg(), |(e: Enum)| {
1288 let serialized = serialize(&e).unwrap();
1289 let bincode_serialized = bincode::serialize(&e).unwrap();
1290 prop_assert_eq!(&serialized, &bincode_serialized);
1291 let deserialized: Enum = deserialize(&serialized).unwrap();
1292 let bincode_deserialized: Enum = bincode::deserialize(&bincode_serialized).unwrap();
1293 prop_assert_eq!(deserialized, bincode_deserialized);
1294 });
1295 }
1296
1297 #[test]
1298 fn enum_with_tag_encoding_roundtrip() {
1299 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1300 #[wincode(internal, tag_encoding = "u8")]
1301 enum Enum {
1302 A { name: String, id: u64 },
1303 B(String, Vec<u8>),
1304 C,
1305 }
1306
1307 proptest!(proptest_cfg(), |(e: Enum)| {
1308 let serialized = serialize(&e).unwrap();
1309 let deserialized: Enum = deserialize(&serialized).unwrap();
1310 prop_assert_eq!(deserialized, e);
1311 });
1312 }
1313
1314 #[test]
1315 fn enum_with_custom_tag_roundtrip() {
1316 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1317 #[wincode(internal)]
1318 enum Enum {
1319 #[wincode(tag = 5)]
1320 A { name: String, id: u64 },
1321 #[wincode(tag = 8)]
1322 B(String, Vec<u8>),
1323 #[wincode(tag = 13)]
1324 C,
1325 }
1326
1327 proptest!(proptest_cfg(), |(e: Enum)| {
1328 let serialized = serialize(&e).unwrap();
1329 let deserialized: Enum = deserialize(&serialized).unwrap();
1330 prop_assert_eq!(deserialized, e);
1331 });
1332
1333 proptest!(proptest_cfg(), |(e: Enum)| {
1334 let serialized = serialize(&e).unwrap();
1335 let int: u32 = match e {
1336 Enum::A { .. } => 5,
1337 Enum::B(..) => 8,
1338 Enum::C => 13,
1339 };
1340 prop_assert_eq!(&int.to_le_bytes(), &serialized[..4]);
1341 });
1342 }
1343
1344 #[test]
1345 fn unit_enum_with_tag_encoding_static_size() {
1346 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq)]
1347 #[wincode(internal, tag_encoding = "u8")]
1348 enum Enum {
1349 A,
1350 B,
1351 C,
1352 }
1353
1354 assert!(matches!(
1355 <Enum as SchemaWrite>::TYPE_META,
1356 TypeMeta::Static {
1357 size: 1,
1358 zero_copy: false
1359 }
1360 ));
1361
1362 assert!(matches!(
1363 <Enum as SchemaRead<'_>>::TYPE_META,
1364 TypeMeta::Static {
1365 size: 1,
1366 zero_copy: false
1367 }
1368 ));
1369 }
1370
1371 #[test]
1372 fn unit_enum_with_static_size() {
1373 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq)]
1374 #[wincode(internal)]
1375 enum Enum {
1376 A,
1377 B,
1378 C,
1379 }
1380
1381 assert!(matches!(
1382 <Enum as SchemaWrite>::TYPE_META,
1383 TypeMeta::Static {
1384 size: 4,
1385 zero_copy: false
1386 }
1387 ));
1388
1389 assert!(matches!(
1390 <Enum as SchemaRead<'_>>::TYPE_META,
1391 TypeMeta::Static {
1392 size: 4,
1393 zero_copy: false
1394 }
1395 ));
1396 }
1397
1398 #[test]
1399 fn enum_tag_encoding() {
1400 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1401 #[wincode(internal, tag_encoding = "u8")]
1402 enum EnumU8 {
1403 A,
1404 B,
1405 C,
1406 }
1407
1408 proptest!(proptest_cfg(), |(e: EnumU8)| {
1409 let serialized = serialize(&e).unwrap();
1410 let int = e as u8;
1411 prop_assert_eq!(&int.to_le_bytes(), &serialized[..]);
1412 });
1413
1414 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1415 #[wincode(internal, tag_encoding = "u8")]
1416 enum EnumTupleU8 {
1417 A(u64),
1418 B(StructStatic),
1419 C(StructNonStatic),
1420 }
1421
1422 proptest!(proptest_cfg(), |(e: EnumTupleU8)| {
1423 let serialized = serialize(&e).unwrap();
1424 let int: u8 = match e {
1425 EnumTupleU8::A(_) => 0,
1426 EnumTupleU8::B(_) => 1,
1427 EnumTupleU8::C(_) => 2,
1428 };
1429 prop_assert_eq!(&int.to_le_bytes(), &serialized[..1]);
1430 });
1431
1432 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1433 #[wincode(internal, tag_encoding = "u8")]
1434 enum EnumRecordU8 {
1435 A { id: u64 },
1436 B { data: StructStatic },
1437 C { data: StructNonStatic },
1438 }
1439
1440 proptest!(proptest_cfg(), |(e: EnumRecordU8)| {
1441 let serialized = serialize(&e).unwrap();
1442 let int: u8 = match e {
1443 EnumRecordU8::A { .. } => 0,
1444 EnumRecordU8::B { .. } => 1,
1445 EnumRecordU8::C { .. } => 2,
1446 };
1447 prop_assert_eq!(&int.to_le_bytes(), &serialized[..1]);
1448 });
1449 }
1450
1451 #[test]
1452 fn enum_static_uniform_variants() {
1453 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1454 #[wincode(internal)]
1455 enum Enum {
1456 A {
1457 a: u64,
1458 },
1459 B {
1460 x: u32,
1461 y: u32,
1462 },
1463 C {
1464 a: u8,
1465 b: u8,
1466 c: u8,
1467 d: u8,
1468 e: u8,
1469 f: u8,
1470 g: u8,
1471 h: u8,
1472 },
1473 }
1474
1475 assert_eq!(
1476 <Enum as SchemaWrite>::TYPE_META,
1477 TypeMeta::Static {
1478 size: 8 + 4,
1480 zero_copy: false
1481 }
1482 );
1483 assert_eq!(
1484 <Enum as SchemaRead<'_>>::TYPE_META,
1485 TypeMeta::Static {
1486 size: 8 + 4,
1488 zero_copy: false
1489 }
1490 );
1491
1492 proptest!(proptest_cfg(), |(e: Enum)| {
1493 let serialized = serialize(&e).unwrap();
1494 let deserialized: Enum = deserialize(&serialized).unwrap();
1495 prop_assert_eq!(deserialized, e);
1496 });
1497 }
1498
1499 #[test]
1500 fn enum_dynamic_non_uniform_variants() {
1501 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1502 #[wincode(internal)]
1503 enum Enum {
1504 A { a: u64 },
1505 B { x: u32, y: u32 },
1506 C { a: u8, b: u8 },
1507 }
1508
1509 assert_eq!(<Enum as SchemaWrite>::TYPE_META, TypeMeta::Dynamic);
1510 assert_eq!(<Enum as SchemaRead<'_>>::TYPE_META, TypeMeta::Dynamic);
1511
1512 proptest!(proptest_cfg(), |(e: Enum)| {
1513 let serialized = serialize(&e).unwrap();
1514 let deserialized: Enum = deserialize(&serialized).unwrap();
1515 prop_assert_eq!(deserialized, e);
1516 });
1517 }
1518
1519 #[test]
1520 fn enum_single_variant_type_meta_pass_thru() {
1521 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, proptest_derive::Arbitrary)]
1522 #[wincode(internal)]
1523 enum Enum {
1524 A { a: u8, b: [u8; 32] },
1525 }
1526
1527 assert_eq!(
1530 <Enum as SchemaWrite>::TYPE_META,
1531 TypeMeta::Static {
1532 size: 1 + 32 + 4,
1533 zero_copy: false
1534 }
1535 );
1536 assert_eq!(
1537 <Enum as SchemaRead<'_>>::TYPE_META,
1538 TypeMeta::Static {
1539 size: 1 + 32 + 4,
1540 zero_copy: false
1541 }
1542 );
1543 }
1544
1545 #[test]
1546 fn enum_unit_and_non_unit_dynamic() {
1547 #[derive(
1548 SchemaWrite,
1549 SchemaRead,
1550 Debug,
1551 PartialEq,
1552 proptest_derive::Arbitrary,
1553 serde::Serialize,
1554 serde::Deserialize,
1555 )]
1556 #[wincode(internal)]
1557 enum Enum {
1558 Unit,
1559 NonUnit(u8),
1560 }
1561
1562 assert_eq!(<Enum as SchemaWrite>::TYPE_META, TypeMeta::Dynamic);
1563 assert_eq!(<Enum as SchemaRead<'_>>::TYPE_META, TypeMeta::Dynamic);
1564
1565 proptest!(proptest_cfg(), |(e: Enum)| {
1566 let serialized = serialize(&e).unwrap();
1567 let bincode_serialized = bincode::serialize(&e).unwrap();
1568 prop_assert_eq!(&serialized, &bincode_serialized);
1569
1570 let deserialized: Enum = deserialize(&serialized).unwrap();
1571 let bincode_deserialized: Enum = bincode::deserialize(&bincode_serialized).unwrap();
1572 prop_assert_eq!(&deserialized, &bincode_deserialized);
1573 prop_assert_eq!(deserialized, e);
1574 });
1575 }
1576
1577 #[test]
1578 fn test_phantom_data() {
1579 let val = PhantomData::<StructStatic>;
1580 let serialized = serialize(&val).unwrap();
1581 let bincode_serialized = bincode::serialize(&val).unwrap();
1582 assert_eq!(&serialized, &bincode_serialized);
1583 assert_eq!(
1584 PhantomData::<StructStatic>::size_of(&val).unwrap(),
1585 bincode::serialized_size(&val).unwrap() as usize
1586 );
1587 let deserialized: PhantomData<StructStatic> = deserialize(&serialized).unwrap();
1588 let bincode_deserialized: PhantomData<StructStatic> =
1589 bincode::deserialize(&bincode_serialized).unwrap();
1590 assert_eq!(deserialized, bincode_deserialized);
1591 }
1592
1593 #[test]
1594 fn test_unit() {
1595 let serialized = serialize(&()).unwrap();
1596 let bincode_serialized = bincode::serialize(&()).unwrap();
1597 assert_eq!(&serialized, &bincode_serialized);
1598 assert_eq!(
1599 <()>::size_of(&()).unwrap(),
1600 bincode::serialized_size(&()).unwrap() as usize
1601 );
1602 assert!(deserialize::<()>(&serialized).is_ok());
1603 assert!(bincode::deserialize::<()>(&bincode_serialized).is_ok());
1604 }
1605
1606 #[test]
1607 fn test_borrowed_bytes() {
1608 #[derive(
1609 SchemaWrite, SchemaRead, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize,
1610 )]
1611 #[wincode(internal)]
1612 struct BorrowedBytes<'a> {
1613 bytes: &'a [u8],
1614 }
1615
1616 proptest!(proptest_cfg(), |(bytes in proptest::collection::vec(any::<u8>(), 0..=100))| {
1617 let val = BorrowedBytes { bytes: &bytes };
1618 let bincode_serialized = bincode::serialize(&val).unwrap();
1619 let schema_serialized = serialize(&val).unwrap();
1620 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1621 let bincode_deserialized: BorrowedBytes = bincode::deserialize(&bincode_serialized).unwrap();
1622 let schema_deserialized: BorrowedBytes = deserialize(&schema_serialized).unwrap();
1623 prop_assert_eq!(&val, &bincode_deserialized);
1624 prop_assert_eq!(val, schema_deserialized);
1625 });
1626 }
1627
1628 #[test]
1629 fn test_boxed_slice_pod_drop() {
1630 #[derive(proptest_derive::Arbitrary, Debug, Clone, Copy)]
1631 #[allow(dead_code)]
1632 struct Signature([u8; 64]);
1633
1634 type Target = containers::Box<[Pod<Signature>]>;
1635 proptest!(proptest_cfg(), |(slice in proptest::collection::vec(any::<Signature>(), 1..=32).prop_map(|vec| vec.into_boxed_slice()))| {
1636 let serialized = Target::serialize(&slice).unwrap();
1637 let deserialized = Target::deserialize(&serialized[..serialized.len() - 32]);
1640 prop_assert!(deserialized.is_err());
1641 });
1642 }
1643
1644 #[test]
1645 fn test_zero_copy_padding_disqualification() {
1646 #[derive(SchemaWrite, SchemaRead)]
1647 #[wincode(internal)]
1648 #[repr(C, align(4))]
1649 struct Padded {
1650 a: u8,
1651 }
1652
1653 assert!(matches!(
1654 <Padded as SchemaWrite>::TYPE_META,
1655 TypeMeta::Static {
1656 size: 1,
1658 zero_copy: false
1660 }
1661 ));
1662
1663 assert!(matches!(
1664 <Padded as SchemaRead<'_>>::TYPE_META,
1665 TypeMeta::Static {
1666 size: 1,
1668 zero_copy: false
1670 }
1671 ));
1672 }
1673
1674 proptest! {
1675 #![proptest_config(proptest_cfg())]
1676
1677 #[test]
1678 fn test_char(val in any::<char>()) {
1679 let bincode_serialized = bincode::serialize(&val).unwrap();
1680 let schema_serialized = serialize(&val).unwrap();
1681 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1682 prop_assert_eq!(char::size_of(&val).unwrap(), bincode::serialized_size(&val).unwrap() as usize);
1683
1684 let bincode_deserialized: char = bincode::deserialize(&bincode_serialized).unwrap();
1685 let schema_deserialized: char = deserialize(&schema_serialized).unwrap();
1686 prop_assert_eq!(val, bincode_deserialized);
1687 prop_assert_eq!(val, schema_deserialized);
1688 }
1689
1690 #[test]
1691 fn test_elem_compat(val in any::<StructStatic>()) {
1692 let bincode_serialized = bincode::serialize(&val).unwrap();
1693 let schema_serialized = <Elem<StructStatic>>::serialize(&val).unwrap();
1694 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1695
1696 let bincode_deserialized: StructStatic = bincode::deserialize(&bincode_serialized).unwrap();
1697 let schema_deserialized: StructStatic = <Elem<StructStatic>>::deserialize(&schema_serialized).unwrap();
1698 prop_assert_eq!(&val, &bincode_deserialized);
1699 prop_assert_eq!(val, schema_deserialized);
1700 }
1701
1702 #[test]
1703 fn test_elem_vec_compat(val in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
1704 let bincode_serialized = bincode::serialize(&val).unwrap();
1705 let schema_serialized = <containers::Vec<Elem<StructStatic>>>::serialize(&val).unwrap();
1706 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1707
1708 let bincode_deserialized: Vec<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1709 let schema_deserialized = <containers::Vec<Elem<StructStatic>>>::deserialize(&schema_serialized).unwrap();
1710 prop_assert_eq!(&val, &bincode_deserialized);
1711 prop_assert_eq!(val, schema_deserialized);
1712 }
1713
1714 #[test]
1715 fn test_vec_elem_static(vec in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
1716 let bincode_serialized = bincode::serialize(&vec).unwrap();
1717 let schema_serialized = serialize(&vec).unwrap();
1718 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1719
1720 let bincode_deserialized: Vec<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1721 let schema_deserialized: Vec<StructStatic> = deserialize(&schema_serialized).unwrap();
1722 prop_assert_eq!(&vec, &bincode_deserialized);
1723 prop_assert_eq!(vec, schema_deserialized);
1724 }
1725
1726 #[test]
1727 fn test_vec_elem_zero_copy(vec in proptest::collection::vec(any::<StructZeroCopy>(), 0..=100)) {
1728 let bincode_serialized = bincode::serialize(&vec).unwrap();
1729 let schema_serialized = serialize(&vec).unwrap();
1730 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1731
1732 let bincode_deserialized: Vec<StructZeroCopy> = bincode::deserialize(&bincode_serialized).unwrap();
1733 let schema_deserialized: Vec<StructZeroCopy> = deserialize(&schema_serialized).unwrap();
1734 prop_assert_eq!(&vec, &bincode_deserialized);
1735 prop_assert_eq!(vec, schema_deserialized);
1736 }
1737
1738
1739 #[test]
1740 fn test_vec_elem_non_static(vec in proptest::collection::vec(any::<StructNonStatic>(), 0..=16)) {
1741 let bincode_serialized = bincode::serialize(&vec).unwrap();
1742 let schema_serialized = serialize(&vec).unwrap();
1743 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1744
1745 let bincode_deserialized: Vec<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1746 let schema_deserialized: Vec<StructNonStatic> = deserialize(&schema_serialized).unwrap();
1747 prop_assert_eq!(&vec, &bincode_deserialized);
1748 prop_assert_eq!(vec, schema_deserialized);
1749 }
1750
1751 #[test]
1752 fn test_vec_elem_bytes(vec in proptest::collection::vec(any::<u8>(), 0..=100)) {
1753 let bincode_serialized = bincode::serialize(&vec).unwrap();
1754 let schema_serialized = serialize(&vec).unwrap();
1755 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1756
1757 let bincode_deserialized: Vec<u8> = bincode::deserialize(&bincode_serialized).unwrap();
1758 let schema_deserialized: Vec<u8> = deserialize(&schema_serialized).unwrap();
1759 prop_assert_eq!(&vec, &bincode_deserialized);
1760 prop_assert_eq!(vec, schema_deserialized);
1761 }
1762
1763 #[test]
1764 fn test_serialize_slice(slice in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
1765 let bincode_serialized = bincode::serialize(slice.as_slice()).unwrap();
1766 let schema_serialized = serialize(slice.as_slice()).unwrap();
1767 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1768 }
1769
1770 #[test]
1771 fn test_vec_pod(vec in proptest::collection::vec(any::<[u8; 32]>(), 0..=100)) {
1772 let bincode_serialized = bincode::serialize(&vec).unwrap();
1773 let schema_serialized = serialize(&vec).unwrap();
1774 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1775
1776 let bincode_deserialized: Vec<[u8; 32]> = bincode::deserialize(&bincode_serialized).unwrap();
1777 let schema_deserialized: Vec<[u8; 32]> = deserialize(&schema_serialized).unwrap();
1778 prop_assert_eq!(&vec, &bincode_deserialized);
1779 prop_assert_eq!(vec, schema_deserialized);
1780 }
1781
1782 #[test]
1783 fn test_vec_deque_elem_static(vec in proptest::collection::vec_deque(any::<StructStatic>(), 0..=100)) {
1784 let bincode_serialized = bincode::serialize(&vec).unwrap();
1785 let schema_serialized = serialize(&vec).unwrap();
1786 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1787
1788 let bincode_deserialized: VecDeque<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1789 let schema_deserialized: VecDeque<StructStatic> = deserialize(&schema_serialized).unwrap();
1790 prop_assert_eq!(&vec, &bincode_deserialized);
1791 prop_assert_eq!(vec, schema_deserialized);
1792 }
1793
1794 #[test]
1795 fn test_vec_deque_elem_non_static(vec in proptest::collection::vec_deque(any::<StructNonStatic>(), 0..=16)) {
1796 let bincode_serialized = bincode::serialize(&vec).unwrap();
1797 let schema_serialized = serialize(&vec).unwrap();
1798 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1799
1800 let bincode_deserialized: VecDeque<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1801 let schema_deserialized: VecDeque<StructNonStatic> = deserialize(&schema_serialized).unwrap();
1802 prop_assert_eq!(&vec, &bincode_deserialized);
1803 prop_assert_eq!(vec, schema_deserialized);
1804 }
1805
1806 #[test]
1807 fn test_vec_deque_elem_bytes(vec in proptest::collection::vec_deque(any::<u8>(), 0..=100)) {
1808 let bincode_serialized = bincode::serialize(&vec).unwrap();
1809 let schema_serialized = serialize(&vec).unwrap();
1810 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1811
1812 let bincode_deserialized: VecDeque<u8> = bincode::deserialize(&bincode_serialized).unwrap();
1813 let schema_deserialized: VecDeque<u8> = deserialize(&schema_serialized).unwrap();
1814 prop_assert_eq!(&vec, &bincode_deserialized);
1815 prop_assert_eq!(vec, schema_deserialized);
1816 }
1817
1818 #[test]
1819 fn test_hash_map_zero_copy(map in proptest::collection::hash_map(any::<u8>(), any::<StructZeroCopy>(), 0..=100)) {
1820 let bincode_serialized = bincode::serialize(&map).unwrap();
1821 let schema_serialized = serialize(&map).unwrap();
1822 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1823
1824 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1825 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1826 prop_assert_eq!(&map, &bincode_deserialized);
1827 prop_assert_eq!(map, schema_deserialized);
1828 }
1829
1830 #[test]
1831 fn test_hash_map_static(map in proptest::collection::hash_map(any::<u64>(), any::<StructStatic>(), 0..=100)) {
1832 let bincode_serialized = bincode::serialize(&map).unwrap();
1833 let schema_serialized = serialize(&map).unwrap();
1834 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1835
1836 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1837 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1838 prop_assert_eq!(&map, &bincode_deserialized);
1839 prop_assert_eq!(map, schema_deserialized);
1840 }
1841
1842
1843 #[test]
1844 fn test_hash_map_non_static(map in proptest::collection::hash_map(any::<u64>(), any::<StructNonStatic>(), 0..=16)) {
1845 let bincode_serialized = bincode::serialize(&map).unwrap();
1846 let schema_serialized = serialize(&map).unwrap();
1847 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1848
1849 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1850 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1851 prop_assert_eq!(&map, &bincode_deserialized);
1852 prop_assert_eq!(map, schema_deserialized);
1853 }
1854
1855 #[test]
1856 fn test_hash_set_zero_copy(set in proptest::collection::hash_set(any::<StructZeroCopy>(), 0..=100)) {
1857 let bincode_serialized = bincode::serialize(&set).unwrap();
1858 let schema_serialized = serialize(&set).unwrap();
1859 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1860
1861 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1862 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1863 prop_assert_eq!(&set, &bincode_deserialized);
1864 prop_assert_eq!(set, schema_deserialized);
1865 }
1866
1867 #[test]
1868 fn test_hash_set_static(set in proptest::collection::hash_set(any::<StructStatic>(), 0..=100)) {
1869 let bincode_serialized = bincode::serialize(&set).unwrap();
1870 let schema_serialized = serialize(&set).unwrap();
1871 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1872
1873 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1874 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1875 prop_assert_eq!(&set, &bincode_deserialized);
1876 prop_assert_eq!(set, schema_deserialized);
1877 }
1878
1879 #[test]
1880 fn test_hash_set_non_static(set in proptest::collection::hash_set(any::<StructNonStatic>(), 0..=16)) {
1881 let bincode_serialized = bincode::serialize(&set).unwrap();
1882 let schema_serialized = serialize(&set).unwrap();
1883 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1884
1885 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1886 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1887 prop_assert_eq!(&set, &bincode_deserialized);
1888 prop_assert_eq!(set, schema_deserialized);
1889 }
1890
1891 #[test]
1892 fn test_btree_map_zero_copy(map in proptest::collection::btree_map(any::<u8>(), any::<StructZeroCopy>(), 0..=100)) {
1893 let bincode_serialized = bincode::serialize(&map).unwrap();
1894 let schema_serialized = serialize(&map).unwrap();
1895 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1896
1897 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1898 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1899 prop_assert_eq!(&map, &bincode_deserialized);
1900 prop_assert_eq!(map, schema_deserialized);
1901 }
1902
1903 #[test]
1904 fn test_btree_map_static(map in proptest::collection::btree_map(any::<u64>(), any::<StructStatic>(), 0..=100)) {
1905 let bincode_serialized = bincode::serialize(&map).unwrap();
1906 let schema_serialized = serialize(&map).unwrap();
1907 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1908
1909 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1910 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1911 prop_assert_eq!(&map, &bincode_deserialized);
1912 prop_assert_eq!(map, schema_deserialized);
1913 }
1914
1915 #[test]
1916 fn test_btree_map_non_static(map in proptest::collection::btree_map(any::<u64>(), any::<StructNonStatic>(), 0..=16)) {
1917 let bincode_serialized = bincode::serialize(&map).unwrap();
1918 let schema_serialized = serialize(&map).unwrap();
1919 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1920
1921 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1922 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1923 prop_assert_eq!(&map, &bincode_deserialized);
1924 prop_assert_eq!(map, schema_deserialized);
1925 }
1926
1927 #[test]
1928 fn test_btree_set_zero_copy(set in proptest::collection::btree_set(any::<StructZeroCopy>(), 0..=100)) {
1929 let bincode_serialized = bincode::serialize(&set).unwrap();
1930 let schema_serialized = serialize(&set).unwrap();
1931 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1932
1933 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1934 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1935 prop_assert_eq!(&set, &bincode_deserialized);
1936 prop_assert_eq!(set, schema_deserialized);
1937 }
1938
1939 #[test]
1940 fn test_btree_set_static(set in proptest::collection::btree_set(any::<StructStatic>(), 0..=100)) {
1941 let bincode_serialized = bincode::serialize(&set).unwrap();
1942 let schema_serialized = serialize(&set).unwrap();
1943 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1944
1945 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1946 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1947 prop_assert_eq!(&set, &bincode_deserialized);
1948 prop_assert_eq!(set, schema_deserialized);
1949 }
1950
1951 #[test]
1952 fn test_btree_set_non_static(map in proptest::collection::btree_set(any::<StructNonStatic>(), 0..=16)) {
1953 let bincode_serialized = bincode::serialize(&map).unwrap();
1954 let schema_serialized = serialize(&map).unwrap();
1955 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1956
1957 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
1958 let schema_deserialized = deserialize(&schema_serialized).unwrap();
1959 prop_assert_eq!(&map, &bincode_deserialized);
1960 prop_assert_eq!(map, schema_deserialized);
1961 }
1962
1963 #[test]
1964 fn test_binary_heap_zero_copy(heap in proptest::collection::binary_heap(any::<StructZeroCopy>(), 0..=100)) {
1965 let bincode_serialized = bincode::serialize(&heap).unwrap();
1966 let schema_serialized = serialize(&heap).unwrap();
1967 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1968
1969 let bincode_deserialized: BinaryHeap<StructZeroCopy> = bincode::deserialize(&bincode_serialized).unwrap();
1970 let schema_deserialized: BinaryHeap<StructZeroCopy> = deserialize(&schema_serialized).unwrap();
1971 prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
1972 prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
1973 }
1974
1975 #[test]
1976 fn test_binary_heap_static(heap in proptest::collection::binary_heap(any::<StructStatic>(), 0..=100)) {
1977 let bincode_serialized = bincode::serialize(&heap).unwrap();
1978 let schema_serialized = serialize(&heap).unwrap();
1979 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1980
1981 let bincode_deserialized: BinaryHeap<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1982 let schema_deserialized: BinaryHeap<StructStatic> = deserialize(&schema_serialized).unwrap();
1983 prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
1984 prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
1985 }
1986
1987
1988 #[test]
1989 fn test_binary_heap_non_static(heap in proptest::collection::binary_heap(any::<StructNonStatic>(), 0..=16)) {
1990 let bincode_serialized = bincode::serialize(&heap).unwrap();
1991 let schema_serialized = serialize(&heap).unwrap();
1992 prop_assert_eq!(&bincode_serialized, &schema_serialized);
1993
1994 let bincode_deserialized: BinaryHeap<StructNonStatic> = bincode::deserialize(&bincode_serialized).unwrap();
1995 let schema_deserialized: BinaryHeap<StructNonStatic> = deserialize(&schema_serialized).unwrap();
1996 prop_assert_eq!(heap.as_slice(), bincode_deserialized.as_slice());
1997 prop_assert_eq!(heap.as_slice(), schema_deserialized.as_slice());
1998 }
1999
2000 #[test]
2001 fn test_linked_list_zero_copy(list in proptest::collection::linked_list(any::<StructZeroCopy>(), 0..=100)) {
2002 let bincode_serialized = bincode::serialize(&list).unwrap();
2003 let schema_serialized = serialize(&list).unwrap();
2004 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2005
2006 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2007 let schema_deserialized = deserialize(&schema_serialized).unwrap();
2008 prop_assert_eq!(&list, &bincode_deserialized);
2009 prop_assert_eq!(list, schema_deserialized);
2010 }
2011
2012 #[test]
2013 fn test_linked_list_static(list in proptest::collection::linked_list(any::<StructStatic>(), 0..=100)) {
2014 let bincode_serialized = bincode::serialize(&list).unwrap();
2015 let schema_serialized = serialize(&list).unwrap();
2016 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2017
2018 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2019 let schema_deserialized = deserialize(&schema_serialized).unwrap();
2020 prop_assert_eq!(&list, &bincode_deserialized);
2021 prop_assert_eq!(list, schema_deserialized);
2022 }
2023
2024 #[test]
2025 fn test_linked_list_non_static(list in proptest::collection::linked_list(any::<StructNonStatic>(), 0..=16)) {
2026 let bincode_serialized = bincode::serialize(&list).unwrap();
2027 let schema_serialized = serialize(&list).unwrap();
2028 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2029
2030 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2031 let schema_deserialized = deserialize(&schema_serialized).unwrap();
2032 prop_assert_eq!(&list, &bincode_deserialized);
2033 prop_assert_eq!(list, schema_deserialized);
2034 }
2035
2036 #[test]
2037 fn test_array_bytes(array in any::<[u8; 32]>()) {
2038 let bincode_serialized = bincode::serialize(&array).unwrap();
2039 let schema_serialized = serialize(&array).unwrap();
2040 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2041
2042 let bincode_deserialized: [u8; 32] = bincode::deserialize(&bincode_serialized).unwrap();
2043 let schema_deserialized: [u8; 32] = deserialize(&schema_serialized).unwrap();
2044 prop_assert_eq!(&array, &bincode_deserialized);
2045 prop_assert_eq!(array, schema_deserialized);
2046 }
2047
2048 #[test]
2049 fn test_array_static(array in any::<[u64; 32]>()) {
2050 let bincode_serialized = bincode::serialize(&array).unwrap();
2051 type Target = [u64; 32];
2052 let schema_serialized = Target::serialize(&array).unwrap();
2053 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2054 let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
2055 let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
2056 prop_assert_eq!(&array, &bincode_deserialized);
2057 prop_assert_eq!(array, schema_deserialized);
2058 }
2059
2060 #[test]
2061 fn test_array_non_static(array in any::<[StructNonStatic; 16]>()) {
2062 let bincode_serialized = bincode::serialize(&array).unwrap();
2063 type Target = [StructNonStatic; 16];
2064 let schema_serialized = Target::serialize(&array).unwrap();
2065 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2066 let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
2067 let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
2068 prop_assert_eq!(&array, &bincode_deserialized);
2069 prop_assert_eq!(array, schema_deserialized);
2070 }
2071
2072 #[test]
2073 fn test_option(option in proptest::option::of(any::<StructStatic>())) {
2074 let bincode_serialized = bincode::serialize(&option).unwrap();
2075 let schema_serialized = serialize(&option).unwrap();
2076
2077 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2078 let bincode_deserialized: Option<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2079 let schema_deserialized: Option<StructStatic> = deserialize(&schema_serialized).unwrap();
2080 prop_assert_eq!(&option, &bincode_deserialized);
2081 prop_assert_eq!(&option, &schema_deserialized);
2082 }
2083
2084 #[test]
2085 fn test_option_container(option in proptest::option::of(any::<[u8; 32]>())) {
2086 let bincode_serialized = bincode::serialize(&option).unwrap();
2087 type Target = Option<Pod<[u8; 32]>>;
2088 let schema_serialized = Target::serialize(&option).unwrap();
2089 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2090 let bincode_deserialized: Option<[u8; 32]> = bincode::deserialize(&bincode_serialized).unwrap();
2091 let schema_deserialized: Option<[u8; 32]> = Target::deserialize(&schema_serialized).unwrap();
2092 prop_assert_eq!(&option, &bincode_deserialized);
2093 prop_assert_eq!(&option, &schema_deserialized);
2094 }
2095
2096 #[test]
2097 fn test_bool(val in any::<bool>()) {
2098 let bincode_serialized = bincode::serialize(&val).unwrap();
2099 let schema_serialized = serialize(&val).unwrap();
2100 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2101 let bincode_deserialized: bool = bincode::deserialize(&bincode_serialized).unwrap();
2102 let schema_deserialized: bool = deserialize(&schema_serialized).unwrap();
2103 prop_assert_eq!(val, bincode_deserialized);
2104 prop_assert_eq!(val, schema_deserialized);
2105 }
2106
2107 #[test]
2108 fn test_bool_invalid_bit_pattern(val in 2u8..=255) {
2109 let bincode_deserialized: Result<bool,_> = bincode::deserialize(&[val]);
2110 let schema_deserialized: Result<bool,_> = deserialize(&[val]);
2111 prop_assert!(bincode_deserialized.is_err());
2112 prop_assert!(schema_deserialized.is_err());
2113 }
2114
2115 #[test]
2116 fn test_box(s in any::<StructStatic>()) {
2117 let data = Box::new(s);
2118 let bincode_serialized = bincode::serialize(&data).unwrap();
2119 let schema_serialized = serialize(&data).unwrap();
2120 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2121
2122 let bincode_deserialized: Box<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2123 let schema_deserialized: Box<StructStatic> = deserialize(&schema_serialized).unwrap();
2124 prop_assert_eq!(&data, &bincode_deserialized);
2125 prop_assert_eq!(&data, &schema_deserialized);
2126 }
2127
2128 #[test]
2129 fn test_rc(s in any::<StructStatic>()) {
2130 let data = Rc::new(s);
2131 let bincode_serialized = bincode::serialize(&data).unwrap();
2132 let schema_serialized = serialize(&data).unwrap();
2133 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2134
2135 let bincode_deserialized: Rc<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2136 let schema_deserialized: Rc<StructStatic> = deserialize(&schema_serialized).unwrap();
2137 prop_assert_eq!(&data, &bincode_deserialized);
2138 prop_assert_eq!(&data, &schema_deserialized);
2139 }
2140
2141 #[test]
2142 fn test_arc(s in any::<StructStatic>()) {
2143 let data = Arc::new(s);
2144 let bincode_serialized = bincode::serialize(&data).unwrap();
2145 let schema_serialized = serialize(&data).unwrap();
2146 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2147
2148 let bincode_deserialized: Arc<StructStatic> = bincode::deserialize(&bincode_serialized).unwrap();
2149 let schema_deserialized: Arc<StructStatic> = deserialize(&schema_serialized).unwrap();
2150 prop_assert_eq!(&data, &bincode_deserialized);
2151 prop_assert_eq!(&data, &schema_deserialized);
2152 }
2153
2154 #[test]
2155 fn test_boxed_slice_zero_copy(vec in proptest::collection::vec(any::<StructZeroCopy>(), 0..=100)) {
2156 let data = vec.into_boxed_slice();
2157 let bincode_serialized = bincode::serialize(&data).unwrap();
2158 let schema_serialized = serialize(&data).unwrap();
2159 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2160
2161 let bincode_deserialized: Box<[StructZeroCopy]> = bincode::deserialize(&bincode_serialized).unwrap();
2162 let schema_deserialized: Box<[StructZeroCopy]> = deserialize(&schema_serialized).unwrap();
2163 prop_assert_eq!(&data, &bincode_deserialized);
2164 prop_assert_eq!(&data, &schema_deserialized);
2165 }
2166
2167 #[test]
2168 fn test_boxed_slice_static(vec in proptest::collection::vec(any::<StructStatic>(), 0..=100)) {
2169 let data = vec.into_boxed_slice();
2170 let bincode_serialized = bincode::serialize(&data).unwrap();
2171 let schema_serialized = serialize(&data).unwrap();
2172 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2173
2174 let bincode_deserialized: Box<[StructStatic]> = bincode::deserialize(&bincode_serialized).unwrap();
2175 let schema_deserialized: Box<[StructStatic]> = deserialize(&schema_serialized).unwrap();
2176 prop_assert_eq!(&data, &bincode_deserialized);
2177 prop_assert_eq!(&data, &schema_deserialized);
2178 }
2179
2180 #[test]
2181 fn test_boxed_slice_non_static(vec in proptest::collection::vec(any::<StructNonStatic>(), 0..=16)) {
2182 let data = vec.into_boxed_slice();
2183 let bincode_serialized = bincode::serialize(&data).unwrap();
2184 type Target = Box<[StructNonStatic]>;
2185 let schema_serialized = serialize(&data).unwrap();
2186 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2187
2188 let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
2189 let schema_deserialized: Target = Target::deserialize(&schema_serialized).unwrap();
2190 prop_assert_eq!(&data, &bincode_deserialized);
2191 prop_assert_eq!(&data, &schema_deserialized);
2192 }
2193
2194 #[test]
2195 fn test_integers(
2196 val in (
2197 any::<u8>(),
2198 any::<i8>(),
2199 any::<u16>(),
2200 any::<i16>(),
2201 any::<u32>(),
2202 any::<i32>(),
2203 any::<usize>(),
2204 any::<isize>(),
2205 any::<u64>(),
2206 any::<i64>(),
2207 any::<u128>(),
2208 any::<i128>()
2209 )
2210 ) {
2211 type Target = (u8, i8, u16, i16, u32, i32, usize, isize, u64, i64, u128, i128);
2212 let bincode_serialized = bincode::serialize(&val).unwrap();
2213 let schema_serialized = serialize(&val).unwrap();
2214 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2215 let bincode_deserialized: Target = bincode::deserialize(&bincode_serialized).unwrap();
2216 let schema_deserialized: Target = deserialize(&schema_serialized).unwrap();
2217 prop_assert_eq!(val, bincode_deserialized);
2218 prop_assert_eq!(val, schema_deserialized);
2219 }
2220
2221 #[test]
2222 fn test_tuple_zero_copy(
2223 tuple in (
2224 any::<StructZeroCopy>(),
2225 any::<[u8; 32]>(),
2226 )
2227 ) {
2228 let bincode_serialized = bincode::serialize(&tuple).unwrap();
2229 let schema_serialized = serialize(&tuple).unwrap();
2230
2231 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2232 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2233 let schema_deserialized = deserialize(&schema_serialized).unwrap();
2234 prop_assert_eq!(&tuple, &bincode_deserialized);
2235 prop_assert_eq!(&tuple, &schema_deserialized);
2236
2237 }
2238
2239 #[test]
2240 fn test_tuple_static(
2241 tuple in (
2242 any::<StructStatic>(),
2243 any::<[u8; 32]>(),
2244 )
2245 ) {
2246 let bincode_serialized = bincode::serialize(&tuple).unwrap();
2247 let schema_serialized = serialize(&tuple).unwrap();
2248
2249 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2250 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2251 let schema_deserialized = deserialize(&schema_serialized).unwrap();
2252 prop_assert_eq!(&tuple, &bincode_deserialized);
2253 prop_assert_eq!(&tuple, &schema_deserialized);
2254
2255 }
2256
2257 #[test]
2258 fn test_tuple_non_static(
2259 tuple in (
2260 any::<StructNonStatic>(),
2261 any::<[u8; 32]>(),
2262 proptest::collection::vec(any::<StructStatic>(), 0..=100),
2263 )
2264 ) {
2265 let bincode_serialized = bincode::serialize(&tuple).unwrap();
2266 type BincodeTarget = (StructNonStatic, [u8; 32], Vec<StructStatic>);
2267 type Target = (StructNonStatic, Pod<[u8; 32]>, Vec<StructStatic>);
2268 let schema_serialized = Target::serialize(&tuple).unwrap();
2269
2270 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2271 let bincode_deserialized: BincodeTarget = bincode::deserialize(&bincode_serialized).unwrap();
2272 let schema_deserialized = Target::deserialize(&schema_serialized).unwrap();
2273 prop_assert_eq!(&tuple, &bincode_deserialized);
2274 prop_assert_eq!(&tuple, &schema_deserialized);
2275
2276 }
2277
2278 #[test]
2279 fn test_str(str in any::<String>()) {
2280 let bincode_serialized = bincode::serialize(&str).unwrap();
2281 let schema_serialized = serialize(&str).unwrap();
2282 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2283 let bincode_deserialized: &str = bincode::deserialize(&bincode_serialized).unwrap();
2284 let schema_deserialized: &str = deserialize(&schema_serialized).unwrap();
2285 prop_assert_eq!(&str, &bincode_deserialized);
2286 prop_assert_eq!(&str, &schema_deserialized);
2287
2288 let bincode_deserialized: String = bincode::deserialize(&bincode_serialized).unwrap();
2289 let schema_deserialized: String = deserialize(&schema_serialized).unwrap();
2290 prop_assert_eq!(&str, &bincode_deserialized);
2291 prop_assert_eq!(&str, &schema_deserialized);
2292 }
2293
2294 #[test]
2295 fn test_struct_zero_copy(val in any::<StructZeroCopy>()) {
2296 let bincode_serialized = bincode::serialize(&val).unwrap();
2297 let schema_serialized = serialize(&val).unwrap();
2298 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2299
2300 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2301 let schema_deserialized = deserialize(&schema_serialized).unwrap();
2302 prop_assert_eq!(&val, &bincode_deserialized);
2303 prop_assert_eq!(&val, &schema_deserialized);
2304 }
2305
2306 #[test]
2307 fn test_struct_static(val in any::<StructStatic>()) {
2308 let bincode_serialized = bincode::serialize(&val).unwrap();
2309 let schema_serialized = serialize(&val).unwrap();
2310 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2311
2312 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2313 let schema_deserialized = deserialize(&schema_serialized).unwrap();
2314 prop_assert_eq!(&val, &bincode_deserialized);
2315 prop_assert_eq!(&val, &schema_deserialized);
2316 }
2317
2318 #[test]
2319 fn test_struct_non_static(val in any::<StructNonStatic>()) {
2320 let bincode_serialized = bincode::serialize(&val).unwrap();
2321 let schema_serialized = serialize(&val).unwrap();
2322 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2323
2324 let bincode_deserialized = bincode::deserialize(&bincode_serialized).unwrap();
2325 let schema_deserialized = deserialize(&schema_serialized).unwrap();
2326 prop_assert_eq!(&val, &bincode_deserialized);
2327 prop_assert_eq!(&val, &schema_deserialized);
2328 }
2329
2330 #[test]
2331 fn test_floats(
2332 val in (
2333 any::<f32>(),
2334 any::<f64>(),
2335 )
2336 ) {
2337 let bincode_serialized = bincode::serialize(&val).unwrap();
2338 let schema_serialized = serialize(&val).unwrap();
2339 prop_assert_eq!(&bincode_serialized, &schema_serialized);
2340
2341 let bincode_deserialized: (f32, f64) = bincode::deserialize(&bincode_serialized).unwrap();
2342 let schema_deserialized: (f32, f64) = deserialize(&schema_serialized).unwrap();
2343 prop_assert_eq!(val, bincode_deserialized);
2344 prop_assert_eq!(val, schema_deserialized);
2345 }
2346 }
2347
2348 #[test]
2349 fn test_struct_zero_copy_refs() {
2350 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
2352 #[wincode(internal)]
2353 #[repr(C)]
2354 struct Zc {
2355 a: u8,
2356 b: [u8; 64],
2357 c: i8,
2358 d: [i8; 64],
2359 }
2360
2361 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
2363 #[wincode(internal)]
2364 #[repr(C)]
2365 struct ZcRefs<'a> {
2366 a: &'a u8,
2367 b: &'a [u8; 64],
2368 c: &'a i8,
2369 d: &'a [i8; 64],
2370 }
2371
2372 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
2374 #[wincode(internal)]
2375 #[repr(transparent)]
2376 struct ZcWrapper<'a> {
2377 data: &'a Zc,
2378 }
2379
2380 impl<'a> From<&'a ZcRefs<'a>> for Zc {
2381 fn from(value: &'a ZcRefs<'a>) -> Self {
2382 Self {
2383 a: *value.a,
2384 b: *value.b,
2385 c: *value.c,
2386 d: *value.d,
2387 }
2388 }
2389 }
2390
2391 proptest!(proptest_cfg(), |(data in any::<Zc>())| {
2392 let serialized = serialize(&data).unwrap();
2393 let deserialized = Zc::deserialize(&serialized).unwrap();
2394 assert_eq!(data, deserialized);
2395
2396 let serialized_ref = serialize(&ZcRefs { a: &data.a, b: &data.b, c: &data.c, d: &data.d }).unwrap();
2397 assert_eq!(serialized_ref, serialized);
2398 let deserialized_ref = ZcRefs::deserialize(&serialized_ref).unwrap();
2399 assert_eq!(data, (&deserialized_ref).into());
2400
2401 let serialized_wrapper = serialize(&ZcWrapper { data: &data }).unwrap();
2402 assert_eq!(serialized_wrapper, serialized);
2403 let deserialized_wrapper = ZcWrapper::deserialize(&serialized_wrapper).unwrap();
2404 assert_eq!(data, *deserialized_wrapper.data);
2405 });
2406 }
2407
2408 #[test]
2409 fn test_pod_zero_copy() {
2410 #[derive(Debug, PartialEq, Eq, proptest_derive::Arbitrary, Clone, Copy)]
2411 #[repr(transparent)]
2412 struct Address([u8; 64]);
2413
2414 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
2415 #[wincode(internal)]
2416 #[repr(C)]
2417 struct MyStruct {
2418 #[wincode(with = "Pod<_>")]
2419 address: Address,
2420 }
2421
2422 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
2423 #[wincode(internal)]
2424 struct MyStructRef<'a> {
2425 inner: &'a MyStruct,
2426 }
2427
2428 proptest!(proptest_cfg(), |(data in any::<MyStruct>())| {
2429 let serialized = serialize(&data).unwrap();
2430 let deserialized = MyStruct::deserialize(&serialized).unwrap();
2431 assert_eq!(data, deserialized);
2432
2433 let serialized_ref = serialize(&MyStructRef { inner: &data }).unwrap();
2434 assert_eq!(serialized_ref, serialized);
2435 let deserialized_ref = MyStructRef::deserialize(&serialized_ref).unwrap();
2436 assert_eq!(data, *deserialized_ref.inner);
2437 });
2438 }
2439
2440 #[test]
2441 fn test_pod_zero_copy_explicit_ref() {
2442 #[derive(Debug, PartialEq, Eq, proptest_derive::Arbitrary, Clone, Copy)]
2443 #[repr(transparent)]
2444 struct Address([u8; 64]);
2445
2446 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq)]
2447 #[wincode(internal)]
2448 struct MyStructRef<'a> {
2449 #[wincode(with = "&'a Pod<Address>")]
2450 address: &'a Address,
2451 }
2452
2453 #[derive(SchemaWrite, SchemaRead, Debug, PartialEq, Eq, proptest_derive::Arbitrary)]
2454 #[wincode(internal)]
2455 struct MyStruct {
2456 #[wincode(with = "Pod<_>")]
2457 address: Address,
2458 }
2459
2460 proptest!(proptest_cfg(), |(data in any::<MyStruct>())| {
2461 let serialized = serialize(&data).unwrap();
2462 let deserialized = MyStruct::deserialize(&serialized).unwrap();
2463 assert_eq!(data, deserialized);
2464
2465 let serialized_ref = serialize(&MyStructRef { address: &data.address }).unwrap();
2466 assert_eq!(serialized_ref, serialized);
2467 let deserialized_ref = MyStructRef::deserialize(&serialized_ref).unwrap();
2468 assert_eq!(data.address, *deserialized_ref.address);
2469 });
2470 }
2471
2472 #[test]
2473 fn test_result_basic() {
2474 proptest!(proptest_cfg(), |(value: Result<u64, String>)| {
2475 let wincode_serialized = serialize(&value).unwrap();
2476 let bincode_serialized = bincode::serialize(&value).unwrap();
2477 prop_assert_eq!(&wincode_serialized, &bincode_serialized);
2478
2479 let wincode_deserialized: Result<u64, String> = deserialize(&wincode_serialized).unwrap();
2480 let bincode_deserialized: Result<u64, String> = bincode::deserialize(&bincode_serialized).unwrap();
2481 prop_assert_eq!(&value, &wincode_deserialized);
2482 prop_assert_eq!(wincode_deserialized, bincode_deserialized);
2483 });
2484 }
2485
2486 #[test]
2487 fn test_result_bincode_equivalence() {
2488 use serde::{Deserialize, Serialize};
2489
2490 #[derive(
2491 Serialize,
2492 Deserialize,
2493 Debug,
2494 PartialEq,
2495 Clone,
2496 proptest_derive::Arbitrary,
2497 SchemaWrite,
2498 SchemaRead,
2499 )]
2500 #[wincode(internal)]
2501 enum Error {
2502 NotFound,
2503 InvalidInput(String),
2504 Other(u32),
2505 }
2506
2507 proptest!(proptest_cfg(), |(value: Result<Vec<u8>, Error>)| {
2508 let wincode_serialized = serialize(&value).unwrap();
2509 let bincode_serialized = bincode::serialize(&value).unwrap();
2510 prop_assert_eq!(&wincode_serialized, &bincode_serialized);
2511
2512 let wincode_deserialized: Result<Vec<u8>, Error> = deserialize(&wincode_serialized).unwrap();
2513 let bincode_deserialized: Result<Vec<u8>, Error> = bincode::deserialize(&bincode_serialized).unwrap();
2514 prop_assert_eq!(&value, &wincode_deserialized);
2515 prop_assert_eq!(wincode_deserialized, bincode_deserialized);
2516 });
2517 }
2518
2519 #[test]
2520 fn test_result_nested() {
2521 proptest!(proptest_cfg(), |(value: Result<Result<u64, String>, u32>)| {
2522 let wincode_serialized = serialize(&value).unwrap();
2523 let bincode_serialized = bincode::serialize(&value).unwrap();
2524 prop_assert_eq!(&wincode_serialized, &bincode_serialized);
2525
2526 let wincode_deserialized: Result<Result<u64, String>, u32> = deserialize(&wincode_serialized).unwrap();
2527 let bincode_deserialized: Result<Result<u64, String>, u32> = bincode::deserialize(&bincode_serialized).unwrap();
2528 prop_assert_eq!(&value, &wincode_deserialized);
2529 prop_assert_eq!(wincode_deserialized, bincode_deserialized);
2530 });
2531 }
2532
2533 #[test]
2534 fn test_result_with_complex_types() {
2535 use std::collections::HashMap;
2536
2537 proptest!(proptest_cfg(), |(value: Result<HashMap<String, Vec<u32>>, bool>)| {
2538 let wincode_serialized = serialize(&value).unwrap();
2539 let bincode_serialized = bincode::serialize(&value).unwrap();
2540 prop_assert_eq!(&wincode_serialized, &bincode_serialized);
2541
2542 let wincode_deserialized: Result<HashMap<String, Vec<u32>>, bool> = deserialize(&wincode_serialized).unwrap();
2543 let bincode_deserialized: Result<HashMap<String, Vec<u32>>, bool> = bincode::deserialize(&bincode_serialized).unwrap();
2544 prop_assert_eq!(&value, &wincode_deserialized);
2545 prop_assert_eq!(wincode_deserialized, bincode_deserialized);
2546 });
2547 }
2548
2549 #[test]
2550 fn test_result_type_meta_static() {
2551 assert!(matches!(
2553 <Result<u64, u64> as SchemaRead>::TYPE_META,
2554 TypeMeta::Static {
2555 size: 12,
2556 zero_copy: false
2557 }
2558 ));
2559
2560 proptest!(proptest_cfg(), |(value: Result<u64, u64>)| {
2561 let wincode_serialized = serialize(&value).unwrap();
2562 let bincode_serialized = bincode::serialize(&value).unwrap();
2563 prop_assert_eq!(&wincode_serialized, &bincode_serialized);
2564
2565 let wincode_deserialized: Result<u64, u64> = deserialize(&wincode_serialized).unwrap();
2566 let bincode_deserialized: Result<u64, u64> = bincode::deserialize(&bincode_serialized).unwrap();
2567 prop_assert_eq!(&value, &wincode_deserialized);
2568 prop_assert_eq!(wincode_deserialized, bincode_deserialized);
2569 });
2570 }
2571
2572 #[test]
2573 fn test_result_type_meta_dynamic() {
2574 assert!(matches!(
2576 <Result<u64, String> as SchemaRead>::TYPE_META,
2577 TypeMeta::Dynamic
2578 ));
2579
2580 proptest!(proptest_cfg(), |(value: Result<u64, String>)| {
2581 let wincode_serialized = serialize(&value).unwrap();
2582 let bincode_serialized = bincode::serialize(&value).unwrap();
2583 prop_assert_eq!(&wincode_serialized, &bincode_serialized);
2584
2585 let wincode_deserialized: Result<u64, String> = deserialize(&wincode_serialized).unwrap();
2586 let bincode_deserialized: Result<u64, String> = bincode::deserialize(&bincode_serialized).unwrap();
2587 prop_assert_eq!(&value, &wincode_deserialized);
2588 prop_assert_eq!(wincode_deserialized, bincode_deserialized);
2589 });
2590 }
2591
2592 #[test]
2593 fn test_result_type_meta_different_sizes() {
2594 assert!(matches!(
2596 <Result<u64, u32> as SchemaRead>::TYPE_META,
2597 TypeMeta::Dynamic
2598 ));
2599
2600 proptest!(proptest_cfg(), |(value: Result<u64, u32>)| {
2601 let wincode_serialized = serialize(&value).unwrap();
2602 let bincode_serialized = bincode::serialize(&value).unwrap();
2603 prop_assert_eq!(&wincode_serialized, &bincode_serialized);
2604
2605 let wincode_deserialized: Result<u64, u32> = deserialize(&wincode_serialized).unwrap();
2606 let bincode_deserialized: Result<u64, u32> = bincode::deserialize(&bincode_serialized).unwrap();
2607 prop_assert_eq!(&value, &wincode_deserialized);
2608 prop_assert_eq!(wincode_deserialized, bincode_deserialized);
2609 });
2610 }
2611
2612 struct BufAligned<T> {
2618 buf: Box<[T]>,
2619 }
2620
2621 impl<T> Deref for BufAligned<T>
2622 where
2623 T: ZeroCopy,
2624 {
2625 type Target = [u8];
2626
2627 fn deref(&self) -> &Self::Target {
2628 unsafe {
2629 core::slice::from_raw_parts(
2630 self.buf.as_ptr() as *const u8,
2631 self.buf.len() * size_of::<T>(),
2632 )
2633 }
2634 }
2635 }
2636
2637 impl<T> DerefMut for BufAligned<T>
2638 where
2639 T: ZeroCopy,
2640 {
2641 fn deref_mut(&mut self) -> &mut Self::Target {
2642 unsafe {
2643 core::slice::from_raw_parts_mut(
2644 self.buf.as_mut_ptr() as *mut u8,
2645 self.buf.len() * size_of::<T>(),
2646 )
2647 }
2648 }
2649 }
2650
2651 fn serialize_aligned<T>(src: &T) -> WriteResult<BufAligned<T>>
2653 where
2654 T: SchemaWrite<Src = T> + ZeroCopy,
2655 {
2656 assert_eq!(T::size_of(src)?, size_of::<T>());
2657 let mut b: Box<[MaybeUninit<T>]> = Box::new_uninit_slice(1);
2658 let mut buf =
2659 unsafe { core::slice::from_raw_parts_mut(b.as_mut_ptr() as *mut u8, size_of::<T>()) };
2660 crate::serialize_into(&mut buf, src)?;
2661 Ok(BufAligned {
2662 buf: unsafe { b.assume_init() },
2663 })
2664 }
2665
2666 #[test]
2667 fn test_zero_copy_mut_roundrip() {
2668 proptest!(proptest_cfg(), |(data: StructZeroCopy, data_rand: StructZeroCopy)| {
2669 let mut serialized = serialize_aligned(&data).unwrap();
2670 let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
2671 prop_assert_eq!(deserialized, data);
2672
2673
2674 {
2676 let ref_mut = StructZeroCopy::from_bytes_mut(&mut serialized).unwrap();
2677 *ref_mut = data_rand;
2678 }
2679 let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
2682 prop_assert_eq!(deserialized, data_rand);
2683 });
2684 }
2685
2686 #[test]
2687 fn test_deserialize_mut_roundrip() {
2688 proptest!(proptest_cfg(), |(data: StructZeroCopy, data_rand: StructZeroCopy)| {
2689 let mut serialized = serialize_aligned(&data).unwrap();
2690 let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
2691 prop_assert_eq!(deserialized, data);
2692
2693
2694 {
2696 let ref_mut: &mut StructZeroCopy = deserialize_mut(&mut serialized).unwrap();
2697 *ref_mut = data_rand;
2698 }
2699 let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
2702 prop_assert_eq!(deserialized, data_rand);
2703 });
2704 }
2705
2706 #[test]
2707 fn test_zero_copy_deserialize_ref() {
2708 proptest!(proptest_cfg(), |(data: StructZeroCopy)| {
2709 let serialized = serialize_aligned(&data).unwrap();
2710 let deserialized: StructZeroCopy = deserialize(&serialized).unwrap();
2711 prop_assert_eq!(deserialized, data);
2712
2713 let ref_data = StructZeroCopy::from_bytes(&serialized).unwrap();
2714 prop_assert_eq!(ref_data, &data);
2715 });
2716 }
2717
2718 #[test]
2719 #[cfg(feature = "bytes")]
2720 fn test_bytes_roundtrip() {
2721 proptest!(proptest_cfg(), |(data in proptest::collection::vec(any::<u8>(), 0..1000).prop_map(bytes::Bytes::from))| {
2722 let serialized = serialize(&data).unwrap();
2723 let deserialized: bytes::Bytes = deserialize(&serialized).unwrap();
2724 prop_assert_eq!(data, deserialized);
2725 });
2726 }
2727
2728 #[test]
2729 #[cfg(feature = "bytes")]
2730 fn test_bytes_mut_roundtrip() {
2731 proptest!(proptest_cfg(), |(data in proptest::collection::vec(any::<u8>(), 0..1000).prop_map(|v| bytes::BytesMut::from(v.as_slice())))| {
2732 let serialized = serialize(&data).unwrap();
2733 let deserialized: bytes::BytesMut = deserialize(&serialized).unwrap();
2734 prop_assert_eq!(data, deserialized);
2735 });
2736 }
2737}