blob: c34cf2eb3a208ffe2719beafa08b5bd6a69292cc [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::{
hash::{Hash, Hasher},
ptr,
sync::Arc,
};
/// ByAddr allows two Arcs to be compared by address instead of using its contained
/// type's comparator.
#[derive(Debug)]
pub struct ByAddr<T: ?Sized>(pub Arc<T>);
impl<T: ?Sized> ByAddr<T> {
/// Constructs a new ByAddr<T>.
pub fn new(value: Arc<T>) -> Self {
Self(value)
}
}
impl<T: ?Sized> Clone for ByAddr<T> {
fn clone(&self) -> Self {
ByAddr::new(self.0.clone())
}
}
impl<T: ?Sized> PartialEq<ByAddr<T>> for ByAddr<T> {
fn eq(&self, other: &ByAddr<T>) -> bool {
self.0.as_ref() as *const T == other.0.as_ref() as *const T
}
}
impl<T: ?Sized> Hash for ByAddr<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
ptr::hash(self.0.as_ref(), state);
}
}
impl<T: ?Sized> Eq for ByAddr<T> {}
#[cfg(test)]
mod tests {
use {
super::*,
std::{collections::HashSet, sync::Arc},
};
#[test]
fn by_addr_eq() {
// Both arcs should contain same content so that we are sure that equality is based on
// address and not string content.
let common_str = "common_str".to_string();
let str1 = Arc::new(common_str.clone());
let str2 = Arc::new(common_str.clone());
let by_addr = ByAddr::new(str1.clone());
assert_eq!(by_addr, ByAddr::new(str1));
assert_ne!(by_addr, ByAddr::new(str2));
}
#[test]
fn by_addr_hash() {
// Both arcs should contain same content so that we are sure that hashing is based on
// address and not string content.
let common_str = "common_str".to_string();
let str1 = Arc::new(common_str.clone());
let str2 = Arc::new(common_str.clone());
let by_addr = ByAddr::new(str1.clone());
let mut set: HashSet<ByAddr<String>> = HashSet::new();
set.insert(by_addr);
assert!(set.contains(&ByAddr::new(str1)));
assert!(!set.contains(&ByAddr::new(str2)));
}
#[test]
fn by_addr_clone() {
let my_str = Arc::new("my str".to_owned());
let by_addr = ByAddr::new(my_str.clone());
let cloned = by_addr.clone();
assert_eq!(by_addr, cloned);
let mut set: HashSet<ByAddr<String>> = HashSet::new();
set.insert(by_addr);
assert!(set.contains(&cloned));
}
}