1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#![warn(missing_docs)]
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::size_of_val;
pub struct RefId<'a, T: ?Sized>(
pub &'a T,
);
impl<'a, T: ?Sized> Clone for RefId<'a, T> {
fn clone(&self) -> Self {
RefId(self.0)
}
}
impl<'a, T: ?Sized> Copy for RefId<'a, T> {}
impl<'a, T: ?Sized> PartialEq for RefId<'a, T> {
fn eq(&self, other: &Self) -> bool {
(size_of_val(self.0) == 0 && size_of_val(other.0) == 0)
|| (self.0 as *const T == other.0 as *const T)
}
}
impl<'a, T: ?Sized> Eq for RefId<'a, T> {}
impl<'a, T: ?Sized> Hash for RefId<'a, T> {
fn hash<H: Hasher>(&self, state: &mut H) {
if size_of_val(self.0) != 0 {
(self.0 as *const T).hash(state)
}
}
}
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for RefId<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}@{:?}", self.0, self.0 as *const _)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_two_refs_to_same_value() {
let v = 1;
let r1 = &v;
let r2 = &v;
assert_eq!(RefId(r1), RefId(r2));
}
#[test]
fn test_two_boxes() {
#[derive(Debug)]
struct S {
_value: i32,
}
let v1 = Box::new(S { _value: 1 });
let v2 = Box::new(S { _value: 2 });
let r1: &S = &v1;
let r2: &S = &v2;
assert_eq!(RefId(r1), RefId(r1));
assert_ne!(RefId(r1), RefId(r2));
}
#[test]
fn test_unit_type() {
let v1 = ();
let v2 = ();
let r1: &() = &v1;
let r2: &() = &v2;
assert_eq!(RefId(r1), RefId(r2));
}
#[test]
fn test_empty_slice() {
let v = vec![5, 6, 7];
let r1: &[i32] = &v[0..0];
let r2: &[i32] = &v[1..1];
assert_eq!(RefId(r1), RefId(r2));
}
#[test]
fn test_nonempty_slices() {
let v1 = vec![5, 6, 7];
let v2 = vec![5, 6, 7];
let r1: &[i32] = &v1[0..1];
let r2: &[i32] = &v1[0..1];
let r3: &[i32] = &v1[0..2];
let r4: &[i32] = &v2[0..1];
assert_eq!(RefId(r1), RefId(r1));
assert_eq!(RefId(r1), RefId(r2));
assert_ne!(RefId(r1), RefId(r3));
assert_ne!(RefId(r1), RefId(r4));
}
}