heed_traits/lib.rs
1#![doc(
2 html_favicon_url = "https://raw.githubusercontent.com/meilisearch/heed/main/assets//heed-pigeon.ico?raw=true"
3)]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/meilisearch/heed/main/assets/heed-pigeon-logo.png?raw=true"
6)]
7
8//! Contains the traits used to encode and decode database content.
9
10#![warn(missing_docs)]
11
12use std::borrow::Cow;
13use std::cmp::{Ord, Ordering};
14use std::error::Error as StdError;
15
16/// A boxed `Send + Sync + 'static` error.
17pub type BoxedError = Box<dyn StdError + Send + Sync + 'static>;
18
19/// A trait that represents an encoding structure.
20pub trait BytesEncode<'a> {
21 /// The type to encode.
22 type EItem: ?Sized + 'a;
23
24 /// Encode the given item as bytes.
25 fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<'a, [u8]>, BoxedError>;
26}
27
28/// A trait that represents a decoding structure.
29pub trait BytesDecode<'a> {
30 /// The type to decode.
31 type DItem: 'a;
32
33 /// Decode the given bytes as `DItem`.
34 fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError>;
35}
36
37/// Define a custom key comparison function for a database.
38///
39/// The comparison function is called whenever it is necessary to compare a key specified
40/// by the application with a key currently stored in the database. If no comparison function
41/// is specified, and no special key flags were specified, the keys are compared lexically,
42/// with shorter keys collating before longer keys.
43pub trait Comparator {
44 /// Compares the raw bytes representation of two keys.
45 ///
46 /// # Safety
47 ///
48 /// This function must never crash, this is the reason why it takes raw bytes as parameter,
49 /// to let you define the recovery method you want in case of a decoding error.
50 fn compare(a: &[u8], b: &[u8]) -> Ordering;
51}
52
53/// Define a lexicographic comparator, which is a special case of [`Comparator`].
54///
55/// Types that implements [`LexicographicComparator`] will automatically have [`Comparator`]
56/// implemented as well, where the [`Comparator::compare`] is implemented per the definition
57/// of lexicographic ordering with [`LexicographicComparator::compare_elem`].
58///
59/// This trait is introduced to support prefix iterators, which implicit assumes that the
60/// underlying key comparator is lexicographic.
61pub trait LexicographicComparator: Comparator {
62 /// Compare a single byte; this function is used to implement [`Comparator::compare`]
63 /// by definition of lexicographic ordering.
64 ///
65 /// # Safety
66 ///
67 /// This function must never crash.
68 fn compare_elem(a: u8, b: u8) -> Ordering;
69
70 /// Advances the given `elem` to its immediate lexicographic successor, if possible.
71 /// Returns `None` if `elem` is already at its maximum value with respect to the
72 /// lexicographic order defined by this comparator.
73 fn successor(elem: u8) -> Option<u8>;
74
75 /// Moves the given `elem` to its immediate lexicographic predecessor, if possible.
76 /// Returns `None` if `elem` is already at its minimum value with respect to the
77 /// lexicographic order defined by this comparator.
78 fn predecessor(elem: u8) -> Option<u8>;
79
80 /// Returns the maximum byte value per the comparator's lexicographic order.
81 fn max_elem() -> u8;
82
83 /// Returns the minimum byte value per the comparator's lexicographic order.
84 fn min_elem() -> u8;
85}
86
87impl<C: LexicographicComparator> Comparator for C {
88 fn compare(a: &[u8], b: &[u8]) -> Ordering {
89 for idx in 0..std::cmp::min(a.len(), b.len()) {
90 if a[idx] != b[idx] {
91 return C::compare_elem(a[idx], b[idx]);
92 }
93 }
94 Ord::cmp(&a.len(), &b.len())
95 }
96}