use std::cmp::Ordering;
pub const EMPTY_KEY: &[u8] = &[];
pub trait KeyComparator: Send + Sync {
fn compare(&self, key1: &[u8], key2: &[u8]) -> Ordering;
}
pub fn compare_unsigned_bytes(key1: &[u8], key2: &[u8]) -> Ordering {
key1.cmp(key2)
}
pub fn compare_keys(
key1: &[u8],
key2: &[u8],
comparator: Option<&dyn KeyComparator>,
) -> Ordering {
match comparator {
Some(cmp) => cmp.compare(key1, key2),
None => compare_unsigned_bytes(key1, key2),
}
}
pub fn get_key_prefix_length(key1: &[u8], key2: &[u8]) -> usize {
let min_len = key1.len().min(key2.len());
let mut prefix_len = 0;
for i in 0..min_len {
if key1[i] == key2[i] {
prefix_len += 1;
} else {
break;
}
}
prefix_len
}
pub fn create_key_prefix(key1: &[u8], key2: &[u8]) -> Option<Vec<u8>> {
let prefix_len = get_key_prefix_length(key1, key2);
if prefix_len == 0 { None } else { Some(key1[..prefix_len].to_vec()) }
}
#[derive(Debug, Clone, Copy)]
pub struct DefaultComparator;
impl KeyComparator for DefaultComparator {
fn compare(&self, key1: &[u8], key2: &[u8]) -> Ordering {
compare_unsigned_bytes(key1, key2)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_compare_unsigned_bytes() {
let k1 = b"abc";
let k2 = b"abd";
let k3 = b"abc";
assert_eq!(compare_unsigned_bytes(k1, k2), Ordering::Less);
assert_eq!(compare_unsigned_bytes(k2, k1), Ordering::Greater);
assert_eq!(compare_unsigned_bytes(k1, k3), Ordering::Equal);
}
#[test]
fn test_compare_different_lengths() {
let k1 = b"abc";
let k2 = b"abcd";
assert_eq!(compare_unsigned_bytes(k1, k2), Ordering::Less);
assert_eq!(compare_unsigned_bytes(k2, k1), Ordering::Greater);
}
#[test]
fn test_compare_empty_keys() {
let k1 = EMPTY_KEY;
let k2 = b"x";
assert_eq!(compare_unsigned_bytes(k1, k2), Ordering::Less);
assert_eq!(compare_unsigned_bytes(k1, k1), Ordering::Equal);
}
#[test]
fn test_compare_with_unsigned_bytes() {
let k1 = &[0xFE_u8];
let k2 = &[0x01_u8];
assert_eq!(compare_unsigned_bytes(k1, k2), Ordering::Greater);
}
#[test]
fn test_get_key_prefix_length() {
let k1 = b"abcdef";
let k2 = b"abcxyz";
assert_eq!(get_key_prefix_length(k1, k2), 3);
let k3 = b"xyz";
assert_eq!(get_key_prefix_length(k1, k3), 0);
let k4 = b"abcdef";
assert_eq!(get_key_prefix_length(k1, k4), 6); }
#[test]
fn test_get_key_prefix_length_different_lengths() {
let k1 = b"abc";
let k2 = b"abcdef";
assert_eq!(get_key_prefix_length(k1, k2), 3);
assert_eq!(get_key_prefix_length(k2, k1), 3);
}
#[test]
fn test_create_key_prefix() {
let k1 = b"abcdef";
let k2 = b"abcxyz";
let prefix = create_key_prefix(k1, k2);
assert_eq!(prefix, Some(b"abc".to_vec()));
let k3 = b"xyz";
let no_prefix = create_key_prefix(k1, k3);
assert_eq!(no_prefix, None);
}
#[test]
fn test_create_key_prefix_empty() {
let k1 = EMPTY_KEY;
let k2 = b"abc";
assert_eq!(create_key_prefix(k1, k2), None);
assert_eq!(create_key_prefix(k2, k1), None);
}
#[test]
fn test_compare_keys_with_default() {
let k1 = b"abc";
let k2 = b"abd";
assert_eq!(compare_keys(k1, k2, None), Ordering::Less);
}
#[test]
fn test_compare_keys_with_custom_comparator() {
struct ReverseComparator;
impl KeyComparator for ReverseComparator {
fn compare(&self, key1: &[u8], key2: &[u8]) -> Ordering {
key2.cmp(key1) }
}
let k1 = b"abc";
let k2 = b"abd";
let cmp = ReverseComparator;
assert_eq!(compare_keys(k1, k2, Some(&cmp)), Ordering::Greater);
}
#[test]
fn test_default_comparator() {
let cmp = DefaultComparator;
let k1 = b"abc";
let k2 = b"abd";
assert_eq!(cmp.compare(k1, k2), Ordering::Less);
assert_eq!(compare_keys(k1, k2, Some(&cmp)), Ordering::Less);
}
}