Coverage Report

Created: 2026-03-31 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/radix_trie-0.3.0/src/keys.rs
Line
Count
Source
1
use endian_type::{BigEndian, LittleEndian};
2
use nibble_vec::Nibblet;
3
use std::path::{Path, PathBuf};
4
5
/// Trait for types which can be used to key a Radix Trie.
6
///
7
/// Types that implement this trait should be convertible to a vector of half-bytes (nibbles)
8
/// such that no two instances of the type convert to the same vector.
9
/// To protect against faulty behaviour, the trie will **panic** if it finds two distinct keys
10
/// of type `K` which encode to the same `Nibblet`, so be careful!
11
///
12
/// If you would like to implement this trait for your own type, you need to implement
13
/// *either* `encode_bytes` or `encode`. You only need to implement one of the two.
14
/// If you don't implement one, your code will **panic** as soon you use the trie.
15
/// There is no performance penalty for implementing `encode_bytes` instead of `encode`,
16
/// so it is preferred except in the case where you require half-byte precision.
17
///
18
/// Many standard types implement this trait already. Integer types are encoded *big-endian*
19
/// by default but can be encoded little-endian using the `LittleEndian<T>` wrapper type.
20
pub trait TrieKey: PartialEq + Eq {
21
    /// Encode a value as a vector of bytes.
22
0
    fn encode_bytes(&self) -> Vec<u8> {
23
0
        panic!("implement this method or TrieKey::encode");
24
    }
25
26
    /// Encode a value as a NibbleVec.
27
    #[inline]
28
0
    fn encode(&self) -> Nibblet {
29
0
        Nibblet::from_byte_vec(self.encode_bytes())
30
0
    }
Unexecuted instantiation: <alloc::vec::Vec<u8> as radix_trie::keys::TrieKey>::encode
Unexecuted instantiation: <_ as radix_trie::keys::TrieKey>::encode
31
}
32
33
/// Key comparison result.
34
#[derive(Debug)]
35
pub enum KeyMatch {
36
    /// The keys match up to the given index.
37
    Partial(usize),
38
    /// The first key is a prefix of the second.
39
    FirstPrefix,
40
    /// The second key is a prefix of the first.
41
    SecondPrefix,
42
    /// The keys match exactly.
43
    Full,
44
}
45
46
/// Compare two Trie keys.
47
///
48
/// Compares `first[start_idx .. ]` to `second`, i.e. only looks at a slice of the first key.
49
#[inline]
50
0
pub fn match_keys(start_idx: usize, first: &Nibblet, second: &Nibblet) -> KeyMatch {
51
0
    let first_len = first.len() - start_idx;
52
0
    let min_length = ::std::cmp::min(first_len, second.len());
53
54
0
    for i in 0..min_length {
55
0
        if first.get(start_idx + i) != second.get(i) {
56
0
            return KeyMatch::Partial(i);
57
0
        }
58
    }
59
60
0
    match (first_len, second.len()) {
61
0
        (x, y) if x < y => KeyMatch::FirstPrefix,
62
0
        (x, y) if x == y => KeyMatch::Full,
63
0
        _ => KeyMatch::SecondPrefix,
64
    }
65
0
}
Unexecuted instantiation: radix_trie::keys::match_keys
Unexecuted instantiation: radix_trie::keys::match_keys
66
67
/// Check two keys for equality and panic if they differ.
68
#[inline]
69
0
pub fn check_keys<K: ?Sized>(key1: &K, key2: &K)
70
0
where
71
0
    K: TrieKey,
