1
use std::{
2
    borrow::Cow, convert::Infallible, io::ErrorKind, num::TryFromIntError, string::FromUtf8Error,
3
};
4

            
5
use arc_bytes::{
6
    serde::{Bytes, CowBytes},
7
    ArcBytes,
8
};
9
use num_traits::{FromPrimitive, ToPrimitive};
10
use ordered_varint::{Signed, Unsigned, Variable};
11
use serde::{Deserialize, Serialize};
12

            
13
use crate::{connection::Range, AnyError};
14

            
15
/// A trait that enables a type to convert itself into a `memcmp`-compatible
16
/// sequence of bytes.
17
pub trait Key<'k>: Clone + std::fmt::Debug + Send + Sync {
18
    /// The error type that can be produced by either serialization or
19
    /// deserialization.
20
    type Error: AnyError;
21

            
22
    /// The size of the key, if constant. If this type doesn't produce the same
23
    /// number of bytes for each value, this should be `None`.
24
    const LENGTH: Option<usize>;
25

            
26
    /// Convert `self` into a `Cow<[u8]>` containing bytes that are able to be
27
    /// compared via `memcmp` in a way that is comptaible with its own Ord
28
    /// implementation.
29
    fn as_ord_bytes(&'k self) -> Result<Cow<'k, [u8]>, Self::Error>;
30

            
31
    /// Deserialize a sequence of bytes previously encoded with
32
    /// [`Self::as_ord_bytes`].
33
    fn from_ord_bytes(bytes: &'k [u8]) -> Result<Self, Self::Error>;
34

            
35
    /// Return the first value in sequence for this type. Not all types
36
    /// implement this.
37
    fn first_value() -> Result<Self, NextValueError> {
38
        Err(NextValueError::Unsupported)
39
    }
40

            
41
    /// Return the next value in sequence for this type. Not all types implement
42
    /// this. Instead of wrapping/overflowing, None should be returned.
43
1
    fn next_value(&self) -> Result<Self, NextValueError> {
44
1
        Err(NextValueError::Unsupported)
45
1
    }
46
}
47

            
48
/// The error types for [`Key::next_value()`].
49
#[derive(Clone, thiserror::Error, Debug, Serialize, Deserialize)]
50
pub enum NextValueError {
51
    /// The key type does not support this operation.
52
    #[error("the key type does not support automatic ids")]
53
    Unsupported,
54
    /// Generating a new value would wrap the underlying value.
55
    #[error("the key type has run out of unique values")]
56
    WouldWrap,
57
}
58

            
59
/// A type that can be used as a prefix range in range-based queries.
60
pub trait IntoPrefixRange: Sized {
61
    /// Returns the value as a prefix-range, which will match all values that
62
    /// start with `self`.
63
    fn into_prefix_range(self) -> Range<Self>;
64
}
65

            
66
20
fn next_byte_sequence(start: &[u8]) -> Option<Vec<u8>> {
67
20
    let mut end = start.to_vec();
68
    // Modify the last byte by adding one. If it would wrap, we proceed to the
69
    // next byte.
70
30
    while let Some(last_byte) = end.pop() {
71
20
        if let Some(next) = last_byte.checked_add(1) {
72
10
            end.push(next);
73
10
            return Some(end);
74
10
        }
75
    }
76

            
77
10
    None
78
20
}
79

            
80
impl<'k> Key<'k> for Cow<'k, [u8]> {
81
    type Error = Infallible;
82

            
83
    const LENGTH: Option<usize> = None;
84

            
85
1
    fn as_ord_bytes(&'k self) -> Result<Cow<'k, [u8]>, Self::Error> {
86
1
        Ok(self.clone())
87
1
    }
88

            
89
1
    fn from_ord_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
90
1
        Ok(Cow::Owned(bytes.to_vec()))
91
1
    }
92
}
93

            
94
impl<'k> IntoPrefixRange for Cow<'k, [u8]> {
95
    fn into_prefix_range(self) -> Range<Self> {
96
4
        if let Some(next) = next_byte_sequence(&self) {
97
2
            Range::from(self..Cow::Owned(next))
98
        } else {
99
2
            Range::from(self..)
100
        }
101
4
    }
102
}
103

            
104
1
#[test]
105
1
fn cow_prefix_range_tests() {
106
1
    use std::ops::RangeBounds;
107
1
    assert!(Cow::<'_, [u8]>::Borrowed(b"a")
108
1
        .into_prefix_range()
109
1
        .contains(&Cow::Borrowed(b"aa")));
110
1
    assert!(!Cow::<'_, [u8]>::Borrowed(b"a")
111
1
        .into_prefix_range()
112
1
        .contains(&Cow::Borrowed(b"b")));
113
1
    assert!(Cow::<'_, [u8]>::Borrowed(b"\xff")
114
1
        .into_prefix_range()
115
1
        .contains(&Cow::Borrowed(b"\xff\xff")));
116
1
    assert!(!Cow::<'_, [u8]>::Borrowed(b"\xff")
117
1
        .into_prefix_range()
118
1
        .contains(&Cow::Borrowed(b"\xfe")));
119
1
}
120

            
121
impl<'a> Key<'a> for Vec<u8> {
122
    type Error = Infallible;
123

            
124
    const LENGTH: Option<usize> = None;
125

            
126
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
127
        Ok(Cow::Borrowed(self))
128
    }
