use std::any::Any;
pub trait DynEq: Any + private::SealedEq {
fn dyn_eq(&self, other: &dyn Any) -> bool;
}
impl<T: PartialEq + 'static> DynEq for T {
fn dyn_eq(&self, other: &dyn Any) -> bool {
other
.downcast_ref::<Self>()
.is_some_and(|other| other.eq(self))
}
}
pub trait DynHash: private::SealedHash {
fn dyn_hash(&self, state: &mut dyn std::hash::Hasher);
}
impl<T: std::hash::Hash + 'static> DynHash for T {
fn dyn_hash(&self, mut state: &mut dyn std::hash::Hasher) {
std::hash::Hash::hash(self, &mut state);
}
}
mod private {
pub trait SealedEq {}
impl<T: PartialEq + ?Sized> SealedEq for T {}
pub trait SealedHash {}
impl<T: std::hash::Hash + ?Sized> SealedHash for T {}
}
#[cfg(test)]
mod tests {
use std::any::Any;
use std::fmt::Debug;
use super::DynEq;
trait MyTrait: DynEq + Debug + Any {}
impl MyTrait for u32 {}
impl MyTrait for u64 {}
impl PartialEq for dyn MyTrait {
fn eq(&self, other: &Self) -> bool {
self.dyn_eq(other)
}
}
#[test]
fn test_dyn_eq() {
let var_w = &2_u32 as &dyn MyTrait;
let var_x = &5_u32 as &dyn MyTrait;
let var_y = &5_u32 as &dyn MyTrait;
let var_z = &5_u64 as &dyn MyTrait;
assert_eq!(var_x, var_y);
assert_ne!(var_w, var_x);
assert_ne!(var_y, var_z);
}
}