/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerovec-0.11.6/src/ule/tuplevar.rs
Line | Count | Source |
1 | | // This file is part of ICU4X. For terms of use, please see the file |
2 | | // called LICENSE at the top level of the ICU4X source tree |
3 | | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
4 | | |
5 | | //! [`VarULE`] impls for tuples. |
6 | | //! |
7 | | //! This module exports [`Tuple2VarULE`], [`Tuple3VarULE`], ..., the corresponding [`VarULE`] types |
8 | | //! of tuples containing purely [`VarULE`] types. |
9 | | //! |
10 | | //! This can be paired with [`VarTupleULE`] to make arbitrary combinations of [`ULE`] and [`VarULE`] types. |
11 | | //! |
12 | | //! [`VarTupleULE`]: crate::ule::vartuple::VarTupleULE |
13 | | |
14 | | use super::*; |
15 | | use crate::varzerovec::{Index16, VarZeroVecFormat}; |
16 | | use core::fmt; |
17 | | use core::marker::PhantomData; |
18 | | use zerofrom::ZeroFrom; |
19 | | |
20 | | macro_rules! tuple_varule { |
21 | | // Invocation: Should be called like `tuple_ule!(Tuple2VarULE, 2, [ A a AX 0, B b BX 1 ])` |
22 | | // |
23 | | // $T is a generic name, $t is a lowercase version of it, $T_alt is an "alternate" name to use when we need two types referring |
24 | | // to the same input field, $i is an index. |
25 | | // |
26 | | // $name is the name of the type, $len MUST be the total number of fields, and then $i must be an integer going from 0 to (n - 1) in sequence |
27 | | // (This macro code can rely on $i < $len) |
28 | | ($name:ident, $len:literal, [ $($T:ident $t:ident $T_alt: ident $i:tt),+ ]) => { |
29 | | #[doc = concat!("VarULE type for tuples with ", $len, " elements. See module docs for more information")] |
30 | | #[repr(transparent)] |
31 | | #[allow(clippy::exhaustive_structs)] // stable |
32 | | pub struct $name<$($T: ?Sized,)+ Format: VarZeroVecFormat = Index16> { |
33 | | $($t: PhantomData<$T>,)+ |
34 | | // Safety invariant: Each "field" $i of the MultiFieldsULE is a valid instance of $t |
35 | | // |
36 | | // In other words, calling `.get_field::<$T>($i)` is always safe. |
37 | | // |
38 | | // This invariant is upheld when this type is constructed during VarULE parsing/validation |
39 | | multi: MultiFieldsULE<$len, Format> |
40 | | } |
41 | | |
42 | | impl<$($T: VarULE + ?Sized,)+ Format: VarZeroVecFormat> $name<$($T,)+ Format> { |
43 | | $( |
44 | | #[doc = concat!("Get field ", $i, "of this tuple")] |
45 | 0 | pub fn $t(&self) -> &$T { |
46 | | // Safety: See invariant of `multi`. |
47 | | unsafe { |
48 | 0 | self.multi.get_field::<$T>($i) |
49 | | } |
50 | 0 | } Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple2VarULE<_, _, _>>::a Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple2VarULE<_, _, _>>::b Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _>>::a Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _>>::b Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _>>::c Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _>>::a Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _>>::b Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _>>::c Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _>>::d Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>::a Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>::b Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>::c Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>::d Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>::e Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>::a Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>::b Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>::c Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>::d Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>::e Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>::f |
51 | | |
52 | | |
53 | | )+ |
54 | | } |
55 | | |
56 | | // # Safety |
57 | | // |
58 | | // ## Checklist |
59 | | // |
60 | | // Safety checklist for `VarULE`: |
61 | | // |
62 | | // 1. align(1): repr(transparent) around an align(1) VarULE type: MultiFieldsULE |
63 | | // 2. No padding: see previous point |
64 | | // 3. `validate_bytes` validates that this type is a valid MultiFieldsULE, and that each field is the correct type from the tuple. |
65 | | // 4. `validate_bytes` checks length by deferring to the inner ULEs |
66 | | // 5. `from_bytes_unchecked` returns a fat pointer to the bytes. |
67 | | // 6. All other methods are left at their default impl. |
68 | | // 7. The inner ULEs have byte equality, so this composition has byte equality. |
69 | | unsafe impl<$($T: VarULE + ?Sized,)+ Format: VarZeroVecFormat> VarULE for $name<$($T,)+ Format> |
70 | | { |
71 | 0 | fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> { |
72 | | // Safety: We validate that this type is the same kind of MultiFieldsULE (with $len, Format) |
73 | | // as in the type def |
74 | 0 | let multi = <MultiFieldsULE<$len, Format> as VarULE>::parse_bytes(bytes)?; |
75 | | $( |
76 | | // Safety invariant: $i < $len, from the macro invocation |
77 | | unsafe { |
78 | 0 | multi.validate_field::<$T>($i)?; |
79 | | } |
80 | | )+ |
81 | 0 | Ok(()) |
82 | 0 | } Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _> as zerovec::ule::VarULE>::validate_bytes Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple2VarULE<_, _, _> as zerovec::ule::VarULE>::validate_bytes Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _> as zerovec::ule::VarULE>::validate_bytes Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _> as zerovec::ule::VarULE>::validate_bytes Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _> as zerovec::ule::VarULE>::validate_bytes |
83 | | |
84 | 0 | unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self { |
85 | | // Safety: We validate that this type is the same kind of MultiFieldsULE (with $len, Format) |
86 | | // as in the type def |
87 | 0 | let multi = <MultiFieldsULE<$len, Format> as VarULE>::from_bytes_unchecked(bytes); |
88 | | |
89 | | // This type is repr(transparent) over MultiFieldsULE<$len>, so its slices can be transmuted |
90 | | // Field invariant upheld here: validate_bytes above validates every field for being the right type |
91 | 0 | &*(multi as *const MultiFieldsULE<$len, Format> as *const $name<$($T,)+ Format>) |
92 | 0 | } Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _> as zerovec::ule::VarULE>::from_bytes_unchecked Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple2VarULE<_, _, _> as zerovec::ule::VarULE>::from_bytes_unchecked Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _> as zerovec::ule::VarULE>::from_bytes_unchecked Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _> as zerovec::ule::VarULE>::from_bytes_unchecked Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _> as zerovec::ule::VarULE>::from_bytes_unchecked |
93 | | } |
94 | | |
95 | | impl<$($T: fmt::Debug + VarULE + ?Sized,)+ Format: VarZeroVecFormat> fmt::Debug for $name<$($T,)+ Format> { |
96 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
97 | 0 | ($(self.$t(),)+).fmt(f) |
98 | 0 | } Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple2VarULE<_, _, _> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _> as core::fmt::Debug>::fmt |
99 | | } |
100 | | |
101 | | // We need manual impls since `#[derive()]` is disallowed on packed types |
102 | | impl<$($T: PartialEq + VarULE + ?Sized,)+ Format: VarZeroVecFormat> PartialEq for $name<$($T,)+ Format> { |
103 | 0 | fn eq(&self, other: &Self) -> bool { |
104 | | |
105 | 0 | ($(self.$t(),)+).eq(&($(other.$t(),)+)) |
106 | 0 | } Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple2VarULE<_, _, _> as core::cmp::PartialEq>::eq Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _> as core::cmp::PartialEq>::eq Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _> as core::cmp::PartialEq>::eq Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _> as core::cmp::PartialEq>::eq Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _> as core::cmp::PartialEq>::eq |
107 | | } |
108 | | |
109 | | impl<$($T: Eq + VarULE + ?Sized,)+ Format: VarZeroVecFormat> Eq for $name<$($T,)+ Format> {} |
110 | | |
111 | | impl<$($T: PartialOrd + VarULE + ?Sized,)+ Format: VarZeroVecFormat> PartialOrd for $name<$($T,)+ Format> { |
112 | 0 | fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { |
113 | 0 | ($(self.$t(),)+).partial_cmp(&($(other.$t(),)+)) |
114 | 0 | } Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple2VarULE<_, _, _> as core::cmp::PartialOrd>::partial_cmp Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _> as core::cmp::PartialOrd>::partial_cmp Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _> as core::cmp::PartialOrd>::partial_cmp Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _> as core::cmp::PartialOrd>::partial_cmp Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _> as core::cmp::PartialOrd>::partial_cmp |
115 | | } |
116 | | |
117 | | impl<$($T: Ord + VarULE + ?Sized,)+ Format: VarZeroVecFormat> Ord for $name<$($T,)+ Format> { |
118 | 0 | fn cmp(&self, other: &Self) -> core::cmp::Ordering { |
119 | 0 | ($(self.$t(),)+).cmp(&($(other.$t(),)+)) |
120 | 0 | } Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple2VarULE<_, _, _> as core::cmp::Ord>::cmp Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _> as core::cmp::Ord>::cmp Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _> as core::cmp::Ord>::cmp Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _> as core::cmp::Ord>::cmp Unexecuted instantiation: <zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _> as core::cmp::Ord>::cmp |
121 | | } |
122 | | |
123 | | // # Safety |
124 | | // |
125 | | // encode_var_ule_len: returns the length of the individual VarULEs together. |
126 | | // |
127 | | // encode_var_ule_write: writes bytes by deferring to the inner VarULE impls. |
128 | | unsafe impl<$($T,)+ $($T_alt,)+ Format> EncodeAsVarULE<$name<$($T,)+ Format>> for ( $($T_alt),+ ) |
129 | | where |
130 | | $($T: VarULE + ?Sized,)+ |
131 | | $($T_alt: EncodeAsVarULE<$T>,)+ |
132 | | Format: VarZeroVecFormat, |
133 | | { |
134 | 0 | fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R { |
135 | | // unnecessary if the other two are implemented |
136 | 0 | unreachable!() Unexecuted instantiation: <(_, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple2VarULE<_, _, _>>>::encode_var_ule_as_slices::<_, _> Unexecuted instantiation: <(_, _, _, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>>::encode_var_ule_as_slices::<_, _> Unexecuted instantiation: <(_, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _>>>::encode_var_ule_as_slices::<_, _> Unexecuted instantiation: <(_, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _>>>::encode_var_ule_as_slices::<_, _> Unexecuted instantiation: <(_, _, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>>::encode_var_ule_as_slices::<_, _> |
137 | | } |
138 | | |
139 | | #[inline] |
140 | 0 | fn encode_var_ule_len(&self) -> usize { |
141 | | // Safety: We validate that this type is the same kind of MultiFieldsULE (with $len, Format) |
142 | | // as in the type def |
143 | 0 | MultiFieldsULE::<$len, Format>::compute_encoded_len_for([$(self.$i.encode_var_ule_len()),+]) |
144 | 0 | } Unexecuted instantiation: <(_, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple2VarULE<_, _, _>>>::encode_var_ule_len Unexecuted instantiation: <(_, _, _, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>>::encode_var_ule_len Unexecuted instantiation: <(_, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _>>>::encode_var_ule_len Unexecuted instantiation: <(_, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _>>>::encode_var_ule_len Unexecuted instantiation: <(_, _, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>>::encode_var_ule_len |
145 | | |
146 | | #[inline] |
147 | 0 | fn encode_var_ule_write(&self, dst: &mut [u8]) { |
148 | 0 | let lengths = [$(self.$i.encode_var_ule_len()),+]; |
149 | | // Safety: We validate that this type is the same kind of MultiFieldsULE (with $len, Format) |
150 | | // as in the type def |
151 | 0 | let multi = MultiFieldsULE::<$len, Format>::new_from_lengths_partially_initialized(lengths, dst); |
152 | | $( |
153 | | // Safety: $i < $len, from the macro invocation, and field $i is supposed to be of type $T |
154 | 0 | unsafe { |
155 | 0 | multi.set_field_at::<$T, $T_alt>($i, &self.$i); |
156 | 0 | } |
157 | | )+ |
158 | 0 | } Unexecuted instantiation: <(_, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple2VarULE<_, _, _>>>::encode_var_ule_write Unexecuted instantiation: <(_, _, _, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>>::encode_var_ule_write Unexecuted instantiation: <(_, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _>>>::encode_var_ule_write Unexecuted instantiation: <(_, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _>>>::encode_var_ule_write Unexecuted instantiation: <(_, _, _, _, _) as zerovec::ule::encode::EncodeAsVarULE<zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>>::encode_var_ule_write |
159 | | } |
160 | | |
161 | | #[cfg(feature = "alloc")] |
162 | | impl<$($T: VarULE + ?Sized,)+ Format: VarZeroVecFormat> alloc::borrow::ToOwned for $name<$($T,)+ Format> { |
163 | | type Owned = alloc::boxed::Box<Self>; |
164 | | fn to_owned(&self) -> Self::Owned { |
165 | | encode_varule_to_box(self) |
166 | | } |
167 | | } |
168 | | |
169 | | impl<'a, $($T,)+ $($T_alt,)+ Format> ZeroFrom <'a, $name<$($T,)+ Format>> for ($($T_alt),+) |
170 | | where |
171 | | $($T: VarULE + ?Sized,)+ |
172 | | $($T_alt: ZeroFrom<'a, $T>,)+ |
173 | | Format: VarZeroVecFormat { |
174 | 0 | fn zero_from(other: &'a $name<$($T,)+ Format>) -> Self { |
175 | 0 | ( |
176 | 0 | $($T_alt::zero_from(other.$t()),)+ |
177 | 0 | ) |
178 | 0 | } Unexecuted instantiation: <(_, _) as zerofrom::zero_from::ZeroFrom<zerovec::ule::tuplevar::Tuple2VarULE<_, _, _>>>::zero_from Unexecuted instantiation: <(_, _, _, _, _, _) as zerofrom::zero_from::ZeroFrom<zerovec::ule::tuplevar::Tuple6VarULE<_, _, _, _, _, _, _>>>::zero_from Unexecuted instantiation: <(_, _, _) as zerofrom::zero_from::ZeroFrom<zerovec::ule::tuplevar::Tuple3VarULE<_, _, _, _>>>::zero_from Unexecuted instantiation: <(_, _, _, _) as zerofrom::zero_from::ZeroFrom<zerovec::ule::tuplevar::Tuple4VarULE<_, _, _, _, _>>>::zero_from Unexecuted instantiation: <(_, _, _, _, _) as zerofrom::zero_from::ZeroFrom<zerovec::ule::tuplevar::Tuple5VarULE<_, _, _, _, _, _>>>::zero_from |
179 | | } |
180 | | |
181 | | #[cfg(feature = "serde")] |
182 | | impl<$($T: serde::Serialize,)+ Format> serde::Serialize for $name<$($T,)+ Format> |
183 | | where |
184 | | $($T: VarULE + ?Sized,)+ |
185 | | // This impl should be present on almost all VarULE types. if it isn't, that is a bug |
186 | | $(for<'a> &'a $T: ZeroFrom<'a, $T>,)+ |
187 | | Format: VarZeroVecFormat |
188 | | { |
189 | | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer { |
190 | | if serializer.is_human_readable() { |
191 | | let this = ( |
192 | | $(self.$t()),+ |
193 | | ); |
194 | | <($(&$T),+) as serde::Serialize>::serialize(&this, serializer) |
195 | | } else { |
196 | | serializer.serialize_bytes(self.multi.as_bytes()) |
197 | | } |
198 | | } |
199 | | } |
200 | | |
201 | | #[cfg(all(feature = "serde", feature = "alloc"))] |
202 | | impl<'de, $($T: VarULE + ?Sized,)+ Format> serde::Deserialize<'de> for alloc::boxed::Box<$name<$($T,)+ Format>> |
203 | | where |
204 | | // This impl should be present on almost all deserializable VarULE types |
205 | | $( alloc::boxed::Box<$T>: serde::Deserialize<'de>,)+ |
206 | | Format: VarZeroVecFormat { |
207 | | fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error> where Des: serde::Deserializer<'de> { |
208 | | if deserializer.is_human_readable() { |
209 | | let this = <( $(alloc::boxed::Box<$T>),+) as serde::Deserialize>::deserialize(deserializer)?; |
210 | | let this_ref = ( |
211 | | $(&*this.$i),+ |
212 | | ); |
213 | | Ok(crate::ule::encode_varule_to_box(&this_ref)) |
214 | | } else { |
215 | | // This branch should usually not be hit, since Cow-like use cases will hit the Deserialize impl for &'a TupleNVarULE instead. |
216 | | |
217 | | let deserialized = <&$name<$($T,)+ Format>>::deserialize(deserializer)?; |
218 | | Ok(deserialized.to_boxed()) |
219 | | } |
220 | | } |
221 | | } |
222 | | |
223 | | #[cfg(feature = "serde")] |
224 | | impl<'a, 'de: 'a, $($T: VarULE + ?Sized,)+ Format: VarZeroVecFormat> serde::Deserialize<'de> for &'a $name<$($T,)+ Format> { |
225 | | fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error> where Des: serde::Deserializer<'de> { |
226 | | if deserializer.is_human_readable() { |
227 | | Err(serde::de::Error::custom( |
228 | | concat!("&", stringify!($name), " can only deserialize in zero-copy ways"), |
229 | | )) |
230 | | } else { |
231 | | let bytes = <&[u8]>::deserialize(deserializer)?; |
232 | | $name::<$($T,)+ Format>::parse_bytes(bytes).map_err(serde::de::Error::custom) |
233 | | } |
234 | | } |
235 | | } |
236 | | }; |
237 | | } |
238 | | |
239 | | tuple_varule!(Tuple2VarULE, 2, [ A a AE 0, B b BE 1 ]); |
240 | | tuple_varule!(Tuple3VarULE, 3, [ A a AE 0, B b BE 1, C c CE 2 ]); |
241 | | tuple_varule!(Tuple4VarULE, 4, [ A a AE 0, B b BE 1, C c CE 2, D d DE 3 ]); |
242 | | tuple_varule!(Tuple5VarULE, 5, [ A a AE 0, B b BE 1, C c CE 2, D d DE 3, E e EE 4 ]); |
243 | | tuple_varule!(Tuple6VarULE, 6, [ A a AE 0, B b BE 1, C c CE 2, D d DE 3, E e EE 4, F f FE 5 ]); |
244 | | |
245 | | #[cfg(test)] |
246 | | mod tests { |
247 | | use super::*; |
248 | | use crate::varzerovec::{Index16, Index32, Index8, VarZeroVecFormat}; |
249 | | use crate::VarZeroSlice; |
250 | | use crate::VarZeroVec; |
251 | | |
252 | | #[test] |
253 | | fn test_pairvarule_validate() { |
254 | | let vec: Vec<(&str, &[u8])> = vec![("a", b"b"), ("foo", b"bar"), ("lorem", b"ipsum\xFF")]; |
255 | | let zerovec: VarZeroVec<Tuple2VarULE<str, [u8]>> = (&vec).into(); |
256 | | let bytes = zerovec.as_bytes(); |
257 | | let zerovec2 = VarZeroVec::parse_bytes(bytes).unwrap(); |
258 | | assert_eq!(zerovec, zerovec2); |
259 | | |
260 | | // Test failed validation with a correctly sized but differently constrained tuple |
261 | | // Note: ipsum\xFF is not a valid str |
262 | | let zerovec3 = VarZeroVec::<Tuple2VarULE<str, str>>::parse_bytes(bytes); |
263 | | assert!(zerovec3.is_err()); |
264 | | |
265 | | #[cfg(feature = "serde")] |
266 | | for val in zerovec.iter() { |
267 | | // Can't use inference due to https://github.com/rust-lang/rust/issues/130180 |
268 | | test_utils::assert_serde_roundtrips::<Tuple2VarULE<str, [u8]>>(val); |
269 | | } |
270 | | } |
271 | | fn test_tripleule_validate_inner<Format: VarZeroVecFormat>() { |
272 | | let vec: Vec<(&str, &[u8], VarZeroVec<str>)> = vec![ |
273 | | ("a", b"b", (&vec!["a", "b", "c"]).into()), |
274 | | ("foo", b"bar", (&vec!["baz", "quux"]).into()), |
275 | | ( |
276 | | "lorem", |
277 | | b"ipsum\xFF", |
278 | | (&vec!["dolor", "sit", "amet"]).into(), |
279 | | ), |
280 | | ]; |
281 | | let zerovec: VarZeroVec<Tuple3VarULE<str, [u8], VarZeroSlice<str>, Format>> = (&vec).into(); |
282 | | let bytes = zerovec.as_bytes(); |
283 | | let zerovec2 = VarZeroVec::parse_bytes(bytes).unwrap(); |
284 | | assert_eq!(zerovec, zerovec2); |
285 | | |
286 | | // Test failed validation with a correctly sized but differently constrained tuple |
287 | | // Note: the str is unlikely to be a valid varzerovec |
288 | | let zerovec3 = VarZeroVec::<Tuple3VarULE<VarZeroSlice<str>, [u8], VarZeroSlice<str>, Format>>::parse_bytes(bytes); |
289 | | assert!(zerovec3.is_err()); |
290 | | |
291 | | #[cfg(feature = "serde")] |
292 | | for val in zerovec.iter() { |
293 | | // Can't use inference due to https://github.com/rust-lang/rust/issues/130180 |
294 | | test_utils::assert_serde_roundtrips::<Tuple3VarULE<str, [u8], VarZeroSlice<str>, Format>>( |
295 | | val, |
296 | | ); |
297 | | } |
298 | | } |
299 | | |
300 | | #[test] |
301 | | fn test_tripleule_validate() { |
302 | | test_tripleule_validate_inner::<Index8>(); |
303 | | test_tripleule_validate_inner::<Index16>(); |
304 | | test_tripleule_validate_inner::<Index32>(); |
305 | | } |
306 | | } |