redb/
tuple_types.rs

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}