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
238impl<T: Value> Value for (T,) {
239 type SelfType<'a>
240 = (T::SelfType<'a>,)
241 where
242 Self: 'a;
243 type AsBytes<'a>
244 = T::AsBytes<'a>
245 where
246 Self: 'a;
247
248 fn fixed_width() -> Option<usize> {
249 T::fixed_width()
250 }
251
252 fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a>
253 where
254 Self: 'a,
255 {
256 (T::from_bytes(data),)
257 }
258
259 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Self::AsBytes<'a>
260 where
261 Self: 'a,
262 Self: 'b,
263 {
264 T::as_bytes(&value.0)
265 }
266
267 fn type_name() -> TypeName {
268 TypeName::internal(&format!("({},)", T::type_name().name()))
269 }
270}
271
272impl<T: Key> Key for (T,) {
273 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
274 T::compare(data1, data2)
275 }
276}
277
278tuple_impl! {
279 T0, t0, 0
280 | T1, t1, 1
281}
282
283tuple_impl! {
284 T0, t0, 0,
285 T1, t1, 1
286 | T2, t2, 2
287}
288
289tuple_impl! {
290 T0, t0, 0,
291 T1, t1, 1,
292 T2, t2, 2
293 | T3, t3, 3
294}
295
296tuple_impl! {
297 T0, t0, 0,
298 T1, t1, 1,
299 T2, t2, 2,
300 T3, t3, 3
301 | T4, t4, 4
302}
303
304tuple_impl! {
305 T0, t0, 0,
306 T1, t1, 1,
307 T2, t2, 2,
308 T3, t3, 3,
309 T4, t4, 4
310 | T5, t5, 5
311}
312
313tuple_impl! {
314 T0, t0, 0,
315 T1, t1, 1,
316 T2, t2, 2,
317 T3, t3, 3,
318 T4, t4, 4,
319 T5, t5, 5
320 | T6, t6, 6
321}
322
323tuple_impl! {
324 T0, t0, 0,
325 T1, t1, 1,
326 T2, t2, 2,
327 T3, t3, 3,
328 T4, t4, 4,
329 T5, t5, 5,
330 T6, t6, 6
331 | T7, t7, 7
332}
333
334tuple_impl! {
335 T0, t0, 0,
336 T1, t1, 1,
337 T2, t2, 2,
338 T3, t3, 3,
339 T4, t4, 4,
340 T5, t5, 5,
341 T6, t6, 6,
342 T7, t7, 7
343 | T8, t8, 8
344}
345
346tuple_impl! {
347 T0, t0, 0,
348 T1, t1, 1,
349 T2, t2, 2,
350 T3, t3, 3,
351 T4, t4, 4,
352 T5, t5, 5,
353 T6, t6, 6,
354 T7, t7, 7,
355 T8, t8, 8
356 | T9, t9, 9
357}
358
359tuple_impl! {
360 T0, t0, 0,
361 T1, t1, 1,
362 T2, t2, 2,
363 T3, t3, 3,
364 T4, t4, 4,
365 T5, t5, 5,
366 T6, t6, 6,
367 T7, t7, 7,
368 T8, t8, 8,
369 T9, t9, 9
370 | T10, t10, 10
371}
372
373tuple_impl! {
374 T0, t0, 0,
375 T1, t1, 1,
376 T2, t2, 2,
377 T3, t3, 3,
378 T4, t4, 4,
379 T5, t5, 5,
380 T6, t6, 6,
381 T7, t7, 7,
382 T8, t8, 8,
383 T9, t9, 9,
384 T10, t10, 10
385 | T11, t11, 11
386}
387
388#[cfg(test)]
389mod test {
390 use crate::types::Value;
391
392 #[test]
393 fn width() {
394 assert!(<(&str, u8)>::fixed_width().is_none());
395 assert!(<(u16, u8, &str, u128)>::fixed_width().is_none());
396 assert_eq!(<(u16,)>::fixed_width().unwrap(), 2);
397 assert_eq!(<(u16, u8)>::fixed_width().unwrap(), 3);
398 assert_eq!(<(u16, u8, u128)>::fixed_width().unwrap(), 19);
399 assert_eq!(<(u16, u8, i8, u128)>::fixed_width().unwrap(), 20);
400 }
401}