redb/
tuple_types.rs

1use crate::complex_types::{decode_varint_len, encode_varint_len};
2use crate::types::{Key, TypeName, Value};
3use std::borrow::Borrow;
4use std::cmp::Ordering;
5
6fn serialize_tuple_elements_variable<const N: usize>(
7    is_fixed_width: [bool; N],
8    slices: [&[u8]; N],
9) -> Vec<u8> {
10    let total_len: usize = slices.iter().map(|x| x.len()).sum();
11    let worst_case_len_overhead: usize =
12        is_fixed_width.iter().map(|x| if *x { 0 } else { 5 }).sum();
13    let mut output = Vec::with_capacity(total_len + worst_case_len_overhead);
14    let zipped = is_fixed_width.iter().zip(slices.iter());
15    for len in zipped
16        .map(|(fixed, x)| if *fixed { None } else { Some(x.len()) })
17        .take(slices.len() - 1)
18        .flatten()
19    {
20        encode_varint_len(len, &mut output);
21    }
22
23    for slice in slices {
24        output.extend_from_slice(slice);
25    }
26
27    debug_assert!(output.len() <= total_len + worst_case_len_overhead);
28
29    output
30}
31
32fn serialize_tuple_elements_fixed(slices: &[&[u8]]) -> Vec<u8> {
33    let total_len: usize = slices.iter().map(|x| x.len()).sum();
34    let mut output = Vec::with_capacity(total_len);
35    for slice in slices {
36        output.extend_from_slice(slice);
37    }
38    output
39}
40
41fn parse_lens<const N: usize>(fixed_width: [Option<usize>; N], data: &[u8]) -> (usize, [usize; N]) {
42    let mut result = [0; N];
43    let mut offset = 0;
44    for (i, &fixed) in fixed_width.iter().enumerate() {
45        if let Some(len) = fixed {
46            result[i] = len;
47        } else {
48            let (len, bytes_read) = decode_varint_len(&data[offset..]);
49            result[i] = len;
50            offset += bytes_read;
51        }
52    }
53    (offset, result)
54}
55
56fn not_equal<T: Key>(data1: &[u8], data2: &[u8]) -> Option<Ordering> {
57    match T::compare(data1, data2) {
58        Ordering::Less => Some(Ordering::Less),
59        Ordering::Equal => None,
60        Ordering::Greater => Some(Ordering::Greater),
61    }
62}
63
64macro_rules! fixed_width_impl {
65    ( $( $t:ty ),+ ) => {
66        {
67            let mut sum = 0;
68            $(
69                sum += <$t>::fixed_width()?;
70            )+
71            Some(sum)
72        }
73    };
74}
75
76macro_rules! as_bytes_impl {
77    ( $value:expr, $( $t:ty, $i:tt ),+ ) => {{
78        if Self::fixed_width().is_some() {
79            serialize_tuple_elements_fixed(&[
80                $(
81                    <$t>::as_bytes($value.$i.borrow()).as_ref(),
82                )+
83            ])
84        } else {
85            serialize_tuple_elements_variable(
86            [
87                $(
88                    <$t>::fixed_width().is_some(),
89                )+
90            ],
91            [
92                $(
93                    <$t>::as_bytes($value.$i.borrow()).as_ref(),
94                )+
95            ])
96        }
97    }};
98}
99
100macro_rules! type_name_impl {
101    ( $head:ty $(,$tail:ty)+ ) => {
102        {
103            let mut result = String::new();
104            result.push('(');
105            result.push_str(&<$head>::type_name().name());
106            $(
107                result.push(',');
108                result.push_str(&<$tail>::type_name().name());
109            )+
110            result.push(')');
111
112            if Self::fixed_width().is_some() {
113                TypeName::internal(&result)
114            } else {
115                TypeName::internal2(&result)
116            }
117        }
118    };
119}
120
121macro_rules! from_bytes_variable_impl {
122    ( $data:expr $(,$t:ty, $v:ident, $i:literal )+ | $t_last:ty, $v_last:ident, $i_last:literal ) => {
123        #[allow(clippy::manual_bits)]
124        {
125            let (mut offset, lens) = parse_lens::<$i_last>(
126                [
127                    $(
128                        <$t>::fixed_width(),
129                    )+
130                ],
131                $data);
132            $(
133                let len = lens[$i];
134                let $v = <$t>::from_bytes(&$data[offset..(offset + len)]);
135                offset += len;
136            )+
137            let $v_last = <$t_last>::from_bytes(&$data[offset..]);
138            ($(
139                $v,
140            )+
141                $v_last
142            )
143        }
144    };
145}
146
147macro_rules! from_bytes_fixed_impl {
148    ( $data:expr $(,$t:ty, $v:ident )+ ) => {
149        {
150            let mut offset = 0;
151            $(
152                let len = <$t>::fixed_width().unwrap();
153                let $v = <$t>::from_bytes(&$data[offset..(offset + len)]);
154                #[allow(unused_assignments)]
155                {
156                    offset += len;
157                }
158            )+
159
160            ($(
161                $v,
162            )+)
163        }
164    };
165}
166
167macro_rules! compare_variable_impl {
168    ( $data0:expr, $data1:expr $(,$t:ty, $i:literal )+ | $t_last:ty, $i_last:literal ) => {
169        #[allow(clippy::manual_bits)]
170        {
171            let fixed_width = [
172                $(
173                    <$t>::fixed_width(),
174                )+
175            ];
176            let (mut offset0, lens0) = parse_lens::<$i_last>(fixed_width, $data0);
177            let (mut offset1, lens1) = parse_lens::<$i_last>(fixed_width, $data1);
178            $(
179                let index = $i;
180                let len0 = lens0[index];
181                let len1 = lens1[index];
182                if let Some(order) = not_equal::<$t>(
183                    &$data0[offset0..(offset0 + len0)],
184                    &$data1[offset1..(offset1 + len1)],
185                ) {
186                    return order;
187                }
188                offset0 += len0;
189                offset1 += len1;
190            )+
191
192            <$t_last>::compare(&$data0[offset0..], &$data1[offset1..])
193        }
194    };
195}
196
197macro_rules! compare_fixed_impl {
198    ( $data0:expr, $data1:expr, $($t:ty),+ ) => {
199        {
200            let mut offset0 = 0;
201            let mut offset1 = 0;
202            $(
203                let len = <$t>::fixed_width().unwrap();
204                if let Some(order) = not_equal::<$t>(
205                    &$data0[offset0..(offset0 + len)],
206                    &$data1[offset1..(offset1 + len)],
207                ) {
208                    return order;
209                }
210                #[allow(unused_assignments)]
211                {
212                    offset0 += len;
213                    offset1 += len;
214                }
215            )+
216
217            Ordering::Equal
218        }
219    };
220}
221
222macro_rules! tuple_impl {
223    ( $($t:ident, $v:ident, $i:tt ),+ | $t_last:ident, $v_last:ident, $i_last:tt ) => {
224        impl<$($t: Value,)+ $t_last: Value> Value for ($($t,)+ $t_last) {
225            type SelfType<'a> = (
226                $(<$t>::SelfType<'a>,)+
227                <$t_last>::SelfType<'a>,
228            )
229            where
230                Self: 'a;
231            type AsBytes<'a> = Vec<u8>
232            where
233                Self: 'a;
234
235            fn fixed_width() -> Option<usize> {
236                fixed_width_impl!($($t,)+ $t_last)
237            }
238
239            fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a>
240            where
241                Self: 'a,
242            {
243                if Self::fixed_width().is_some() {
244                    from_bytes_fixed_impl!(data $(,$t,$v)+, $t_last, $v_last)
245                } else {
246                    from_bytes_variable_impl!(data $(,$t,$v,$i)+ | $t_last, $v_last, $i_last)
247                }
248            }
249
250            fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Vec<u8>
251            where
252                Self: 'a,
253                Self: 'b,
254            {
255                as_bytes_impl!(value, $($t,$i,)+ $t_last, $i_last)
256            }
257
258            fn type_name() -> TypeName {
259                type_name_impl!($($t,)+ $t_last)
260            }
261        }
262
263        impl<$($t: Key,)+ $t_last: Key> Key for ($($t,)+ $t_last) {
264            fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
265                if Self::fixed_width().is_some() {
266                    compare_fixed_impl!(data1, data2, $($t,)+ $t_last)
267                } else {
268                    compare_variable_impl!(data1, data2 $(,$t,$i)+ | $t_last, $i_last)
269                }
270            }
271        }
272    };
273}
274
275impl<T: Value> Value for (T,) {
276    type SelfType<'a>
277        = (T::SelfType<'a>,)
278    where
279        Self: 'a;
280    type AsBytes<'a>
281        = T::AsBytes<'a>
282    where
283        Self: 'a;
284
285    fn fixed_width() -> Option<usize> {
286        T::fixed_width()
287    }
288
289    fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a>
290    where
291        Self: 'a,
292    {
293        (T::from_bytes(data),)
294    }
295
296    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Self::AsBytes<'a>
297    where
298        Self: 'a,
299        Self: 'b,
300    {
301        T::as_bytes(&value.0)
302    }
303
304    fn type_name() -> TypeName {
305        TypeName::internal(&format!("({},)", T::type_name().name()))
306    }
307}
308
309impl<T: Key> Key for (T,) {
310    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
311        T::compare(data1, data2)
312    }
313}
314
315tuple_impl! {
316    T0, t0, 0
317    | T1, t1, 1
318}
319
320tuple_impl! {
321    T0, t0, 0,
322    T1, t1, 1
323    | T2, t2, 2
324}
325
326tuple_impl! {
327    T0, t0, 0,
328    T1, t1, 1,
329    T2, t2, 2
330    | T3, t3, 3
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}
340
341tuple_impl! {
342    T0, t0, 0,
343    T1, t1, 1,
344    T2, t2, 2,
345    T3, t3, 3,
346    T4, t4, 4
347    | T5, t5, 5
348}
349
350tuple_impl! {
351    T0, t0, 0,
352    T1, t1, 1,
353    T2, t2, 2,
354    T3, t3, 3,
355    T4, t4, 4,
356    T5, t5, 5
357    | T6, t6, 6
358}
359
360tuple_impl! {
361    T0, t0, 0,
362    T1, t1, 1,
363    T2, t2, 2,
364    T3, t3, 3,
365    T4, t4, 4,
366    T5, t5, 5,
367    T6, t6, 6
368    | T7, t7, 7
369}
370
371tuple_impl! {
372    T0, t0, 0,
373    T1, t1, 1,
374    T2, t2, 2,
375    T3, t3, 3,
376    T4, t4, 4,
377    T5, t5, 5,
378    T6, t6, 6,
379    T7, t7, 7
380    | T8, t8, 8
381}
382
383tuple_impl! {
384    T0, t0, 0,
385    T1, t1, 1,
386    T2, t2, 2,
387    T3, t3, 3,
388    T4, t4, 4,
389    T5, t5, 5,
390    T6, t6, 6,
391    T7, t7, 7,
392    T8, t8, 8
393    | T9, t9, 9
394}
395
396tuple_impl! {
397    T0, t0, 0,
398    T1, t1, 1,
399    T2, t2, 2,
400    T3, t3, 3,
401    T4, t4, 4,
402    T5, t5, 5,
403    T6, t6, 6,
404    T7, t7, 7,
405    T8, t8, 8,
406    T9, t9, 9
407    | T10, t10, 10
408}
409
410tuple_impl! {
411    T0, t0, 0,
412    T1, t1, 1,
413    T2, t2, 2,
414    T3, t3, 3,
415    T4, t4, 4,
416    T5, t5, 5,
417    T6, t6, 6,
418    T7, t7, 7,
419    T8, t8, 8,
420    T9, t9, 9,
421    T10, t10, 10
422    | T11, t11, 11
423}
424
425#[cfg(test)]
426mod test {
427    use crate::types::Value;
428
429    #[test]
430    fn width() {
431        assert!(<(&str, u8)>::fixed_width().is_none());
432        assert!(<(u16, u8, &str, u128)>::fixed_width().is_none());
433        assert_eq!(<(u16,)>::fixed_width().unwrap(), 2);
434        assert_eq!(<(u16, u8)>::fixed_width().unwrap(), 3);
435        assert_eq!(<(u16, u8, u128)>::fixed_width().unwrap(), 19);
436        assert_eq!(<(u16, u8, i8, u128)>::fixed_width().unwrap(), 20);
437        // Check that length of final field is elided
438        assert_eq!(
439            <(u8, &str)>::as_bytes(&(1, "hello")).len(),
440            "hello".len() + size_of::<u8>()
441        );
442        // Check that varint encoding uses only 1 byte for small strings
443        assert_eq!(
444            <(&str, u8)>::as_bytes(&("hello", 1)).len(),
445            "hello".len() + size_of::<u8>() + size_of::<u8>()
446        );
447    }
448}