1use std::cmp::Ordering;
8
9pub const EMPTY_KEY: &[u8] = &[];
11
12pub trait KeyComparator: Send + Sync {
17 fn compare(&self, key1: &[u8], key2: &[u8]) -> Ordering;
27}
28
29pub fn compare_unsigned_bytes(key1: &[u8], key2: &[u8]) -> Ordering {
42 key1.cmp(key2)
44}
45
46pub fn compare_keys(
57 key1: &[u8],
58 key2: &[u8],
59 comparator: Option<&dyn KeyComparator>,
60) -> Ordering {
61 match comparator {
62 Some(cmp) => cmp.compare(key1, key2),
63 None => compare_unsigned_bytes(key1, key2),
64 }
65}
66
67pub fn get_key_prefix_length(key1: &[u8], key2: &[u8]) -> usize {
79 let min_len = key1.len().min(key2.len());
80 let mut prefix_len = 0;
81
82 for i in 0..min_len {
83 if key1[i] == key2[i] {
84 prefix_len += 1;
85 } else {
86 break;
87 }
88 }
89
90 prefix_len
91}
92
93pub fn create_key_prefix(key1: &[u8], key2: &[u8]) -> Option<Vec<u8>> {
105 let prefix_len = get_key_prefix_length(key1, key2);
106
107 if prefix_len == 0 { None } else { Some(key1[..prefix_len].to_vec()) }
108}
109
110#[derive(Debug, Clone, Copy)]
112pub struct DefaultComparator;
113
114impl KeyComparator for DefaultComparator {
115 fn compare(&self, key1: &[u8], key2: &[u8]) -> Ordering {
116 compare_unsigned_bytes(key1, key2)
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn test_compare_unsigned_bytes() {
126 let k1 = b"abc";
127 let k2 = b"abd";
128 let k3 = b"abc";
129
130 assert_eq!(compare_unsigned_bytes(k1, k2), Ordering::Less);
131 assert_eq!(compare_unsigned_bytes(k2, k1), Ordering::Greater);
132 assert_eq!(compare_unsigned_bytes(k1, k3), Ordering::Equal);
133 }
134
135 #[test]
136 fn test_compare_different_lengths() {
137 let k1 = b"abc";
138 let k2 = b"abcd";
139
140 assert_eq!(compare_unsigned_bytes(k1, k2), Ordering::Less);
141 assert_eq!(compare_unsigned_bytes(k2, k1), Ordering::Greater);
142 }
143
144 #[test]
145 fn test_compare_empty_keys() {
146 let k1 = EMPTY_KEY;
147 let k2 = b"x";
148
149 assert_eq!(compare_unsigned_bytes(k1, k2), Ordering::Less);
150 assert_eq!(compare_unsigned_bytes(k1, k1), Ordering::Equal);
151 }
152
153 #[test]
154 fn test_compare_with_unsigned_bytes() {
155 let k1 = &[0xFE_u8];
157 let k2 = &[0x01_u8];
158
159 assert_eq!(compare_unsigned_bytes(k1, k2), Ordering::Greater);
161 }
162
163 #[test]
164 fn test_get_key_prefix_length() {
165 let k1 = b"abcdef";
166 let k2 = b"abcxyz";
167
168 assert_eq!(get_key_prefix_length(k1, k2), 3); let k3 = b"xyz";
171 assert_eq!(get_key_prefix_length(k1, k3), 0);
172
173 let k4 = b"abcdef";
174 assert_eq!(get_key_prefix_length(k1, k4), 6); }
176
177 #[test]
178 fn test_get_key_prefix_length_different_lengths() {
179 let k1 = b"abc";
180 let k2 = b"abcdef";
181
182 assert_eq!(get_key_prefix_length(k1, k2), 3);
183 assert_eq!(get_key_prefix_length(k2, k1), 3);
184 }
185
186 #[test]
187 fn test_create_key_prefix() {
188 let k1 = b"abcdef";
189 let k2 = b"abcxyz";
190
191 let prefix = create_key_prefix(k1, k2);
192 assert_eq!(prefix, Some(b"abc".to_vec()));
193
194 let k3 = b"xyz";
195 let no_prefix = create_key_prefix(k1, k3);
196 assert_eq!(no_prefix, None);
197 }
198
199 #[test]
200 fn test_create_key_prefix_empty() {
201 let k1 = EMPTY_KEY;
202 let k2 = b"abc";
203
204 assert_eq!(create_key_prefix(k1, k2), None);
205 assert_eq!(create_key_prefix(k2, k1), None);
206 }
207
208 #[test]
209 fn test_compare_keys_with_default() {
210 let k1 = b"abc";
211 let k2 = b"abd";
212
213 assert_eq!(compare_keys(k1, k2, None), Ordering::Less);
214 }
215
216 #[test]
217 fn test_compare_keys_with_custom_comparator() {
218 struct ReverseComparator;
219
220 impl KeyComparator for ReverseComparator {
221 fn compare(&self, key1: &[u8], key2: &[u8]) -> Ordering {
222 key2.cmp(key1) }
224 }
225
226 let k1 = b"abc";
227 let k2 = b"abd";
228 let cmp = ReverseComparator;
229
230 assert_eq!(compare_keys(k1, k2, Some(&cmp)), Ordering::Greater);
232 }
233
234 #[test]
235 fn test_default_comparator() {
236 let cmp = DefaultComparator;
237 let k1 = b"abc";
238 let k2 = b"abd";
239
240 assert_eq!(cmp.compare(k1, k2), Ordering::Less);
241 assert_eq!(compare_keys(k1, k2, Some(&cmp)), Ordering::Less);
242 }
243}