pub trait KeyExtractor<T, K> {
fn extract_key(&self, item: &T) -> K;
}
pub struct IdentityKey;
impl<T: Clone> KeyExtractor<T, T> for IdentityKey {
fn extract_key(&self, item: &T) -> T {
item.clone()
}
}
impl<T, K, F> KeyExtractor<T, K> for F
where
F: Fn(&T) -> K,
{
fn extract_key(&self, item: &T) -> K {
self(item)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_identity_key() {
let extractor = IdentityKey;
assert_eq!(extractor.extract_key(&42), 42);
assert_eq!(extractor.extract_key(&"hello"), "hello");
}
#[test]
fn test_function_key() {
let extractor = |x: &i32| x.abs();
assert_eq!(extractor.extract_key(&-42), 42);
assert_eq!(extractor.extract_key(&10), 10);
}
#[test]
fn test_complex_key() {
#[derive(Debug, PartialEq)]
struct Person {
name: String,
age: u32,
}
let person = Person {
name: "Alice".to_string(),
age: 30,
};
let by_age = |p: &Person| p.age;
assert_eq!(by_age.extract_key(&person), 30);
let by_name_len = |p: &Person| p.name.len();
assert_eq!(by_name_len.extract_key(&person), 5);
}
}