129

            
130
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
131
        Ok(bytes.to_vec())
132
    }
133
}
134

            
135
impl<'k> IntoPrefixRange for Vec<u8> {
136
    fn into_prefix_range(self) -> Range<Self> {
137
4
        if let Some(next) = next_byte_sequence(&self) {
138
2
            Range::from(self..next)
139
        } else {
140
2
            Range::from(self..)
141
        }
142
4
    }
143
}
144

            
145
1
#[test]
146
1
fn vec_prefix_range_tests() {
147
1
    use std::ops::RangeBounds;
148
1
    assert!(b"a".to_vec().into_prefix_range().contains(&b"aa".to_vec()));
149
1
    assert!(!b"a".to_vec().into_prefix_range().contains(&b"b".to_vec()));
150
1
    assert!(b"\xff"
151
1
        .to_vec()
152
1
        .into_prefix_range()
153
1
        .contains(&b"\xff\xff".to_vec()));
154
1
    assert!(!b"\xff"
155
1
        .to_vec()
156
1
        .into_prefix_range()
157
1
        .contains(&b"\xfe".to_vec()));
158
1
}
159

            
160
impl<'a> Key<'a> for ArcBytes<'a> {
161
    type Error = Infallible;
162

            
163
    const LENGTH: Option<usize> = None;
164

            
165
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
166
        Ok(Cow::Borrowed(self))
167
    }
168

            
169
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
170
        Ok(Self::from(bytes))
171
    }
172
}
173

            
174
impl<'k> IntoPrefixRange for ArcBytes<'k> {
175
    fn into_prefix_range(self) -> Range<Self> {
176
4
        if let Some(next) = next_byte_sequence(&self) {
177
2
            Range::from(self..Self::owned(next))
178
        } else {
179
2
            Range::from(self..)
180
        }
181
4
    }
182
}
183

            
184
1
#[test]
185
1
fn arcbytes_prefix_range_tests() {
186
1
    use std::ops::RangeBounds;
187
1
    assert!(ArcBytes::from(b"a")
188
1
        .into_prefix_range()
189
1
        .contains(&ArcBytes::from(b"aa")));
190
1
    assert!(!ArcBytes::from(b"a")
191
1
        .into_prefix_range()
192
1
        .contains(&ArcBytes::from(b"b")));
193
1
    assert!(ArcBytes::from(b"\xff")
194
1
        .into_prefix_range()
195
1
        .contains(&ArcBytes::from(b"\xff\xff")));
196
1
    assert!(!ArcBytes::from(b"\xff")
197
1
        .into_prefix_range()
198
1
        .contains(&ArcBytes::from(b"\xfe")));
199
1
}
200

            
201
impl<'a> Key<'a> for CowBytes<'a> {
202
    type Error = Infallible;
203

            
204
    const LENGTH: Option<usize> = None;
205

            
206
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
207
        Ok(self.0.clone())
208
    }
209

            
210
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
211
        Ok(Self::from(bytes))
212
    }
