1use endian_type::{BigEndian, LittleEndian};
2use std::ffi::OsString;
3use std::path::{Path, PathBuf};
4
5use nibble_vec::Nibblet;
6
7pub trait TrieKey: PartialEq + Eq {
23 fn encode_bytes(&self) -> Vec<u8> {
25 panic!("implement this method or TrieKey::encode");
26 }
27
28 #[inline]
30 fn encode(&self) -> Nibblet {
31 Nibblet::from_byte_vec(self.encode_bytes())
32 }
33}
34
35#[derive(Debug)]
37pub enum KeyMatch {
38 Partial(usize),
40 FirstPrefix,
42 SecondPrefix,
44 Full,
46}
47
48#[inline]
52pub fn match_keys(start_idx: usize, first: &Nibblet, second: &Nibblet) -> KeyMatch {
53 let first_len = first.len() - start_idx;
54 let min_length = ::std::cmp::min(first_len, second.len());
55
56 for i in 0..min_length {
57 if first.get(start_idx + i) != second.get(i) {
58 return KeyMatch::Partial(i);
59 }
60 }
61
62 match (first_len, second.len()) {
63 (x, y) if x < y => KeyMatch::FirstPrefix,
64 (x, y) if x == y => KeyMatch::Full,
65 _ => KeyMatch::SecondPrefix,
66 }
67}
68
69#[inline]
71pub fn check_keys<K: ?Sized>(key1: &K, key2: &K)
72where
73 K: TrieKey,
74{
75 if *key1 != *key2 {
76 panic!("multiple-keys with the same bit representation.");
77 }
78}
79
80impl TrieKey for Vec<u8> {
90 #[inline]
91 fn encode_bytes(&self) -> Vec<u8> {
92 self.clone()
93 }
94}
95
96impl TrieKey for [u8] {
97 #[inline]
98 fn encode_bytes(&self) -> Vec<u8> {
99 self.to_vec()
100 }
101}
102
103impl TrieKey for String {
104 #[inline]
105 fn encode_bytes(&self) -> Vec<u8> {
106 self.as_bytes().encode_bytes()
107 }
108}
109
110impl TrieKey for str {
111 #[inline]
112 fn encode_bytes(&self) -> Vec<u8> {
113 self.as_bytes().encode_bytes()
114 }
115}
116
117impl<'a, T: ?Sized + TrieKey> TrieKey for &'a T {
118 #[inline]
119 fn encode_bytes(&self) -> Vec<u8> {
120 (**self).encode_bytes()
121 }
122}
123
124impl<'a, T: ?Sized + TrieKey> TrieKey for &'a mut T {
125 #[inline]
126 fn encode_bytes(&self) -> Vec<u8> {
127 (**self).encode_bytes()
128 }
129}
130
131impl TrieKey for i8 {
132 #[inline]
133 fn encode_bytes(&self) -> Vec<u8> {
134 let mut v: Vec<u8> = Vec::with_capacity(1);
135 v.push(*self as u8);
136 v
137 }
138}
139
140impl TrieKey for u8 {
141 #[inline]
142 fn encode_bytes(&self) -> Vec<u8> {
143 let mut v: Vec<u8> = Vec::with_capacity(1);
144 v.push(*self);
145 v
146 }
147}
148
149#[cfg(unix)]
150impl TrieKey for PathBuf {
151 fn encode_bytes(&self) -> Vec<u8> {
152 use std::os::unix::ffi::OsStringExt;
153 let str: OsString = self.clone().into();
154 str.into_vec()
155 }
156}
157
158#[cfg(unix)]
159impl TrieKey for Path {
160 fn encode_bytes(&self) -> Vec<u8> {
161 use std::os::unix::ffi::OsStrExt;
162 self.as_os_str().as_bytes().encode_bytes()
163 }
164}
165
166impl<T> TrieKey for LittleEndian<T>
167where
168 T: Eq + Copy,
169{
170 fn encode_bytes(&self) -> Vec<u8> {
171 self.as_bytes().encode_bytes()
172 }
173}
174
175impl<T> TrieKey for BigEndian<T>
176where
177 T: Eq + Copy,
178{
179 fn encode_bytes(&self) -> Vec<u8> {
180 self.as_bytes().to_vec()
181 }
182}
183
184macro_rules! int_keys {
185 ( $( $t:ty ),* ) => {
186 $(
187 impl TrieKey for $t {
188 fn encode_bytes(&self) -> Vec<u8> {
189 let be: BigEndian<$t> = From::from(*self);
190 be.encode_bytes()
191 }
192 }
193 )*
194 };
195}
196
197int_keys!(u16, u32, u64, i16, i32, i64, usize, isize);
198
199#[cfg(test)]
200mod test {
201 pub trait DefaultTrieKey {
202 fn encode_bytes(&self) -> Vec<u8>;
203 }
204
205 impl<T: Into<Vec<u8>> + Clone + PartialEq + Eq> DefaultTrieKey for T {
206 #[inline]
207 fn encode_bytes(&self) -> Vec<u8> {
208 self.clone().into()
209 }
210 }
211
212 pub trait AsTrieKey {
213 fn encode_bytes(&self) -> Vec<u8>;
214 }
215
216 impl<T: AsRef<[u8]> + Clone + PartialEq + Eq> AsTrieKey for &T {
217 #[inline]
218 fn encode_bytes(&self) -> Vec<u8> {
219 self.as_ref().to_vec()
220 }
221 }
222
223 macro_rules! encode_bytes {
224 ($e:expr) => {
225 (&$e).encode_bytes()
226 };
227 }
228
229 #[test]
230 fn test_autoref_specialization() {
231 let _ = encode_bytes!([0_u8]);
232 let _ = encode_bytes!("hello");
233 let _ = encode_bytes!("hello".to_string());
234 }
235}