#![no_std]
#[cfg(feature = "std")]
extern crate std;
use core::hash::{Hash, Hasher};
pub trait Same {
fn same(&self, other: &Self) -> bool;
}
pub trait RefHash {
fn ref_hash<H: Hasher>(&self, hasher: &mut H);
}
impl<'a, T> Same for &'a T {
fn same(&self, other: &Self) -> bool {
let a: *const T = *self;
let b: *const T = *other;
a == b
}
}
#[cfg(feature = "std")]
impl<T> Same for std::rc::Rc<T> {
fn same(&self, other: &Self) -> bool {
std::rc::Rc::ptr_eq(self, other)
}
}
#[cfg(feature = "std")]
impl<T> Same for std::sync::Arc<T> {
fn same(&self, other: &Self) -> bool {
std::sync::Arc::ptr_eq(self, other)
}
}
impl<'a, T> RefHash for &'a T {
fn ref_hash<H: Hasher>(&self, hasher: &mut H) {
let ptr: *const T = *self;
ptr.hash(hasher);
}
}
#[cfg(feature = "std")]
impl<T> RefHash for std::rc::Rc<T> {
fn ref_hash<H: Hasher>(&self, hasher: &mut H) {
(&**self).ref_hash(hasher);
}
}
#[cfg(feature = "std")]
impl<T> RefHash for std::sync::Arc<T> {
fn ref_hash<H: Hasher>(&self, hasher: &mut H) {
(&**self).ref_hash(hasher);
}
}
pub struct RefCmp<T: Same>(pub T);
impl<T: Same> Eq for RefCmp<T> {}
impl<T: Same> PartialEq for RefCmp<T> {
fn eq(&self, other: &Self) -> bool {
self.0.same(&other.0)
}
}
impl<T: Same + RefHash> Hash for RefCmp<T> {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.0.ref_hash(hasher);
}
}
impl<T: Same> core::ops::Deref for RefCmp<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<U, T: Same + AsRef<U>> AsRef<U> for RefCmp<T> {
fn as_ref(&self) -> &U {
self.0.as_ref()
}
}
impl<T: Same> core::borrow::Borrow<T> for RefCmp<T> {
fn borrow(&self) -> &T {
&self.0
}
}
#[cfg(test)]
mod tests {
use ::Same;
use ::RefCmp;
#[test]
fn refs() {
let a = 42;
let b = 42;
let a_ref = &a;
let a_ref_again = &a;
let b_ref = &b;
assert!(a_ref.same(&a_ref_again));
assert!(!a_ref.same(&b_ref));
let mut hash_set = ::std::collections::HashSet::new();
assert!(hash_set.insert(RefCmp(a_ref)));
assert!(!hash_set.insert(RefCmp(a_ref_again)));
assert!(hash_set.insert(RefCmp(b_ref)));
}
#[test]
fn rcs() {
let a = ::std::rc::Rc::new(42);
let a_cloned = a.clone();
let b = ::std::rc::Rc::new(42);
assert!(a.same(&a_cloned));
assert!(!a.same(&b));
let mut hash_set = ::std::collections::HashSet::new();
assert!(hash_set.insert(RefCmp(a)));
assert!(!hash_set.insert(RefCmp(a_cloned)));
assert!(hash_set.insert(RefCmp(b)));
}
#[test]
fn arcs() {
let a = ::std::sync::Arc::new(42);
let a_cloned = a.clone();
let b = ::std::sync::Arc::new(42);
assert!(a.same(&a_cloned));
assert!(!a.same(&b));
let mut hash_set = ::std::collections::HashSet::new();
assert!(hash_set.insert(RefCmp(a)));
assert!(!hash_set.insert(RefCmp(a_cloned)));
assert!(hash_set.insert(RefCmp(b)));
}
}