213
}
214

            
215
impl<'k> IntoPrefixRange for CowBytes<'k> {
216
    fn into_prefix_range(self) -> Range<Self> {
217
4
        if let Some(next) = next_byte_sequence(&self) {
218
2
            Range::from(self..Self::from(next))
219
        } else {
220
2
            Range::from(self..)
221
        }
222
4
    }
223
}
224

            
225
1
#[test]
226
1
fn cowbytes_prefix_range_tests() {
227
1
    use std::ops::RangeBounds;
228
1
    assert!(CowBytes::from(&b"a"[..])
229
1
        .into_prefix_range()
230
1
        .contains(&CowBytes::from(&b"aa"[..])));
231
1
    assert!(!CowBytes::from(&b"a"[..])
232
1
        .into_prefix_range()
233
1
        .contains(&CowBytes::from(&b"b"[..])));
234
1
    assert!(CowBytes::from(&b"\xff"[..])
235
1
        .into_prefix_range()
236
1
        .contains(&CowBytes::from(&b"\xff\xff"[..])));
237
1
    assert!(!CowBytes::from(&b"\xff"[..])
238
1
        .into_prefix_range()
239
1
        .contains(&CowBytes::from(&b"\xfe"[..])));
240
1
}
241

            
242
impl<'a> Key<'a> for Bytes {
243
    type Error = Infallible;
244

            
245
    const LENGTH: Option<usize> = None;
246

            
247
692982
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
248
692982
        Ok(Cow::Borrowed(self))
249
692982
    }
250

            
251
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
252
        Ok(Self::from(bytes))
253
    }
254
}
255

            
256
impl IntoPrefixRange for Bytes {
257
    fn into_prefix_range(self) -> Range<Self> {
258
4
        if let Some(next) = next_byte_sequence(&self) {
259
2
            Range::from(self..Self::from(next))
260
        } else {
261
2
            Range::from(self..)
262
        }
263
4
    }
264
}
265

            
266
1
#[test]
267
1
fn bytes_prefix_range_tests() {
268
1
    use std::ops::RangeBounds;
269
1
    assert!(Bytes::from(b"a".to_vec())
270
1
        .into_prefix_range()
271
1
        .contains(&Bytes::from(b"aa".to_vec())));
272
1
    assert!(!Bytes::from(b"a".to_vec())
273
1
        .into_prefix_range()
274
1
        .contains(&Bytes::from(b"b".to_vec())));
275
1
    assert!(Bytes::from(b"\xff".to_vec())
276
1
        .into_prefix_range()
277
1
        .contains(&Bytes::from(b"\xff\xff".to_vec())));
278
1
    assert!(!Bytes::from(b"\xff".to_vec())
279
1
        .into_prefix_range()
280
1
        .contains(&Bytes::from(b"\xfe".to_vec())));
281
1
}
282

            
283
impl<'a> Key<'a> for String {
284
    type Error = FromUtf8Error;
285

            
286
    const LENGTH: Option<usize> = None;
287

            
288
345061
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
289
345061
        Ok(Cow::Borrowed(self.as_bytes()))
290
345061
    }
291

            
292
317709
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
293
317709
        Self::from_utf8(bytes.to_vec())
294
317709
    }
295
}
296

            
297
impl IntoPrefixRange for String {
298
6
    fn into_prefix_range(self) -> Range<Self> {
299
6
        let mut bytes = self.as_bytes().to_vec();
300
6
        for (index, char) in self.char_indices().rev() {
301
6
            let mut next_char = u32::from(char) + 1;
302
6
            if next_char == 0xd800 {
303
                next_char = 0xE000;
304
6
            } else if next_char > u32::from(char::MAX) {
305
2
                continue;
306
4
            }
307

            
308
4
            let mut char_bytes = [0; 6];
309
4
            bytes.splice(
310
4
                index..,
311
4
                char::try_from(next_char)
312
4
                    .unwrap()
313
4
                    .encode_utf8(&mut char_bytes)
314
4
                    .bytes(),
315
4
            );
316
4
            return Range::from(self..Self::from_utf8(bytes).unwrap());
317
        }
318

            
319
2
        Range::from(self..)
320
6
    }
321
}
322

            
323
1
#[test]
324
1
fn string_prefix_range_tests() {
325
1
    use std::ops::RangeBounds;
326
1
    assert!(String::from("a")
327
1
        .into_prefix_range()
328
1
        .contains(&String::from("aa")));
329
1
    assert!(!String::from("a")
330
1
        .into_prefix_range()
331
1
        .contains(&String::from("b")));
332
1
    assert!(String::from("\u{d799}")
333
1
        .into_prefix_range()
334
1
        .contains(&String::from("\u{d799}a")));
335
1
    assert!(!String::from("\u{d799}")
336
1
        .into_prefix_range()
337
1
        .contains(&String::from("\u{e000}")));
338
1
    assert!(String::from("\u{10ffff}")
339
1
        .into_prefix_range()
340
1
        .contains(&String::from("\u{10ffff}a")));
341
1
    assert!(!String::from("\u{10ffff}")
342
1
        .into_prefix_range()
343
1
        .contains(&String::from("\u{10fffe}")));
344
1
}
345

            
346
impl<'a> Key<'a> for () {
347
    type Error = Infallible;
348

            
349
    const LENGTH: Option<usize> = Some(0);
350

            
351
55
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
352
55
        Ok(Cow::default())
353
55
    }
