redb/
types.rs

1use std::cmp::Ordering;
2use std::convert::TryInto;
3use std::fmt::Debug;
4use std::mem::size_of;
5#[cfg(feature = "chrono_v0_4")]
6mod chrono_v0_4;
7#[cfg(feature = "uuid")]
8mod uuid;
9
10#[derive(Eq, PartialEq, Clone, Debug)]
11enum TypeClassification {
12    Internal,
13    UserDefined,
14    // Used by variable width tuple encoding in version 3.0 and newer. This differentiates the encoding
15    // from the old encoding used previously
16    Internal2,
17}
18
19impl TypeClassification {
20    fn to_byte(&self) -> u8 {
21        match self {
22            TypeClassification::Internal => 1,
23            TypeClassification::UserDefined => 2,
24            TypeClassification::Internal2 => 3,
25        }
26    }
27
28    fn from_byte(value: u8) -> Self {
29        match value {
30            1 => TypeClassification::Internal,
31            2 => TypeClassification::UserDefined,
32            3 => TypeClassification::Internal2,
33            _ => unreachable!(),
34        }
35    }
36}
37
38#[derive(Eq, PartialEq, Debug, Clone)]
39pub struct TypeName {
40    classification: TypeClassification,
41    name: String,
42}
43
44impl TypeName {
45    /// It is recommended that `name` be prefixed with the crate name to minimize the chance of
46    /// it coliding with another user defined type
47    pub fn new(name: &str) -> Self {
48        Self {
49            classification: TypeClassification::UserDefined,
50            name: name.to_string(),
51        }
52    }
53
54    pub(crate) fn internal(name: &str) -> Self {
55        Self {
56            classification: TypeClassification::Internal,
57            name: name.to_string(),
58        }
59    }
60
61    pub(crate) fn internal2(name: &str) -> Self {
62        Self {
63            classification: TypeClassification::Internal2,
64            name: name.to_string(),
65        }
66    }
67
68    pub(crate) fn to_bytes(&self) -> Vec<u8> {
69        let mut result = Vec::with_capacity(self.name.len() + 1);
70        result.push(self.classification.to_byte());
71        result.extend_from_slice(self.name.as_bytes());
72        result
73    }
74
75    pub(crate) fn from_bytes(bytes: &[u8]) -> Self {
76        let classification = TypeClassification::from_byte(bytes[0]);
77        let name = std::str::from_utf8(&bytes[1..]).unwrap().to_string();
78
79        Self {
80            classification,
81            name,
82        }
83    }
84
85    pub fn name(&self) -> &str {
86        &self.name
87    }
88}
89
90/// Types that implement this trait can be used as values in a redb table
91pub trait Value: Debug {
92    /// `SelfType<'a>` must be the same type as Self with all lifetimes replaced with 'a
93    type SelfType<'a>: Debug + 'a
94    where
95        Self: 'a;
96
97    type AsBytes<'a>: AsRef<[u8]> + 'a
98    where
99        Self: 'a;
100
101    /// Width of a fixed type, or None for variable width
102    fn fixed_width() -> Option<usize>;
103
104    /// Deserializes data
105    /// Implementations may return a view over data, or an owned type
106    fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a>
107    where
108        Self: 'a;
109
110    /// Serialize the value to a slice
111    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Self::AsBytes<'a>
112    where
113        Self: 'b;
114
115    /// Globally unique identifier for this type
116    fn type_name() -> TypeName;
117}
118
119/// Implementing this trait indicates that the type can be mutated in-place as a &mut [u8].
120/// This enables the `.insert_reserve()` method on Table
121pub trait MutInPlaceValue: Value {
122    /// The base type such that &mut [u8] can be safely transmuted to `&mut BaseRefType`
123    type BaseRefType: Debug + ?Sized;
124
125    // Initialize `data` to a valid value. This method will be called (at some point, not necessarily immediately)
126    // before from_bytes_mut() is called on a slice.
127    fn initialize(data: &mut [u8]);
128
129    fn from_bytes_mut(data: &mut [u8]) -> &mut Self::BaseRefType;
130}
131
132impl MutInPlaceValue for &[u8] {
133    type BaseRefType = [u8];
134
135    fn initialize(_data: &mut [u8]) {
136        // no-op. All values are valid.
137    }
138
139    fn from_bytes_mut(data: &mut [u8]) -> &mut Self::BaseRefType {
140        data
141    }
142}
143
144/// Trait which allows the type to be used as a key in a redb table
145pub trait Key: Value {
146    /// Compare data1 with data2
147    fn compare(data1: &[u8], data2: &[u8]) -> Ordering;
148}
149
150impl Value for () {
151    type SelfType<'a>
152        = ()
153    where
154        Self: 'a;
155    type AsBytes<'a>
156        = &'a [u8]
157    where
158        Self: 'a;
159
160    fn fixed_width() -> Option<usize> {
161        Some(0)
162    }
163
164    #[allow(clippy::unused_unit, clippy::semicolon_if_nothing_returned)]
165    fn from_bytes<'a>(_data: &'a [u8]) -> ()
166    where
167        Self: 'a,
168    {
169        ()
170    }
171
172    #[allow(clippy::ignored_unit_patterns)]
173    fn as_bytes<'a, 'b: 'a>(_: &'a Self::SelfType<'b>) -> &'a [u8]
174    where
175        Self: 'b,
176    {
177        &[]
178    }
179
180    fn type_name() -> TypeName {
181        TypeName::internal("()")
182    }
183}
184
185impl Key for () {
186    fn compare(_data1: &[u8], _data2: &[u8]) -> Ordering {
187        Ordering::Equal
188    }
189}
190
191impl Value for bool {
192    type SelfType<'a>
193        = bool
194    where
195        Self: 'a;
196    type AsBytes<'a>
197        = &'a [u8]
198    where
199        Self: 'a;
200
201    fn fixed_width() -> Option<usize> {
202        Some(1)
203    }
204
205    fn from_bytes<'a>(data: &'a [u8]) -> bool
206    where
207        Self: 'a,
208    {
209        match data[0] {
210            0 => false,
211            1 => true,
212            _ => unreachable!(),
213        }
214    }
215
216    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a [u8]
217    where
218        Self: 'b,
219    {
220        match value {
221            true => &[1],
222            false => &[0],
223        }
224    }
225
226    fn type_name() -> TypeName {
227        TypeName::internal("bool")
228    }
229}
230
231impl Key for bool {
232    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
233        let value1 = Self::from_bytes(data1);
234        let value2 = Self::from_bytes(data2);
235        value1.cmp(&value2)
236    }
237}
238
239impl<T: Value> Value for Option<T> {
240    type SelfType<'a>
241        = Option<T::SelfType<'a>>
242    where
243        Self: 'a;
244    type AsBytes<'a>
245        = Vec<u8>
246    where
247        Self: 'a;
248
249    fn fixed_width() -> Option<usize> {
250        T::fixed_width().map(|x| x + 1)
251    }
252
253    fn from_bytes<'a>(data: &'a [u8]) -> Option<T::SelfType<'a>>
254    where
255        Self: 'a,
256    {
257        match data[0] {
258            0 => None,
259            1 => Some(T::from_bytes(&data[1..])),
260            _ => unreachable!(),
261        }
262    }
263
264    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Vec<u8>
265    where
266        Self: 'b,
267    {
268        let mut result = vec![0];
269        if let Some(x) = value {
270            result[0] = 1;
271            result.extend_from_slice(T::as_bytes(x).as_ref());
272        } else if let Some(fixed_width) = T::fixed_width() {
273            result.extend_from_slice(&vec![0; fixed_width]);
274        }
275        result
276    }
277
278    fn type_name() -> TypeName {
279        TypeName::internal(&format!("Option<{}>", T::type_name().name()))
280    }
281}
282
283impl<T: Key> Key for Option<T> {
284    #[allow(clippy::collapsible_else_if)]
285    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
286        if data1[0] == 0 {
287            if data2[0] == 0 {
288                Ordering::Equal
289            } else {
290                Ordering::Less
291            }
292        } else {
293            if data2[0] == 0 {
294                Ordering::Greater
295            } else {
296                T::compare(&data1[1..], &data2[1..])
297            }
298        }
299    }
300}
301
302impl Value for &[u8] {
303    type SelfType<'a>
304        = &'a [u8]
305    where
306        Self: 'a;
307    type AsBytes<'a>
308        = &'a [u8]
309    where
310        Self: 'a;
311
312    fn fixed_width() -> Option<usize> {
313        None
314    }
315
316    fn from_bytes<'a>(data: &'a [u8]) -> &'a [u8]
317    where
318        Self: 'a,
319    {
320        data
321    }
322
323    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a [u8]
324    where
325        Self: 'b,
326    {
327        value
328    }
329
330    fn type_name() -> TypeName {
331        TypeName::internal("&[u8]")
332    }
333}
334
335impl Key for &[u8] {
336    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
337        data1.cmp(data2)
338    }
339}
340
341impl<const N: usize> Value for &[u8; N] {
342    type SelfType<'a>
343        = &'a [u8; N]
344    where
345        Self: 'a;
346    type AsBytes<'a>
347        = &'a [u8; N]
348    where
349        Self: 'a;
350
351    fn fixed_width() -> Option<usize> {
352        Some(N)
353    }
354
355    fn from_bytes<'a>(data: &'a [u8]) -> &'a [u8; N]
356    where
357        Self: 'a,
358    {
359        data.try_into().unwrap()
360    }
361
362    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a [u8; N]
363    where
364        Self: 'b,
365    {
366        value
367    }
368
369    fn type_name() -> TypeName {
370        TypeName::internal(&format!("[u8;{N}]"))
371    }
372}
373
374impl<const N: usize> Key for &[u8; N] {
375    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
376        data1.cmp(data2)
377    }
378}
379
380impl<const N: usize, T: Value> Value for [T; N] {
381    type SelfType<'a>
382        = [T::SelfType<'a>; N]
383    where
384        Self: 'a;
385    type AsBytes<'a>
386        = Vec<u8>
387    where
388        Self: 'a;
389
390    fn fixed_width() -> Option<usize> {
391        T::fixed_width().map(|x| x * N)
392    }
393
394    fn from_bytes<'a>(data: &'a [u8]) -> [T::SelfType<'a>; N]
395    where
396        Self: 'a,
397    {
398        let mut result = Vec::with_capacity(N);
399        if let Some(fixed) = T::fixed_width() {
400            for i in 0..N {
401                result.push(T::from_bytes(&data[fixed * i..fixed * (i + 1)]));
402            }
403        } else {
404            // Set offset to the first data item
405            let mut start = size_of::<u32>() * N;
406            for i in 0..N {
407                let range = size_of::<u32>() * i..size_of::<u32>() * (i + 1);
408                let end = u32::from_le_bytes(data[range].try_into().unwrap()) as usize;
409                result.push(T::from_bytes(&data[start..end]));
410                start = end;
411            }
412        }
413        result.try_into().unwrap()
414    }
415
416    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Vec<u8>
417    where
418        Self: 'b,
419    {
420        if let Some(fixed) = T::fixed_width() {
421            let mut result = Vec::with_capacity(fixed * N);
422            for item in value {
423                result.extend_from_slice(T::as_bytes(item).as_ref());
424            }
425            result
426        } else {
427            // Reserve space for the end offsets
428            let mut result = vec![0u8; size_of::<u32>() * N];
429            for i in 0..N {
430                result.extend_from_slice(T::as_bytes(&value[i]).as_ref());
431                let end: u32 = result.len().try_into().unwrap();
432                result[size_of::<u32>() * i..size_of::<u32>() * (i + 1)]
433                    .copy_from_slice(&end.to_le_bytes());
434            }
435            result
436        }
437    }
438
439    fn type_name() -> TypeName {
440        // Uses the same type name as [T;N] so that tables are compatible with [u8;N] and &[u8;N] types
441        // This requires that the binary encoding be the same
442        TypeName::internal(&format!("[{};{N}]", T::type_name().name()))
443    }
444}
445
446impl<const N: usize, T: Key> Key for [T; N] {
447    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
448        if let Some(fixed) = T::fixed_width() {
449            for i in 0..N {
450                let range = fixed * i..fixed * (i + 1);
451                let comparison = T::compare(&data1[range.clone()], &data2[range]);
452                if !comparison.is_eq() {
453                    return comparison;
454                }
455            }
456        } else {
457            // Set offset to the first data item
458            let mut start1 = size_of::<u32>() * N;
459            let mut start2 = size_of::<u32>() * N;
460            for i in 0..N {
461                let range = size_of::<u32>() * i..size_of::<u32>() * (i + 1);
462                let end1 = u32::from_le_bytes(data1[range.clone()].try_into().unwrap()) as usize;
463                let end2 = u32::from_le_bytes(data2[range].try_into().unwrap()) as usize;
464                let comparison = T::compare(&data1[start1..end1], &data2[start2..end2]);
465                if !comparison.is_eq() {
466                    return comparison;
467                }
468                start1 = end1;
469                start2 = end2;
470            }
471        }
472        Ordering::Equal
473    }
474}
475
476impl Value for &str {
477    type SelfType<'a>
478        = &'a str
479    where
480        Self: 'a;
481    type AsBytes<'a>
482        = &'a str
483    where
484        Self: 'a;
485
486    fn fixed_width() -> Option<usize> {
487        None
488    }
489
490    fn from_bytes<'a>(data: &'a [u8]) -> &'a str
491    where
492        Self: 'a,
493    {
494        std::str::from_utf8(data).unwrap()
495    }
496
497    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a str
498    where
499        Self: 'b,
500    {
501        value
502    }
503
504    fn type_name() -> TypeName {
505        TypeName::internal("&str")
506    }
507}
508
509impl Key for &str {
510    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
511        let str1 = Self::from_bytes(data1);
512        let str2 = Self::from_bytes(data2);
513        str1.cmp(str2)
514    }
515}
516
517impl Value for String {
518    type SelfType<'a>
519        = String
520    where
521        Self: 'a;
522    type AsBytes<'a>
523        = &'a str
524    where
525        Self: 'a;
526
527    fn fixed_width() -> Option<usize> {
528        None
529    }
530
531    fn from_bytes<'a>(data: &'a [u8]) -> String
532    where
533        Self: 'a,
534    {
535        std::str::from_utf8(data).unwrap().to_string()
536    }
537
538    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a str
539    where
540        Self: 'b,
541    {
542        value.as_str()
543    }
544
545    fn type_name() -> TypeName {
546        TypeName::internal("String")
547    }
548}
549
550impl Key for String {
551    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
552        let str1 = std::str::from_utf8(data1).unwrap();
553        let str2 = std::str::from_utf8(data2).unwrap();
554        str1.cmp(str2)
555    }
556}
557
558impl Value for char {
559    type SelfType<'a> = char;
560    type AsBytes<'a>
561        = [u8; 3]
562    where
563        Self: 'a;
564
565    fn fixed_width() -> Option<usize> {
566        Some(3)
567    }
568
569    fn from_bytes<'a>(data: &'a [u8]) -> char
570    where
571        Self: 'a,
572    {
573        char::from_u32(u32::from_le_bytes([data[0], data[1], data[2], 0])).unwrap()
574    }
575
576    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> [u8; 3]
577    where
578        Self: 'b,
579    {
580        let bytes = u32::from(*value).to_le_bytes();
581        [bytes[0], bytes[1], bytes[2]]
582    }
583
584    fn type_name() -> TypeName {
585        TypeName::internal(stringify!(char))
586    }
587}
588
589impl Key for char {
590    fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
591        Self::from_bytes(data1).cmp(&Self::from_bytes(data2))
592    }
593}
594
595macro_rules! le_value {
596    ($t:ty) => {
597        impl Value for $t {
598            type SelfType<'a> = $t;
599            type AsBytes<'a>
600                = [u8; std::mem::size_of::<$t>()]
601            where
602                Self: 'a;
603
604            fn fixed_width() -> Option<usize> {
605                Some(std::mem::size_of::<$t>())
606            }
607
608            fn from_bytes<'a>(data: &'a [u8]) -> $t
609            where
610                Self: 'a,
611            {
612                <$t>::from_le_bytes(data.try_into().unwrap())
613            }
614
615            fn as_bytes<'a, 'b: 'a>(
616                value: &'a Self::SelfType<'b>,
617            ) -> [u8; std::mem::size_of::<$t>()]
618            where
619                Self: 'a,
620                Self: 'b,
621            {
622                value.to_le_bytes()
623            }
624
625            fn type_name() -> TypeName {
626                TypeName::internal(stringify!($t))
627            }
628        }
629    };
630}
631
632macro_rules! le_impl {
633    ($t:ty) => {
634        le_value!($t);
635
636        impl Key for $t {
637            fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
638                Self::from_bytes(data1).cmp(&Self::from_bytes(data2))
639            }
640        }
641    };
642}
643
644le_impl!(u8);
645le_impl!(u16);
646le_impl!(u32);
647le_impl!(u64);
648le_impl!(u128);
649le_impl!(i8);
650le_impl!(i16);
651le_impl!(i32);
652le_impl!(i64);
653le_impl!(i128);
654le_value!(f32);
655le_value!(f64);