use dyn_shim::dyn_shim;
use std::hash::{BuildHasher, BuildHasherDefault, DefaultHasher, Hash};
#[dyn_shim(DynEvent: Hash)]
trait Event {
fn describe(&self) -> String;
}
#[derive(Hash)]
struct KeyPress(char);
impl Event for KeyPress {
fn describe(&self) -> String {
format!("key {:?}", self.0)
}
}
#[derive(Hash)]
struct Click {
x: u32,
y: u32,
}
impl Event for Click {
fn describe(&self) -> String {
format!("click at {},{}", self.x, self.y)
}
}
#[derive(Hash)]
struct Logged {
tick: u64,
event: Box<dyn DynEvent>,
}
fn fingerprint<T: Hash + ?Sized>(value: &T) -> u64 {
BuildHasherDefault::<DefaultHasher>::default().hash_one(value)
}
fn main() {
let log: Vec<Logged> = vec![
Logged {
tick: 1,
event: Box::new(KeyPress('q')),
},
Logged {
tick: 2,
event: Box::new(Click { x: 10, y: 20 }),
},
];
for entry in &log {
println!(
"{:016x} tick {}: {}",
fingerprint(entry),
entry.tick,
entry.event.describe()
);
}
assert_eq!(fingerprint(&*log[0].event), fingerprint(&KeyPress('q')));
}