354

            
355
82
    fn from_ord_bytes(_: &'a [u8]) -> Result<Self, Self::Error> {
356
82
        Ok(())
357
82
    }
358
}
359

            
360
impl<'a> Key<'a> for bool {
361
    type Error = Infallible;
362

            
363
    const LENGTH: Option<usize> = Some(1);
364

            
365
2
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
366
2
        if *self {
367
1
            Ok(Cow::Borrowed(&[1_u8]))
368
        } else {
369
1
            Ok(Cow::Borrowed(&[0_u8]))
370
        }
371
2
    }
372

            
373
2
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
374
2
        if bytes.is_empty() || bytes[0] == 0 {
375
1
            Ok(false)
376
        } else {
377
1
            Ok(true)
378
        }
379
2
    }
380
}
381

            
382
macro_rules! impl_key_for_tuple {
383
    ($(($index:tt, $varname:ident, $generic:ident)),+) => {
384
        impl<'a, $($generic),+> Key<'a> for ($($generic),+)
385
        where
386
            $($generic: Key<'a>),+
387
        {
388
            type Error = CompositeKeyError;
389

            
390
            const LENGTH: Option<usize> = match ($($generic::LENGTH),+) {
391
                ($(Some($varname)),+) => Some($($varname +)+ 0),
392
                _ => None,
393
            };
394

            
395
510
            fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
396
510
                let mut bytes = Vec::new();
397
510

            
398
510
                $(encode_composite_key_field(&self.$index, &mut bytes)?;)+
399

            
400
510
                Ok(Cow::Owned(bytes))
401
510
            }
402

            
403
511
            fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
404
511
                $(let ($varname, bytes) = decode_composite_key_field::<$generic>(bytes)?;)+
405

            
406
511
                if bytes.is_empty() {
407
511
                    Ok(($($varname),+))
408
                } else {
409
                    Err(CompositeKeyError::new(std::io::Error::from(
410
                        ErrorKind::InvalidData,
411
                    )))
412
                }
413
511
            }
414
        }
415
    };
