Greetings!
I'm trying to write some multiple key caching, where data
have a method to generate a sequence of keys on which hash will be generated and stored.
Keys are based on inner value members and because we need only hash from them, I'm trying to do not use Clone
. But again I faced with complex compiler error:
error: implementation of `GenKeys` is not general enough
--> src/main.rs:80:11
|
80 | cache.insert(obj);
| ^^^^^^ implementation of `GenKeys` is not general enough
|
= note: `Foo` must implement `GenKeys<'0, Keys<'_>, 2_usize>`, for any lifetime `'0`...
= note: ...but it actually implements `GenKeys<'1, Keys<'1>, 2_usize>`, for some specific lifetime `'1`
Here some reproducible code:
use std::{
collections::hash_map::{DefaultHasher, HashMap},
hash::{Hash, Hasher},
marker::PhantomData,
};
type Id = u16;
trait GenKeys<'a, K: 'a, const NUMBER_OF_KEYS: usize> {
fn id(&self) -> Id;
fn gen_keys(&'a self) -> [K; NUMBER_OF_KEYS];
}
#[derive(Debug)]
struct Cache<K, V, const NUMBER_OF_KEYS: usize> {
keys_to_hash: HashMap<u64, Id>,
cache: HashMap<Id, V>,
phantom: PhantomData<K>,
}
impl<K, V, const NUMBER_OF_KEYS: usize> Default for Cache<K, V, NUMBER_OF_KEYS> {
fn default() -> Self {
Self {
keys_to_hash: Default::default(),
cache: Default::default(),
phantom: Default::default(),
}
}
}
impl<K, V, const NUMBER_OF_KEYS: usize> Cache<K, V, NUMBER_OF_KEYS>
where
K: Hash,
for<'a> V: GenKeys<'a, K, NUMBER_OF_KEYS>,
{
pub fn insert(&mut self, value: V) {
let id = value.id();
let keys = value.gen_keys().map(|k| (calc_hash(&k), id));
self.keys_to_hash.extend(keys);
self.cache.insert(id, value);
}
}
fn calc_hash<T: Hash>(value: &T) -> u64 {
let mut s = DefaultHasher::new();
value.hash(&mut s);
s.finish()
}
#[derive(Debug, Hash)]
enum Keys<'a> {
ID(Id),
Data(&'a str),
}
#[derive(Debug)]
struct Foo {
id: Id,
data: String,
}
impl<'a> GenKeys<'a, Keys<'a>, 2> for Foo {
fn id(&self) -> Id {
self.id
}
fn gen_keys(&'a self) -> [Keys<'a>; 2] {
[Keys::ID(self.id), Keys::Data(&self.data)]
}
}
fn main() {
let mut cache = Cache::default();
let obj = Foo {
id: 1,
data: "FOO".to_owned(),
};
cache.insert(obj);
println!("{:?}", cache);
}