72
{
73
0
    if *key1 != *key2 {
74
0
        panic!("multiple-keys with the same bit representation.");
75
0
    }
76
0
}
Unexecuted instantiation: radix_trie::keys::check_keys::<alloc::vec::Vec<u8>>
Unexecuted instantiation: radix_trie::keys::check_keys::<_>
77
78
// --- TrieKey Implementations for standard types --- ///
79
80
// This blanket implementation goes into play when specialization is stabilized
81
// impl<T> TrieKey for T where T: Into<Vec<u8>> + Clone + Eq + PartialEq {
82
// fn encode_bytes(&self) -> Vec<u8> {
83
// self.clone().into()
84
// }
85
// }
86
87
impl TrieKey for Vec<u8> {
88
    #[inline]
89
0
    fn encode_bytes(&self) -> Vec<u8> {
90
0
        self.clone()
91
0
    }
Unexecuted instantiation: <alloc::vec::Vec<u8> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <alloc::vec::Vec<u8> as radix_trie::keys::TrieKey>::encode_bytes
92
}
93
94
impl TrieKey for [u8] {
95
    #[inline]
96
0
    fn encode_bytes(&self) -> Vec<u8> {
97
0
        self.to_vec()
98
0
    }
99
}
100
101
impl TrieKey for String {
102
    #[inline]
103
0
    fn encode_bytes(&self) -> Vec<u8> {
104
0
        self.as_bytes().encode_bytes()
105
0
    }
106
}
107
108
impl TrieKey for str {
109
    #[inline]
110
0
    fn encode_bytes(&self) -> Vec<u8> {
111
0
        self.as_bytes().encode_bytes()
112
0
    }
113
}
114
115
impl<T: ?Sized + TrieKey> TrieKey for &T {
116
    #[inline]
117
0
    fn encode_bytes(&self) -> Vec<u8> {
118
0
        (**self).encode_bytes()
119
0
    }
120
}
121
122
impl<T: ?Sized + TrieKey> TrieKey for &mut T {
123
    #[inline]
124
0
    fn encode_bytes(&self) -> Vec<u8> {
125
0
        (**self).encode_bytes()
126
0
    }
127
}
128
129
impl TrieKey for i8 {
130
    #[inline]
131
0
    fn encode_bytes(&self) -> Vec<u8> {
132
0
        let mut v: Vec<u8> = Vec::with_capacity(1);
133
0
        v.push(*self as u8);
134
0
        v
135
0
    }
136
}
137
138
impl TrieKey for u8 {
139
    #[inline]
140
0
    fn encode_bytes(&self) -> Vec<u8> {
141
0
        let mut v: Vec<u8> = Vec::with_capacity(1);
142
0
        v.push(*self);
143
0
        v
144
0
    }
145
}
146
147
#[cfg(unix)]
148
impl TrieKey for PathBuf {
149
0
    fn encode_bytes(&self) -> Vec<u8> {
150
        use std::ffi::OsString;
151
        use std::os::unix::ffi::OsStringExt;
152
0
        let str: OsString = self.clone().into();
153
0
        str.into_vec()
154
0
    }
155
}
156
157
#[cfg(unix)]
158
impl TrieKey for Path {
159
0
    fn encode_bytes(&self) -> Vec<u8> {
160
        use std::os::unix::ffi::OsStrExt;
161
0
        self.as_os_str().as_bytes().encode_bytes()
162
0
    }
163
}
164
165
#[cfg(windows)]
166
impl TrieKey for PathBuf {
167
    fn encode_bytes(&self) -> Vec<u8> {
168
        self.as_os_str().as_encoded_bytes().to_vec()
169
    }
170
}
171
172
#[cfg(windows)]
173
impl TrieKey for Path {
174
    fn encode_bytes(&self) -> Vec<u8> {
175
        self.as_os_str().as_encoded_bytes().to_vec()
176
    }
177
}
178
179
impl<T> TrieKey for LittleEndian<T>
180
where
181
    T: Eq + Copy,
182
{
183
0
    fn encode_bytes(&self) -> Vec<u8> {
184
0
        self.as_byte_slice().encode_bytes()
185
0
    }
186
}
187
188
impl<T> TrieKey for BigEndian<T>
189
where
190
    T: Eq + Copy,
191
{
192
0
    fn encode_bytes(&self) -> Vec<u8> {
193
0
        self.as_byte_slice().to_vec()
194
0
    }
Unexecuted instantiation: <endian_type::BigEndian<isize> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <endian_type::BigEndian<usize> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <endian_type::BigEndian<i32> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <endian_type::BigEndian<u32> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <endian_type::BigEndian<i16> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <endian_type::BigEndian<u16> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <endian_type::BigEndian<i64> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <endian_type::BigEndian<u64> as radix_trie::keys::TrieKey>::encode_bytes
195
}
196
197
macro_rules! int_keys {
198
    ( $( $t:ty ),* ) => {
199
        $(
200
        impl TrieKey for $t {
201
0
            fn encode_bytes(&self) -> Vec<u8> {
202
0
                let be: BigEndian<$t> = From::from(*self);
203
0
                be.encode_bytes()
204
0
            }
Unexecuted instantiation: <u16 as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <u32 as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <u64 as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <i16 as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <i32 as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <i64 as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <usize as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <isize as radix_trie::keys::TrieKey>::encode_bytes
205
        }
206
        )*
207
    };
208
}
209
210
int_keys!(u16, u32, u64, i16, i32, i64, usize, isize);
211
212
macro_rules! vec_int_keys {
213
  ( $( $t:ty ),* ) => {
214
      $(
215
      impl TrieKey for Vec<$t> {
216
0
          fn encode_bytes(&self) -> Vec<u8> {
217
0
              let mut v = Vec::<u8>::with_capacity(self.len() * std::mem::size_of::<$t>());
218
0
              for u in self {
219
0
                  v.extend_from_slice(&u.to_be_bytes());
220
0
              }
221
0
              v
222
0
          }
Unexecuted instantiation: <alloc::vec::Vec<u16> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <alloc::vec::Vec<u32> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <alloc::vec::Vec<u64> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <alloc::vec::Vec<i16> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <alloc::vec::Vec<i32> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <alloc::vec::Vec<i64> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <alloc::vec::Vec<usize> as radix_trie::keys::TrieKey>::encode_bytes
Unexecuted instantiation: <alloc::vec::Vec<isize> as radix_trie::keys::TrieKey>::encode_bytes
223
      }
224
      )*
225
   };
226
}
227
228
vec_int_keys!(u16, u32, u64, i16, i32, i64, usize, isize);
229
230
#[cfg(test)]
231
mod test {
232
    pub trait DefaultTrieKey {
233
        fn encode_bytes(&self) -> Vec<u8>;
234
    }
235
236
    impl<T: Into<Vec<u8>> + Clone + PartialEq + Eq> DefaultTrieKey for T {
237
        #[inline]
238
        fn encode_bytes(&self) -> Vec<u8> {
239
            self.clone().into()
240
        }
241
    }
242
243
    macro_rules! encode_bytes {
244
        ($e:expr) => {
245
            (&$e).encode_bytes()
246
        };
247
    }
248
249
    #[test]
250
    fn test_autoref_specialization() {
251
        let _ = encode_bytes!([0_u8]);
252
        let _ = encode_bytes!("hello");
253
        let _ = encode_bytes!("hello".to_string());
254
    }
255
}