416
}
417

            
418
impl_key_for_tuple!((0, t1, T1), (1, t2, T2));
419
impl_key_for_tuple!((0, t1, T1), (1, t2, T2), (2, t3, T3));
420
impl_key_for_tuple!((0, t1, T1), (1, t2, T2), (2, t3, T3), (3, t4, T4));
421
impl_key_for_tuple!(
422
    (0, t1, T1),
423
    (1, t2, T2),
424
    (2, t3, T3),
425
    (3, t4, T4),
426
    (4, t5, T5)
427
);
428
impl_key_for_tuple!(
429
    (0, t1, T1),
430
    (1, t2, T2),
431
    (2, t3, T3),
432
    (3, t4, T4),
433
    (4, t5, T5),
434
    (5, t6, T6)
435
);
436
impl_key_for_tuple!(
437
    (0, t1, T1),
438
    (1, t2, T2),
439
    (2, t3, T3),
440
    (3, t4, T4),
441
    (4, t5, T5),
442
    (5, t6, T6),
443
    (6, t7, T7)
444
);
445
impl_key_for_tuple!(
446
    (0, t1, T1),
447
    (1, t2, T2),
448
    (2, t3, T3),
449
    (3, t4, T4),
450
    (4, t5, T5),
451
    (5, t6, T6),
452
    (6, t7, T7),
453
    (7, t8, T8)
454
);
455

            
456
3588
fn encode_composite_key_field<'a, T: Key<'a>>(
457
3588
    value: &'a T,
458
3588
    bytes: &mut Vec<u8>,
459
3588
) -> Result<(), CompositeKeyError> {
460
3588
    let t2 = T::as_ord_bytes(value).map_err(CompositeKeyError::new)?;
461
3588
    if T::LENGTH.is_none() {
462
3584
        (t2.len() as u64)
463
3584
            .encode_variable(bytes)
464
3584
            .map_err(CompositeKeyError::new)?;
465
4
    }
466
3588
    bytes.extend(t2.iter().copied());
467
3588
    Ok(())
468
3588
}
469

            
470
3590
fn decode_composite_key_field<'a, T: Key<'a>>(
471
3590
    mut bytes: &'a [u8],
472
3590
) -> Result<(T, &[u8]), CompositeKeyError> {
473
3590
    let length = if let Some(length) = T::LENGTH {
474
6
        length
475
    } else {
476
3584
        usize::try_from(u64::decode_variable(&mut bytes)?)?
477
    };
478
3590
    let (t2, remaining) = bytes.split_at(length);
479
3590
    Ok((
480
3590
        T::from_ord_bytes(t2).map_err(CompositeKeyError::new)?,
481
3590
        remaining,
482
    ))
483
3590
}
484

            
485
1
#[test]
486
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)] // couldn't figure out how to macro-ize it
487
1
fn composite_key_tests() {
488
7
    fn roundtrip<T: for<'a> Key<'a> + Ord + Eq + std::fmt::Debug>(mut cases: Vec<T>) {
489
7
        let mut encoded = {
490
7
            cases
491
7
                .iter()
492
508
                .map(|tuple| tuple.as_ord_bytes().unwrap().to_vec())
493
7
                .collect::<Vec<Vec<u8>>>()
494
7
        };
495
7
        cases.sort();
496
7
        encoded.sort();
497
7
        let decoded = encoded
498
7
            .iter()
499
508
            .map(|encoded| T::from_ord_bytes(encoded).unwrap())
500
7
            .collect::<Vec<_>>();
501
7
        assert_eq!(cases, decoded);
502
7
    }
503
1

            
504
1
    let values = [Unsigned::from(0_u8), Unsigned::from(16_u8)];
505
1
    let mut cases = Vec::new();
506
3
    for t1 in values {
507
6
        for t2 in values {
508
4
            cases.push((t1, t2));
509
4
        }
510
    }
511
1
    roundtrip(cases);
512
1

            
513
1
    let mut cases = Vec::new();
514
3
    for t1 in values {
515
6
        for t2 in values {
516
12
            for t3 in values {
517
8
                cases.push((t1, t2, t3));
518
8
            }
519
        }
520
    }
521
1
    roundtrip(cases);
522
1

            
523
1
    let mut cases = Vec::new();
524
3
    for t1 in values {
525
6
        for t2 in values {
526
12
            for t3 in values {
527
24
                for t4 in values {
528
16
                    cases.push((t1, t2, t3, t4));
529
16
                }
530
            }
531
        }
532
    }
533
1
    roundtrip(cases);
534
1

            
535
1
    let mut cases = Vec::new();
536
3
    for t1 in values {
537
6
        for t2 in values {
538
12
            for t3 in values {
539
24
                for t4 in values {
540
48
                    for t5 in values {
541
32
                        cases.push((t1, t2, t3, t4, t5));
542
32
                    }
543
                }
544
            }
545
        }
546
    }
547
1
    roundtrip(cases);
548
1

            
549
1
    let mut cases = Vec::new();
550
3
    for t1 in values {
551
6
        for t2 in values {
552
12
            for t3 in values {
553
24
                for t4 in values {
554
48
                    for t5 in values {
555
96
                        for t6 in values {
556
64
                            cases.push((t1, t2, t3, t4, t5, t6));
557
64
                        }
558
                    }
559
                }
560
            }
561
        }
562
    }
563
1
    roundtrip(cases);
564
1

            
565
1
    let mut cases = Vec::new();
566
3
    for t1 in values {
567
6
        for t2 in values {
568
12
            for t3 in values {
569
24
                for t4 in values {
570
48
                    for t5 in values {
571
96
                        for t6 in values {
572
192
                            for t7 in values {
573
128
                                cases.push((t1, t2, t3, t4, t5, t6, t7));
574
128
                            }
575
                        }
576
                    }
577
                }
578
            }
579
        }
580
    }
581
1
    roundtrip(cases);
582
1

            
583
1
    let mut cases = Vec::new();
584
3
    for t1 in values {
585
6
        for t2 in values {
586
12
            for t3 in values {
587
24
                for t4 in values {
588
48
                    for t5 in values {
589
96
                        for t6 in values {
590
192
                            for t7 in values {
591
384
                                for t8 in values {
592
256
                                    cases.push((t1, t2, t3, t4, t5, t6, t7, t8));
593
256
                                }
594
                            }
595
                        }
596
                    }
597
                }
598
            }
599
        }
600
    }
601
1
    roundtrip(cases);
602
1
}
603

            
604
/// An error occurred inside of one of the composite key fields.
605
#[derive(thiserror::Error, Debug)]
606
#[error("key error: {0}")]
607
pub struct CompositeKeyError(Box<dyn AnyError>);
608

            
609
impl CompositeKeyError {
610
    pub(crate) fn new<E: AnyError>(error: E) -> Self {
611
        Self(Box::new(error))
612
    }
613
}
614

            
615
impl From<TryFromIntError> for CompositeKeyError {
616
    fn from(err: TryFromIntError) -> Self {
617
        Self::new(err)
618
    }
619
}
620

            
621
impl From<std::io::Error> for CompositeKeyError {
622
    fn from(err: std::io::Error) -> Self {
623
        Self::new(err)
624
    }
625
}
626

            
627
impl<'a> Key<'a> for Signed {
628
    type Error = std::io::Error;
629

            
630
    const LENGTH: Option<usize> = None;
631

            
632
    fn as_ord_bytes(&self) -> Result<Cow<'a, [u8]>, Self::Error> {
633
        self.to_variable_vec().map(Cow::Owned)
634
    }
