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
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}