1use crate::types::{Key, TypeName, Value};
2use std::borrow::Borrow;
3use std::cmp::Ordering;
4use std::mem::size_of;
5
6fn serialize_tuple_elements_variable(slices: &[&[u8]]) -> Vec<u8> {
7 let total_len: usize = slices.iter().map(|x| x.len()).sum();
8 let mut output = Vec::with_capacity((slices.len() - 1) * size_of::<u32>() + total_len);
9 for len in slices.iter().map(|x| x.len()).take(slices.len() - 1) {
10 output.extend_from_slice(&(u32::try_from(len).unwrap()).to_le_bytes());
11 }
12
13 for slice in slices {
14 output.extend_from_slice(slice);
15 }
16
17 output
18}
19
20fn serialize_tuple_elements_fixed(slices: &[&[u8]]) -> Vec<u8> {
21 let total_len: usize = slices.iter().map(|x| x.len()).sum();
22 let mut output = Vec::with_capacity(total_len);
23 for slice in slices {
24 output.extend_from_slice(slice);
25 }
26 output
27}
28
29fn parse_lens<const N: usize>(data: &[u8]) -> [usize; N] {
30 let mut result = [0; N];
31 for i in 0..N {
32 result[i] = u32::from_le_bytes(data[4 * i..4 * (i + 1)].try_into().unwrap()) as usize;
33 }
34 result
35}
36
37fn not_equal<T: Key>(data1: &[u8], data2: &[u8]) -> Option<Ordering> {
38 match T::compare(data1, data2) {
39 Ordering::Less => Some(Ordering::Less),
40 Ordering::Equal => None,
41 Ordering::Greater => Some(Ordering::Greater),
42 }
43}
44
45macro_rules! fixed_width_impl {
46 ( $( $t:ty ),+ ) => {
47 {
48 let mut sum = 0;
49 $(
50 sum += <$t>::fixed_width()?;
51 )+
52 Some(sum)
53 }
54 };
55}
56
57macro_rules! as_bytes_impl {
58 ( $value:expr, $( $t:ty, $i:tt ),+ ) => {{
59 if Self::fixed_width().is_some() {
60 serialize_tuple_elements_fixed(&[
61 $(
62 <$t>::as_bytes($value.$i.borrow()).as_ref(),
63 )+
64 ])
65 } else {
66 serialize_tuple_elements_variable(&[
67 $(
68 <$t>::as_bytes($value.$i.borrow()).as_ref(),
69 )+
70 ])
71 }
72 }};
73}
74
75macro_rules! type_name_impl {
76 ( $head:ty $(,$tail:ty)+ ) => {
77 {
78 let mut result = String::new();
79 result.push('(');
80 result.push_str(&<$head>::type_name().name());
81 $(
82 result.push(',');
83 result.push_str(&<$tail>::type_name().name());
84 )+
85 result.push(')');
86
87 TypeName::internal(&result)
88 }
89 };
90}
91
92macro_rules! from_bytes_variable_impl {
93 ( $data:expr $(,$t:ty, $v:ident, $i:literal )+ | $t_last:ty, $v_last:ident, $i_last:literal ) => {
94 #[allow(clippy::manual_bits)]
95 {
96 let lens: [usize; $i_last] = parse_lens($data);
97 let mut offset = $i_last * size_of::<u32>();
98 $(
99 let len = lens[$i];
100 let $v = <$t>::from_bytes(&$data[offset..(offset + len)]);
101 offset += len;
102 )+
103 let $v_last = <$t_last>::from_bytes(&$data[offset..]);
104 ($(
105 $v,
106 )+
107 $v_last
108 )
109 }
110 };
111}
112
113macro_rules! from_bytes_fixed_impl {
114 ( $data:expr $(,$t:ty, $v:ident )+ ) => {
115 {
116 let mut offset = 0;
117 $(
118 let len = <$t>::fixed_width().unwrap();
119 let $v = <$t>::from_bytes(&$data[offset..(offset + len)]);
120 #[allow(unused_assignments)]
121 {
122 offset += len;
123 }
124 )+
125
126 ($(
127 $v,
128 )+)
129 }
130 };
131}
132
133macro_rules! compare_variable_impl {
134 ( $data0:expr, $data1:expr $(,$t:ty, $i:literal )+ | $t_last:ty, $i_last:literal ) => {
135 #[allow(clippy::manual_bits)]
136 {
137 let lens0: [usize; $i_last] = parse_lens($data0);
138 let lens1: [usize; $i_last] = parse_lens($data1);
139 let mut offset0 = $i_last * size_of::<u32>();
140 let mut offset1 = $i_last * size_of::<u32>();
141 $(
142 let index = $i;
143 let len0 = lens0[index];
144 let len1 = lens1[index];
145 if let Some(order) = not_equal::<$t>(
146 &$data0[offset0..(offset0 + len0)],
147 &$data1[offset1..(offset1 + len1)],
148 ) {
149 return order;
150 }
151 offset0 += len0;
152 offset1 += len1;
153 )+
154
155 <$t_last>::compare(&$data0[offset0..], &$data1[offset1..])
156 }
157 };
158}
159
160macro_rules! compare_fixed_impl {
161 ( $data0:expr, $data1:expr, $($t:ty),+ ) => {
162 {
163 let mut offset0 = 0;
164 let mut offset1 = 0;
165 $(
166 let len = <$t>::fixed_width().unwrap();
167 if let Some(order) = not_equal::<$t>(
168 &$data0[offset0..(offset0 + len)],
169 &$data1[offset1..(offset1 + len)],
170 ) {
171 return order;
172 }
173 #[allow(unused_assignments)]
174 {
175 offset0 += len;
176 offset1 += len;
177 }
178 )+
179
180 Ordering::Equal
181 }
182 };
183}
184
185macro_rules! tuple_impl {
186 ( $($t:ident, $v:ident, $i:tt ),+ | $t_last:ident, $v_last:ident, $i_last:tt ) => {
187 impl<$($t: Value,)+ $t_last: Value> Value for ($($t,)+ $t_last) {
188 type SelfType<'a> = (
189 $(<$t>::SelfType<'a>,)+
190 <$t_last>::SelfType<'a>,
191 )
192 where
193 Self: 'a;
194 type AsBytes<'a> = Vec<u8>
195 where
196 Self: 'a;
197
198 fn fixed_width() -> Option<usize> {
199 fixed_width_impl!($($t,)+ $t_last)
200 }
201
202 fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a>
203 where
204 Self: 'a,
205 {
206 if Self::fixed_width().is_some() {
207 from_bytes_fixed_impl!(data $(,$t,$v)+, $t_last, $v_last)
208 } else {
209 from_bytes_variable_impl!(data $(,$t,$v,$i)+ | $t_last, $v_last, $i_last)
210 }
211 }
212
213 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Vec<u8>
214 where
215 Self: 'a,
216 Self: 'b,
217 {
218 as_bytes_impl!(value, $($t,$i,)+ $t_last, $i_last)
219 }
220
221 fn type_name() -> TypeName {
222 type_name_impl!($($t,)+ $t_last)
223 }
224 }
225
226 impl<$($t: Key,)+ $t_last: Key> Key for ($($t,)+ $t_last) {
227 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
228 if Self::fixed_width().is_some() {
229 compare_fixed_impl!(data1, data2, $($t,)+ $t_last)
230 } else {
231 compare_variable_impl!(data1, data2 $(,$t,$i)+ | $t_last, $i_last)
232 }
233 }
234 }
235 };
236}
237
238tuple_impl! {
239 T0, t0, 0
240 | T1, t1, 1
241}
242
243tuple_impl! {
244 T0, t0, 0,
245 T1, t1, 1
246 | T2, t2, 2
247}
248
249tuple_impl! {
250 T0, t0, 0,
251 T1, t1, 1,
252 T2, t2, 2
253 | T3, t3, 3
254}
255
256tuple_impl! {
257 T0, t0, 0,
258 T1, t1, 1,
259 T2, t2, 2,
260 T3, t3, 3
261 | T4, t4, 4
262}
263
264tuple_impl! {
265 T0, t0, 0,
266 T1, t1, 1,
267 T2, t2, 2,
268 T3, t3, 3,
269 T4, t4, 4
270 | T5, t5, 5
271}
272
273tuple_impl! {
274 T0, t0, 0,
275 T1, t1, 1,
276 T2, t2, 2,
277 T3, t3, 3,
278 T4, t4, 4,
279 T5, t5, 5
280 | T6, t6, 6
281}
282
283tuple_impl! {
284 T0, t0, 0,
285 T1, t1, 1,
286 T2, t2, 2,
287 T3, t3, 3,
288 T4, t4, 4,
289 T5, t5, 5,
290 T6, t6, 6
291 | T7, t7, 7
292}
293
294tuple_impl! {
295 T0, t0, 0,
296 T1, t1, 1,
297 T2, t2, 2,
298 T3, t3, 3,
299 T4, t4, 4,
300 T5, t5, 5,
301 T6, t6, 6,
302 T7, t7, 7
303 | T8, t8, 8
304}
305
306tuple_impl! {
307 T0, t0, 0,
308 T1, t1, 1,
309 T2, t2, 2,
310 T3, t3, 3,
311 T4, t4, 4,
312 T5, t5, 5,
313 T6, t6, 6,
314 T7, t7, 7,
315 T8, t8, 8
316 | T9, t9, 9
317}
318
319tuple_impl! {
320 T0, t0, 0,
321 T1, t1, 1,
322 T2, t2, 2,
323 T3, t3, 3,
324 T4, t4, 4,
325 T5, t5, 5,
326 T6, t6, 6,
327 T7, t7, 7,
328 T8, t8, 8,
329 T9, t9, 9
330 | T10, t10, 10
331}
332
333tuple_impl! {
334 T0, t0, 0,
335 T1, t1, 1,
336 T2, t2, 2,
337 T3, t3, 3,
338 T4, t4, 4,
339 T5, t5, 5,
340 T6, t6, 6,
341 T7, t7, 7,
342 T8, t8, 8,
343 T9, t9, 9,
344 T10, t10, 10
345 | T11, t11, 11
346}
347
348#[cfg(test)]
349mod test {
350 use crate::types::Value;
351
352 #[test]
353 fn width() {
354 assert!(<(&str, u8)>::fixed_width().is_none());
355 assert!(<(u16, u8, &str, u128)>::fixed_width().is_none());
356 assert_eq!(<(u16, u8)>::fixed_width().unwrap(), 3);
357 assert_eq!(<(u16, u8, u128)>::fixed_width().unwrap(), 19);
358 assert_eq!(<(u16, u8, i8, u128)>::fixed_width().unwrap(), 20);
359 }
360}