635

            
636
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
637
        Self::decode_variable(bytes)
638
    }
639

            
640
    fn first_value() -> Result<Self, NextValueError> {
641
        Ok(Self::from(0_i128))
642
    }
643

            
644
    fn next_value(&self) -> Result<Self, NextValueError> {
645
        i128::try_from(*self)
646
            .ok()
647
            .and_then(|key| key.checked_add(1))
648
            .map(Self::from)
649
            .ok_or(NextValueError::WouldWrap)
650
    }
651
}
652

            
653
impl<'a> Key<'a> for Unsigned {
654
    type Error = std::io::Error;
655

            
656
    const LENGTH: Option<usize> = None;
657

            
658
3584
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
659
3584
        self.to_variable_vec().map(Cow::Owned)
660
3584
    }
661

            
662
3584
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
663
3584
        Self::decode_variable(bytes)
664
3584
    }
665

            
666
    fn first_value() -> Result<Self, NextValueError> {
667
        Ok(Self::from(0_u128))
668
    }
669

            
670
    fn next_value(&self) -> Result<Self, NextValueError> {
671
        u128::try_from(*self)
672
            .ok()
673
            .and_then(|key| key.checked_add(1))
674
            .map(Self::from)
675
            .ok_or(NextValueError::WouldWrap)
676
    }
677
}
678

            
679
#[cfg(feature = "uuid")]
680
impl<'k> Key<'k> for uuid::Uuid {
681
    type Error = std::array::TryFromSliceError;
682

            
683
    const LENGTH: Option<usize> = Some(16);
684

            
685
    fn as_ord_bytes(&'k self) -> Result<Cow<'k, [u8]>, Self::Error> {
686
        Ok(Cow::Borrowed(self.as_bytes()))
687
    }
688

            
689
    fn from_ord_bytes(bytes: &'k [u8]) -> Result<Self, Self::Error> {
690
        Ok(Self::from_bytes(bytes.try_into()?))
691
    }
692
}
693

            
694
impl<'a, T> Key<'a> for Option<T>
695
where
696
    T: Key<'a>,
697
{
698
    type Error = T::Error;
699

            
700
    const LENGTH: Option<usize> = T::LENGTH;
701

            
702
    /// # Panics
703
    ///
704
    /// Panics if `T::into_big_endian_bytes` returns an empty `IVec`.
705
    // TODO consider removing this panic limitation by adding a single byte to
706
    // each key (at the end preferrably) so that we can distinguish between None
707
    // and a 0-byte type
708
4411
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
709
4411
        if let Some(contents) = self {
710
3735
            let contents = contents.as_ord_bytes()?;
711
3735
            assert!(!contents.is_empty());
712
3735
            Ok(contents)
713
        } else {
714
676
            Ok(Cow::default())
715
        }
716
4411
    }
717

            
718
4112
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
719
4112
        if bytes.is_empty() {
720
1350
            Ok(None)
721
        } else {
722
2762
            Ok(Some(T::from_ord_bytes(bytes)?))
723
        }
724
4112
    }
