use pointer_identity::{Pointer, PointerIdentity};
use std::{
cmp::Ordering,
collections::{hash_map::DefaultHasher, BTreeSet, HashSet},
hash::{Hash, Hasher},
path::PathBuf,
rc::Rc,
sync::Arc,
};
use test_strategy::*;
#[derive(Arbitrary, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub struct Struct {
number: i64,
string: String,
vector: Vec<(usize, PathBuf)>,
}
fn hash_sum<T: Hash>(t: &T) -> u64 {
let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}
fn test_identity<T: Pointer>(value: T) {
let value = PointerIdentity::new(value);
assert!(value.eq(&value));
assert_eq!(value.cmp(&value), Ordering::Equal);
assert_eq!(value.partial_cmp(&value), Some(Ordering::Equal));
assert_eq!(hash_sum(&value), hash_sum(&value));
}
#[test]
fn can_compare_identity() {
test_identity(Rc::new(0u64));
test_identity(Arc::new(0u64));
test_identity(Box::new(0u64));
test_identity(vec![0u64]);
test_identity(&[0u64] as &[u64]);
test_identity(&[0u64] as &[u64; 1]);
#[cfg(feature = "bytes")]
test_identity(bytes::Bytes::from(vec![0]));
}
fn test_cloned_identity<T: Pointer + Clone>(value: T) {
let value = PointerIdentity::new(value);
let clone = value.clone();
assert!(value.eq(&value));
assert_eq!(value.cmp(&clone), Ordering::Equal);
assert_eq!(value.partial_cmp(&clone), Some(Ordering::Equal));
assert_eq!(hash_sum(&value), hash_sum(&clone));
}
#[test]
fn can_compare_cloned_identity() {
test_cloned_identity(Rc::new(0u64));
test_cloned_identity(Arc::new(()));
test_cloned_identity(&[] as &[()]);
test_cloned_identity(&[] as &[(); 0]);
#[cfg(feature = "bytes")]
test_cloned_identity(bytes::Bytes::from(vec![0]));
}
fn test_different<T: Pointer>(left: T, right: T) {
let left = PointerIdentity::new(left);
let right = PointerIdentity::new(right);
assert!(!left.eq(&right));
assert!(left.cmp(&right) != Ordering::Equal);
assert!(left.partial_cmp(&right).unwrap() != Ordering::Equal);
assert!(hash_sum(&left) != hash_sum(&right));
}
#[proptest]
fn can_compare_different(left: u64, right: u64) {
test_different(Rc::new(left), Rc::new(right));
test_different(Arc::new(left), Arc::new(right));
test_different(Box::new(left), Box::new(right));
test_different::<&[u64]>(&[left], &[right]);
test_different::<&[u64; 1]>(&[left], &[right]);
}
fn test_store<T: Pointer + Clone>(values: Vec<T>) {
let mut hash_set = HashSet::new();
let mut btree_set = BTreeSet::new();
for value in values.iter() {
hash_set.insert(PointerIdentity::new(value.clone()));
btree_set.insert(PointerIdentity::new(value.clone()));
}
assert_eq!(hash_set.len(), values.len());
assert_eq!(btree_set.len(), values.len());
}
#[proptest]
fn can_store(numbers: Vec<u64>) {
test_store::<Rc<u64>>(numbers.iter().copied().map(Rc::new).collect());
test_store::<Arc<u64>>(numbers.iter().copied().map(Arc::new).collect());
}
fn test_methods<T: Pointer + Clone + Eq + std::fmt::Debug>(value: T) {
let mut pointer = PointerIdentity::new(value.clone());
assert_eq!(&*pointer, &value);
*pointer = value.clone();
assert_eq!(pointer.inner(), &value);
assert_eq!(pointer.into_inner(), value);
}
#[test]
fn can_compare_methods() {
test_methods(Rc::new(0u64));
test_methods(Arc::new(0u64));
test_methods(Box::new(0u64));
test_methods(&[] as &[()]);
test_methods(&[] as &[(); 0]);
#[cfg(feature = "bytes")]
test_methods(bytes::Bytes::from(vec![0]));
}
#[test]
fn can_use_unsized_targets() {
let data = vec![0, 1, 2];
let data: Rc<[u8]> = data.into();
let _pointer = PointerIdentity::new(data);
}