1use super::*;
27use core::fmt;
28
29macro_rules! tuple_ule {
30 ($name:ident, $len:literal, [ $($t:ident $i:tt),+ ]) => {
31 #[doc = concat!("ULE type for tuples with ", $len, " elements.")]
32 #[repr(C, packed)]
33 #[allow(clippy::exhaustive_structs)] pub struct $name<$($t),+>($(pub $t),+);
35
36 unsafe impl<$($t: ULE),+> ULE for $name<$($t),+> {
47 fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
48 let ule_bytes = 0usize $(+ size_of::<$t>())+;
50 if bytes.len() % ule_bytes != 0 {
51 return Err(UleError::length::<Self>(bytes.len()));
52 }
53 for chunk in bytes.chunks(ule_bytes) {
54 let mut i = 0;
55 $(
56 let j = i;
57 i += size_of::<$t>();
58 #[expect(clippy::indexing_slicing)] <$t>::validate_bytes(&chunk[j..i])?;
60 )+
61 }
62 Ok(())
63 }
64 }
65
66 impl<$($t: AsULE),+> AsULE for ($($t),+) {
67 type ULE = $name<$(<$t>::ULE),+>;
68
69 #[inline]
70 fn to_unaligned(self) -> Self::ULE {
71 $name($(
72 self.$i.to_unaligned()
73 ),+)
74 }
75
76 #[inline]
77 fn from_unaligned(unaligned: Self::ULE) -> Self {
78 ($(
79 <$t>::from_unaligned(unaligned.$i)
80 ),+)
81 }
82 }
83
84 impl<$($t: fmt::Debug + ULE),+> fmt::Debug for $name<$($t),+> {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
86 ($(self.$i),+).fmt(f)
87 }
88 }
89
90 impl<$($t: PartialEq + ULE),+> PartialEq for $name<$($t),+> {
92 fn eq(&self, other: &Self) -> bool {
93 ($(self.$i),+).eq(&($(other.$i),+))
94 }
95 }
96
97 impl<$($t: Eq + ULE),+> Eq for $name<$($t),+> {}
98
99 impl<$($t: PartialOrd + ULE),+> PartialOrd for $name<$($t),+> {
100 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
101 ($(self.$i),+).partial_cmp(&($(other.$i),+))
102 }
103 }
104
105 impl<$($t: Ord + ULE),+> Ord for $name<$($t),+> {
106 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
107 ($(self.$i),+).cmp(&($(other.$i),+))
108 }
109 }
110
111 impl<$($t: ULE),+> Clone for $name<$($t),+> {
112 fn clone(&self) -> Self {
113 *self
114 }
115 }
116
117 impl<$($t: ULE),+> Copy for $name<$($t),+> {}
118
119 #[cfg(feature = "alloc")]
120 impl<'a, $($t: Ord + AsULE + 'static),+> crate::map::ZeroMapKV<'a> for ($($t),+) {
121 type Container = crate::ZeroVec<'a, ($($t),+)>;
122 type Slice = crate::ZeroSlice<($($t),+)>;
123 type GetType = $name<$(<$t>::ULE),+>;
124 type OwnedType = ($($t),+);
125 }
126 };
127}
128
129#[doc = "ULE type for tuples with 2 elements."]
#[repr(C, packed)]
#[allow(clippy :: exhaustive_structs)]
pub struct Tuple2ULE<A, B>(pub A, pub B);
unsafe impl<A: ULE, B: ULE> ULE for Tuple2ULE<A, B> {
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
let ule_bytes = 0usize + size_of::<A>() + size_of::<B>();
if bytes.len() % ule_bytes != 0 {
return Err(UleError::length::<Self>(bytes.len()));
}
for chunk in bytes.chunks(ule_bytes) {
let mut i = 0;
let j = i;
i += size_of::<A>();
#[expect(clippy :: indexing_slicing)]
<A>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<B>();
#[expect(clippy :: indexing_slicing)]
<B>::validate_bytes(&chunk[j..i])?;
}
Ok(())
}
}
impl<A: AsULE, B: AsULE> AsULE for (A, B) {
type ULE = Tuple2ULE<<A>::ULE, <B>::ULE>;
#[inline]
fn to_unaligned(self) -> Self::ULE {
Tuple2ULE(self.0.to_unaligned(), self.1.to_unaligned())
}
#[inline]
fn from_unaligned(unaligned: Self::ULE) -> Self {
(<A>::from_unaligned(unaligned.0), <B>::from_unaligned(unaligned.1))
}
}
impl<A: fmt::Debug + ULE, B: fmt::Debug + ULE> fmt::Debug for Tuple2ULE<A, B>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
(self.0, self.1).fmt(f)
}
}
impl<A: PartialEq + ULE, B: PartialEq + ULE> PartialEq for Tuple2ULE<A, B> {
fn eq(&self, other: &Self) -> bool {
(self.0, self.1).eq(&(other.0, other.1))
}
}
impl<A: Eq + ULE, B: Eq + ULE> Eq for Tuple2ULE<A, B> {}
impl<A: PartialOrd + ULE, B: PartialOrd + ULE> PartialOrd for Tuple2ULE<A, B>
{
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
(self.0, self.1).partial_cmp(&(other.0, other.1))
}
}
impl<A: Ord + ULE, B: Ord + ULE> Ord for Tuple2ULE<A, B> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(self.0, self.1).cmp(&(other.0, other.1))
}
}
impl<A: ULE, B: ULE> Clone for Tuple2ULE<A, B> {
fn clone(&self) -> Self { *self }
}
impl<A: ULE, B: ULE> Copy for Tuple2ULE<A, B> {}tuple_ule!(Tuple2ULE, "2", [ A 0, B 1 ]);
130#[doc = "ULE type for tuples with 3 elements."]
#[repr(C, packed)]
#[allow(clippy :: exhaustive_structs)]
pub struct Tuple3ULE<A, B, C>(pub A, pub B, pub C);
unsafe impl<A: ULE, B: ULE, C: ULE> ULE for Tuple3ULE<A, B, C> {
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
let ule_bytes =
0usize + size_of::<A>() + size_of::<B>() + size_of::<C>();
if bytes.len() % ule_bytes != 0 {
return Err(UleError::length::<Self>(bytes.len()));
}
for chunk in bytes.chunks(ule_bytes) {
let mut i = 0;
let j = i;
i += size_of::<A>();
#[expect(clippy :: indexing_slicing)]
<A>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<B>();
#[expect(clippy :: indexing_slicing)]
<B>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<C>();
#[expect(clippy :: indexing_slicing)]
<C>::validate_bytes(&chunk[j..i])?;
}
Ok(())
}
}
impl<A: AsULE, B: AsULE, C: AsULE> AsULE for (A, B, C) {
type ULE = Tuple3ULE<<A>::ULE, <B>::ULE, <C>::ULE>;
#[inline]
fn to_unaligned(self) -> Self::ULE {
Tuple3ULE(self.0.to_unaligned(), self.1.to_unaligned(),
self.2.to_unaligned())
}
#[inline]
fn from_unaligned(unaligned: Self::ULE) -> Self {
(<A>::from_unaligned(unaligned.0), <B>::from_unaligned(unaligned.1),
<C>::from_unaligned(unaligned.2))
}
}
impl<A: fmt::Debug + ULE, B: fmt::Debug + ULE, C: fmt::Debug + ULE> fmt::Debug
for Tuple3ULE<A, B, C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
(self.0, self.1, self.2).fmt(f)
}
}
impl<A: PartialEq + ULE, B: PartialEq + ULE, C: PartialEq + ULE> PartialEq for
Tuple3ULE<A, B, C> {
fn eq(&self, other: &Self) -> bool {
(self.0, self.1, self.2).eq(&(other.0, other.1, other.2))
}
}
impl<A: Eq + ULE, B: Eq + ULE, C: Eq + ULE> Eq for Tuple3ULE<A, B, C> {}
impl<A: PartialOrd + ULE, B: PartialOrd + ULE, C: PartialOrd + ULE> PartialOrd
for Tuple3ULE<A, B, C> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
(self.0, self.1, self.2).partial_cmp(&(other.0, other.1, other.2))
}
}
impl<A: Ord + ULE, B: Ord + ULE, C: Ord + ULE> Ord for Tuple3ULE<A, B, C> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(self.0, self.1, self.2).cmp(&(other.0, other.1, other.2))
}
}
impl<A: ULE, B: ULE, C: ULE> Clone for Tuple3ULE<A, B, C> {
fn clone(&self) -> Self { *self }
}
impl<A: ULE, B: ULE, C: ULE> Copy for Tuple3ULE<A, B, C> {}tuple_ule!(Tuple3ULE, "3", [ A 0, B 1, C 2 ]);
131#[doc = "ULE type for tuples with 4 elements."]
#[repr(C, packed)]
#[allow(clippy :: exhaustive_structs)]
pub struct Tuple4ULE<A, B, C, D>(pub A, pub B, pub C, pub D);
unsafe impl<A: ULE, B: ULE, C: ULE, D: ULE> ULE for Tuple4ULE<A, B, C, D> {
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
let ule_bytes =
0usize + size_of::<A>() + size_of::<B>() + size_of::<C>() +
size_of::<D>();
if bytes.len() % ule_bytes != 0 {
return Err(UleError::length::<Self>(bytes.len()));
}
for chunk in bytes.chunks(ule_bytes) {
let mut i = 0;
let j = i;
i += size_of::<A>();
#[expect(clippy :: indexing_slicing)]
<A>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<B>();
#[expect(clippy :: indexing_slicing)]
<B>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<C>();
#[expect(clippy :: indexing_slicing)]
<C>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<D>();
#[expect(clippy :: indexing_slicing)]
<D>::validate_bytes(&chunk[j..i])?;
}
Ok(())
}
}
impl<A: AsULE, B: AsULE, C: AsULE, D: AsULE> AsULE for (A, B, C, D) {
type ULE = Tuple4ULE<<A>::ULE, <B>::ULE, <C>::ULE, <D>::ULE>;
#[inline]
fn to_unaligned(self) -> Self::ULE {
Tuple4ULE(self.0.to_unaligned(), self.1.to_unaligned(),
self.2.to_unaligned(), self.3.to_unaligned())
}
#[inline]
fn from_unaligned(unaligned: Self::ULE) -> Self {
(<A>::from_unaligned(unaligned.0), <B>::from_unaligned(unaligned.1),
<C>::from_unaligned(unaligned.2),
<D>::from_unaligned(unaligned.3))
}
}
impl<A: fmt::Debug + ULE, B: fmt::Debug + ULE, C: fmt::Debug + ULE,
D: fmt::Debug + ULE> fmt::Debug for Tuple4ULE<A, B, C, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
(self.0, self.1, self.2, self.3).fmt(f)
}
}
impl<A: PartialEq + ULE, B: PartialEq + ULE, C: PartialEq + ULE,
D: PartialEq + ULE> PartialEq for Tuple4ULE<A, B, C, D> {
fn eq(&self, other: &Self) -> bool {
(self.0, self.1, self.2,
self.3).eq(&(other.0, other.1, other.2, other.3))
}
}
impl<A: Eq + ULE, B: Eq + ULE, C: Eq + ULE, D: Eq + ULE> Eq for
Tuple4ULE<A, B, C, D> {}
impl<A: PartialOrd + ULE, B: PartialOrd + ULE, C: PartialOrd + ULE,
D: PartialOrd + ULE> PartialOrd for Tuple4ULE<A, B, C, D> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
(self.0, self.1, self.2,
self.3).partial_cmp(&(other.0, other.1, other.2, other.3))
}
}
impl<A: Ord + ULE, B: Ord + ULE, C: Ord + ULE, D: Ord + ULE> Ord for
Tuple4ULE<A, B, C, D> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(self.0, self.1, self.2,
self.3).cmp(&(other.0, other.1, other.2, other.3))
}
}
impl<A: ULE, B: ULE, C: ULE, D: ULE> Clone for Tuple4ULE<A, B, C, D> {
fn clone(&self) -> Self { *self }
}
impl<A: ULE, B: ULE, C: ULE, D: ULE> Copy for Tuple4ULE<A, B, C, D> {}tuple_ule!(Tuple4ULE, "4", [ A 0, B 1, C 2, D 3 ]);
132#[doc = "ULE type for tuples with 5 elements."]
#[repr(C, packed)]
#[allow(clippy :: exhaustive_structs)]
pub struct Tuple5ULE<A, B, C, D, E>(pub A, pub B, pub C, pub D, pub E);
unsafe impl<A: ULE, B: ULE, C: ULE, D: ULE, E: ULE> ULE for
Tuple5ULE<A, B, C, D, E> {
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
let ule_bytes =
0usize + size_of::<A>() + size_of::<B>() + size_of::<C>() +
size_of::<D>() + size_of::<E>();
if bytes.len() % ule_bytes != 0 {
return Err(UleError::length::<Self>(bytes.len()));
}
for chunk in bytes.chunks(ule_bytes) {
let mut i = 0;
let j = i;
i += size_of::<A>();
#[expect(clippy :: indexing_slicing)]
<A>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<B>();
#[expect(clippy :: indexing_slicing)]
<B>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<C>();
#[expect(clippy :: indexing_slicing)]
<C>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<D>();
#[expect(clippy :: indexing_slicing)]
<D>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<E>();
#[expect(clippy :: indexing_slicing)]
<E>::validate_bytes(&chunk[j..i])?;
}
Ok(())
}
}
impl<A: AsULE, B: AsULE, C: AsULE, D: AsULE, E: AsULE> AsULE for
(A, B, C, D, E) {
type ULE = Tuple5ULE<<A>::ULE, <B>::ULE, <C>::ULE, <D>::ULE, <E>::ULE>;
#[inline]
fn to_unaligned(self) -> Self::ULE {
Tuple5ULE(self.0.to_unaligned(), self.1.to_unaligned(),
self.2.to_unaligned(), self.3.to_unaligned(),
self.4.to_unaligned())
}
#[inline]
fn from_unaligned(unaligned: Self::ULE) -> Self {
(<A>::from_unaligned(unaligned.0), <B>::from_unaligned(unaligned.1),
<C>::from_unaligned(unaligned.2),
<D>::from_unaligned(unaligned.3),
<E>::from_unaligned(unaligned.4))
}
}
impl<A: fmt::Debug + ULE, B: fmt::Debug + ULE, C: fmt::Debug + ULE,
D: fmt::Debug + ULE, E: fmt::Debug + ULE> fmt::Debug for
Tuple5ULE<A, B, C, D, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
(self.0, self.1, self.2, self.3, self.4).fmt(f)
}
}
impl<A: PartialEq + ULE, B: PartialEq + ULE, C: PartialEq + ULE,
D: PartialEq + ULE, E: PartialEq + ULE> PartialEq for
Tuple5ULE<A, B, C, D, E> {
fn eq(&self, other: &Self) -> bool {
(self.0, self.1, self.2, self.3,
self.4).eq(&(other.0, other.1, other.2, other.3, other.4))
}
}
impl<A: Eq + ULE, B: Eq + ULE, C: Eq + ULE, D: Eq + ULE, E: Eq + ULE> Eq for
Tuple5ULE<A, B, C, D, E> {}
impl<A: PartialOrd + ULE, B: PartialOrd + ULE, C: PartialOrd + ULE,
D: PartialOrd + ULE, E: PartialOrd + ULE> PartialOrd for
Tuple5ULE<A, B, C, D, E> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
(self.0, self.1, self.2, self.3,
self.4).partial_cmp(&(other.0, other.1, other.2, other.3,
other.4))
}
}
impl<A: Ord + ULE, B: Ord + ULE, C: Ord + ULE, D: Ord + ULE, E: Ord + ULE> Ord
for Tuple5ULE<A, B, C, D, E> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(self.0, self.1, self.2, self.3,
self.4).cmp(&(other.0, other.1, other.2, other.3, other.4))
}
}
impl<A: ULE, B: ULE, C: ULE, D: ULE, E: ULE> Clone for
Tuple5ULE<A, B, C, D, E> {
fn clone(&self) -> Self { *self }
}
impl<A: ULE, B: ULE, C: ULE, D: ULE, E: ULE> Copy for Tuple5ULE<A, B, C, D, E>
{}tuple_ule!(Tuple5ULE, "5", [ A 0, B 1, C 2, D 3, E 4 ]);
133#[doc = "ULE type for tuples with 6 elements."]
#[repr(C, packed)]
#[allow(clippy :: exhaustive_structs)]
pub struct Tuple6ULE<A, B, C, D, E,
F>(pub A, pub B, pub C, pub D, pub E, pub F);
unsafe impl<A: ULE, B: ULE, C: ULE, D: ULE, E: ULE, F: ULE> ULE for
Tuple6ULE<A, B, C, D, E, F> {
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
let ule_bytes =
0usize + size_of::<A>() + size_of::<B>() + size_of::<C>() +
size_of::<D>() + size_of::<E>() + size_of::<F>();
if bytes.len() % ule_bytes != 0 {
return Err(UleError::length::<Self>(bytes.len()));
}
for chunk in bytes.chunks(ule_bytes) {
let mut i = 0;
let j = i;
i += size_of::<A>();
#[expect(clippy :: indexing_slicing)]
<A>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<B>();
#[expect(clippy :: indexing_slicing)]
<B>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<C>();
#[expect(clippy :: indexing_slicing)]
<C>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<D>();
#[expect(clippy :: indexing_slicing)]
<D>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<E>();
#[expect(clippy :: indexing_slicing)]
<E>::validate_bytes(&chunk[j..i])?;
let j = i;
i += size_of::<F>();
#[expect(clippy :: indexing_slicing)]
<F>::validate_bytes(&chunk[j..i])?;
}
Ok(())
}
}
impl<A: AsULE, B: AsULE, C: AsULE, D: AsULE, E: AsULE, F: AsULE> AsULE for
(A, B, C, D, E, F) {
type ULE =
Tuple6ULE<<A>::ULE, <B>::ULE, <C>::ULE, <D>::ULE, <E>::ULE, <F>::ULE>;
#[inline]
fn to_unaligned(self) -> Self::ULE {
Tuple6ULE(self.0.to_unaligned(), self.1.to_unaligned(),
self.2.to_unaligned(), self.3.to_unaligned(),
self.4.to_unaligned(), self.5.to_unaligned())
}
#[inline]
fn from_unaligned(unaligned: Self::ULE) -> Self {
(<A>::from_unaligned(unaligned.0), <B>::from_unaligned(unaligned.1),
<C>::from_unaligned(unaligned.2),
<D>::from_unaligned(unaligned.3),
<E>::from_unaligned(unaligned.4),
<F>::from_unaligned(unaligned.5))
}
}
impl<A: fmt::Debug + ULE, B: fmt::Debug + ULE, C: fmt::Debug + ULE,
D: fmt::Debug + ULE, E: fmt::Debug + ULE, F: fmt::Debug + ULE> fmt::Debug
for Tuple6ULE<A, B, C, D, E, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
(self.0, self.1, self.2, self.3, self.4, self.5).fmt(f)
}
}
impl<A: PartialEq + ULE, B: PartialEq + ULE, C: PartialEq + ULE,
D: PartialEq + ULE, E: PartialEq + ULE, F: PartialEq + ULE> PartialEq for
Tuple6ULE<A, B, C, D, E, F> {
fn eq(&self, other: &Self) -> bool {
(self.0, self.1, self.2, self.3, self.4,
self.5).eq(&(other.0, other.1, other.2, other.3, other.4,
other.5))
}
}
impl<A: Eq + ULE, B: Eq + ULE, C: Eq + ULE, D: Eq + ULE, E: Eq + ULE, F: Eq +
ULE> Eq for Tuple6ULE<A, B, C, D, E, F> {}
impl<A: PartialOrd + ULE, B: PartialOrd + ULE, C: PartialOrd + ULE,
D: PartialOrd + ULE, E: PartialOrd + ULE, F: PartialOrd + ULE> PartialOrd
for Tuple6ULE<A, B, C, D, E, F> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
(self.0, self.1, self.2, self.3, self.4,
self.5).partial_cmp(&(other.0, other.1, other.2, other.3,
other.4, other.5))
}
}
impl<A: Ord + ULE, B: Ord + ULE, C: Ord + ULE, D: Ord + ULE, E: Ord + ULE,
F: Ord + ULE> Ord for Tuple6ULE<A, B, C, D, E, F> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(self.0, self.1, self.2, self.3, self.4,
self.5).cmp(&(other.0, other.1, other.2, other.3, other.4,
other.5))
}
}
impl<A: ULE, B: ULE, C: ULE, D: ULE, E: ULE, F: ULE> Clone for
Tuple6ULE<A, B, C, D, E, F> {
fn clone(&self) -> Self { *self }
}
impl<A: ULE, B: ULE, C: ULE, D: ULE, E: ULE, F: ULE> Copy for
Tuple6ULE<A, B, C, D, E, F> {}tuple_ule!(Tuple6ULE, "6", [ A 0, B 1, C 2, D 3, E 4, F 5 ]);
134
135#[test]
136fn test_pairule_validate() {
137 use crate::ZeroVec;
138 let vec: Vec<(u32, char)> = vec![(1, 'a'), (1234901, '啊'), (100, 'अ')];
139 let zerovec: ZeroVec<(u32, char)> = vec.iter().copied().collect();
140 let bytes = zerovec.as_bytes();
141 let zerovec2 = ZeroVec::parse_bytes(bytes).unwrap();
142 assert_eq!(zerovec, zerovec2);
143
144 let zerovec3 = ZeroVec::<(char, u32)>::parse_bytes(bytes);
147 assert!(zerovec3.is_err());
148}
149
150#[test]
151fn test_tripleule_validate() {
152 use crate::ZeroVec;
153 let vec: Vec<(u32, char, i8)> = vec![(1, 'a', -5), (1234901, '啊', 3), (100, 'अ', -127)];
154 let zerovec: ZeroVec<(u32, char, i8)> = vec.iter().copied().collect();
155 let bytes = zerovec.as_bytes();
156 let zerovec2 = ZeroVec::parse_bytes(bytes).unwrap();
157 assert_eq!(zerovec, zerovec2);
158
159 let zerovec3 = ZeroVec::<(char, i8, u32)>::parse_bytes(bytes);
162 assert!(zerovec3.is_err());
163}
164
165#[test]
166fn test_quadule_validate() {
167 use crate::ZeroVec;
168 let vec: Vec<(u32, char, i8, u16)> =
169 vec![(1, 'a', -5, 3), (1234901, '啊', 3, 11), (100, 'अ', -127, 0)];
170 let zerovec: ZeroVec<(u32, char, i8, u16)> = vec.iter().copied().collect();
171 let bytes = zerovec.as_bytes();
172 let zerovec2 = ZeroVec::parse_bytes(bytes).unwrap();
173 assert_eq!(zerovec, zerovec2);
174
175 let zerovec3 = ZeroVec::<(char, i8, u16, u32)>::parse_bytes(bytes);
178 assert!(zerovec3.is_err());
179}