725

            
726
    fn first_value() -> Result<Self, NextValueError> {
727
        Ok(Some(T::first_value()?))
728
    }
729

            
730
    fn next_value(&self) -> Result<Self, NextValueError> {
731
        self.as_ref().map(T::next_value).transpose()
732
    }
733
}
734

            
735
/// Adds `Key` support to an enum. Requires implementing
736
/// [`ToPrimitive`](num_traits::ToPrimitive) and
737
/// [`FromPrimitive`](num_traits::FromPrimitive), or using a crate like
738
/// [num-derive](https://crates.io/crates/num-derive) to do it automatically.
739
/// Take care when using enums as keys: if the order changes or if the meaning
740
/// of existing numerical values changes, make sure to update any related views'
741
/// version number to ensure the values are re-evaluated.
742
pub trait EnumKey: ToPrimitive + FromPrimitive + Clone + std::fmt::Debug + Send + Sync {}
743

            
744
/// An error that indicates an unexpected number of bytes were present.
745
#[derive(thiserror::Error, Debug)]
746
#[error("incorrect byte length")]
747
pub struct IncorrectByteLength;
748

            
749
/// An error that indicates an unexpected enum variant value was found.
750
#[derive(thiserror::Error, Debug)]
751
#[error("unknown enum variant")]
752
pub struct UnknownEnumVariant;
753

            
754
impl From<std::array::TryFromSliceError> for IncorrectByteLength {
755
    fn from(_: std::array::TryFromSliceError) -> Self {
756
        Self
757
    }
758
}
759

            
760
// ANCHOR: impl_key_for_enumkey
761
impl<'a, T> Key<'a> for T
762
where
763
    T: EnumKey,
764
{
765
    type Error = std::io::Error;
766
    const LENGTH: Option<usize> = None;
767

            
768
4
    fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
769
4
        let integer = self
770
4
            .to_u64()
771
4
            .map(Unsigned::from)
772
4
            .ok_or_else(|| std::io::Error::new(ErrorKind::InvalidData, IncorrectByteLength))?;
773
4
        Ok(Cow::Owned(integer.to_variable_vec()?))
774
4
    }
775

            
776
2
    fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
777
2
        let primitive = u64::decode_variable(bytes)?;
778
2
        Self::from_u64(primitive)
779
2
            .ok_or_else(|| std::io::Error::new(ErrorKind::InvalidData, UnknownEnumVariant))
780
2
    }
