solar_data_structures/
interned.rs1use std::{
4 cmp::Ordering,
5 fmt::{self, Debug},
6 hash::{Hash, Hasher},
7 ops::Deref,
8 ptr,
9};
10
11#[allow(unnameable_types)]
12mod private {
13 #[derive(Clone, Copy, Debug)]
14 pub struct PrivateZst;
15}
16
17#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
29pub struct Interned<'a, T>(pub &'a T, pub private::PrivateZst);
30
31impl<'a, T> Interned<'a, T> {
32 #[inline]
38 pub const fn new_unchecked(t: &'a T) -> Self {
39 Interned(t, private::PrivateZst)
40 }
41}
42
43impl<T> Clone for Interned<'_, T> {
44 fn clone(&self) -> Self {
45 *self
46 }
47}
48
49impl<T> Copy for Interned<'_, T> {}
50
51impl<T> Deref for Interned<'_, T> {
52 type Target = T;
53
54 #[inline]
55 fn deref(&self) -> &T {
56 self.0
57 }
58}
59
60impl<T> PartialEq for Interned<'_, T> {
61 #[inline]
62 fn eq(&self, other: &Self) -> bool {
63 ptr::eq(self.0, other.0)
65 }
66}
67
68impl<T> Eq for Interned<'_, T> {}
69
70impl<T: PartialOrd> PartialOrd for Interned<'_, T> {
71 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
72 if ptr::eq(self.0, other.0) {
75 Some(Ordering::Equal)
76 } else {
77 let res = self.0.partial_cmp(other.0);
78 debug_assert_ne!(res, Some(Ordering::Equal));
79 res
80 }
81 }
82}
83
84impl<T: Ord> Ord for Interned<'_, T> {
85 fn cmp(&self, other: &Self) -> Ordering {
86 if ptr::eq(self.0, other.0) {
89 Ordering::Equal
90 } else {
91 let res = self.0.cmp(other.0);
92 debug_assert_ne!(res, Ordering::Equal);
93 res
94 }
95 }
96}
97
98impl<T> Hash for Interned<'_, T> {
99 #[inline]
100 fn hash<H: Hasher>(&self, s: &mut H) {
101 ptr::hash(self.0, s)
103 }
104}
105
106impl<T: Debug> Debug for Interned<'_, T> {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 self.0.fmt(f)
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[derive(Debug)]
117 struct S(u32);
118
119 impl PartialEq for S {
120 fn eq(&self, _other: &Self) -> bool {
121 panic!("shouldn't be called");
122 }
123 }
124
125 impl Eq for S {}
126
127 #[allow(clippy::non_canonical_partial_ord_impl)]
128 impl PartialOrd for S {
129 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
130 assert_ne!(self.0, other.0);
132 self.0.partial_cmp(&other.0)
133 }
134 }
135
136 impl Ord for S {
137 fn cmp(&self, other: &Self) -> Ordering {
138 assert_ne!(self.0, other.0);
140 self.0.cmp(&other.0)
141 }
142 }
143
144 #[test]
145 fn test_uniq() {
146 let s1 = S(1);
147 let s2 = S(2);
148 let s3 = S(3);
149 let s4 = S(1); let v1 = Interned::new_unchecked(&s1);
152 let v2 = Interned::new_unchecked(&s2);
153 let v3a = Interned::new_unchecked(&s3);
154 let v3b = Interned::new_unchecked(&s3);
155 let v4 = Interned::new_unchecked(&s4); assert_ne!(v1, v2);
158 assert_ne!(v2, v3a);
159 assert_eq!(v1, v1);
160 assert_eq!(v3a, v3b);
161 assert_ne!(v1, v4); assert_eq!(v1.cmp(&v2), Ordering::Less);
164 assert_eq!(v3a.cmp(&v2), Ordering::Greater);
165 assert_eq!(v1.cmp(&v1), Ordering::Equal); assert_eq!(v3a.cmp(&v3b), Ordering::Equal); assert_eq!(v1.partial_cmp(&v2), Some(Ordering::Less));
169 assert_eq!(v3a.partial_cmp(&v2), Some(Ordering::Greater));
170 assert_eq!(v1.partial_cmp(&v1), Some(Ordering::Equal)); assert_eq!(v3a.partial_cmp(&v3b), Some(Ordering::Equal)); }
173}