781
}
782
// ANCHOR_END: impl_key_for_enumkey
783

            
784
macro_rules! impl_key_for_primitive {
785
    ($type:ident) => {
786
        impl<'a> Key<'a> for $type {
787
            type Error = IncorrectByteLength;
788
            const LENGTH: Option<usize> = Some(std::mem::size_of::<$type>());
789

            
790
1622275
            fn as_ord_bytes(&'a self) -> Result<Cow<'a, [u8]>, Self::Error> {
791
1622275
                Ok(Cow::from(self.to_be_bytes().to_vec()))
792
1622275
            }
793

            
794
1457294
            fn from_ord_bytes(bytes: &'a [u8]) -> Result<Self, Self::Error> {
795
1457294
                Ok($type::from_be_bytes(bytes.try_into()?))
796
1457294
            }
797

            
798
23301
            fn first_value() -> Result<Self, NextValueError> {
799
23301
                Ok(0)
800
23301
            }
801

            
802
283959
            fn next_value(&self) -> Result<Self, NextValueError> {
803
283959
                self.checked_add(1).ok_or(NextValueError::WouldWrap)
804
283959
            }
805
        }
806
    };
807
}
808

            
809
impl_key_for_primitive!(i8);
810
impl_key_for_primitive!(u8);
811
impl_key_for_primitive!(i16);
812
impl_key_for_primitive!(u16);
813
impl_key_for_primitive!(i32);
814
impl_key_for_primitive!(u32);
815
impl_key_for_primitive!(i64);
816
impl_key_for_primitive!(u64);
817
impl_key_for_primitive!(i128);
818
impl_key_for_primitive!(u128);
819

            
820
1
#[test]
821
#[allow(clippy::cognitive_complexity)] // I disagree - @ecton
822
1
fn primitive_key_encoding_tests() -> anyhow::Result<()> {
823
1
    macro_rules! test_primitive_extremes {
824
1
        ($type:ident) => {
825
1
            assert_eq!(
826
1
                &$type::MAX.to_be_bytes(),
827
1
                $type::MAX.as_ord_bytes()?.as_ref()
828
1
            );
829
1
            assert_eq!(
830
1
                $type::MAX,
831
1
                $type::from_ord_bytes(&$type::MAX.as_ord_bytes()?)?
832
1
            );
833
1
            assert_eq!(
834
1
                $type::MIN,
835
1
                $type::from_ord_bytes(&$type::MIN.as_ord_bytes()?)?
836
1
            );
837
1
        };
838
1
    }
839
1

            
840
1
    test_primitive_extremes!(i8);
841
1
    test_primitive_extremes!(u8);
842
1
    test_primitive_extremes!(i16);
843
1
    test_primitive_extremes!(u16);
844
1
    test_primitive_extremes!(i32);
845
1
    test_primitive_extremes!(u32);
846
1
    test_primitive_extremes!(i64);
847
1
    test_primitive_extremes!(u64);
848
1
    test_primitive_extremes!(i128);
849
1
    test_primitive_extremes!(u128);
850

            
851
1
    Ok(())
852
1
}
853

            
854
1
#[test]
855
1
fn optional_key_encoding_tests() -> anyhow::Result<()> {
856
1
    assert!(Option::<i8>::None.as_ord_bytes()?.is_empty());
857
1
    assert_eq!(
858
1
        Some(1_i8),
859
1
        Option::from_ord_bytes(&Some(1_i8).as_ord_bytes()?)?
860
    );
861
1
    Ok(())
862
1
}
863

            
864
1
#[test]
865
#[allow(clippy::unit_cmp)] // this is more of a compilation test
866
1
fn unit_key_encoding_tests() -> anyhow::Result<()> {
867
1
    assert!(().as_ord_bytes()?.is_empty());
868
1
    assert_eq!((), <() as Key>::from_ord_bytes(&[])?);
869
1
    Ok(())
870
1
}
871

            
872
1
#[test]
873
#[allow(clippy::unit_cmp)] // this is more of a compilation test
874
1
fn bool_key_encoding_tests() -> anyhow::Result<()> {
875
1
    let true_as_bytes = true.as_ord_bytes()?;
876
1
    let false_as_bytes = false.as_ord_bytes()?;
877
1
    assert!(bool::from_ord_bytes(&true_as_bytes)?);
878
1
    assert!(!bool::from_ord_bytes(&false_as_bytes)?);
879
1
    Ok(())
880
1
}
881

            
882
1
#[test]
883
1
fn vec_key_encoding_tests() -> anyhow::Result<()> {
884
1
    const ORIGINAL_VALUE: &[u8] = b"bonsaidb";
885
1
    let vec = Cow::<'_, [u8]>::from(ORIGINAL_VALUE);
886
1
    assert_eq!(vec.clone(), Cow::from_ord_bytes(&vec.as_ord_bytes()?)?);
887
1
    Ok(())
888
1
}
889

            
890
1
#[test]
891
#[allow(clippy::use_self)] // Weird interaction with num_derive
892
1
fn enum_derive_tests() -> anyhow::Result<()> {
893
4
    #[derive(Debug, Clone, num_derive::ToPrimitive, num_derive::FromPrimitive)]
894
    enum SomeEnum {
895
        One = 1,
896
        NineNineNine = 999,
897
    }
898

            
899
    impl EnumKey for SomeEnum {}
900

            
901
1
    let encoded = SomeEnum::One.as_ord_bytes()?;
902
1
    let value = SomeEnum::from_ord_bytes(&encoded)?;
903
1
    assert!(matches!(value, SomeEnum::One));
904

            
905
1
    let encoded = SomeEnum::NineNineNine.as_ord_bytes()?;
906
1
    let value = SomeEnum::from_ord_bytes(&encoded)?;
907
1
    assert!(matches!(value, SomeEnum::NineNineNine));
908

            
909
1
    Ok(())
910
1
}