1#![forbid(missing_docs)]
28#![deny(clippy::all)]
29
30use std::any::TypeId;
31use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
32use std::hash::{BuildHasher, Hash};
33use std::path::{Path, PathBuf};
34use std::rc::Rc;
35use std::sync::Arc;
36
37pub trait IsSame<Rhs = Self>
39where
40 Rhs: ?Sized,
41{
42 fn is_same(&self, other: &Rhs) -> bool;
44
45 fn is_not_same(&self, other: &Rhs) -> bool {
47 !self.is_same(other)
48 }
49}
50
51impl<T> IsSame for Rc<T>
52where
53 T: ?Sized,
54{
55 fn is_same(&self, other: &Self) -> bool {
56 Rc::ptr_eq(self, other)
57 }
58}
59
60impl<T> IsSame for Arc<T>
61where
62 T: ?Sized,
63{
64 fn is_same(&self, other: &Self) -> bool {
65 Arc::ptr_eq(self, other)
66 }
67}
68
69impl<T, Rhs> IsSame<Rhs> for Vec<T>
70where
71 T: IsSame,
72 Rhs: AsRef<[T]> + ?Sized,
73{
74 fn is_same(&self, other: &Rhs) -> bool {
75 let other = other.as_ref();
76 if self.as_ptr() == other.as_ptr() {
77 true
78 } else if self.len() != other.len() {
79 false
80 } else {
81 self.iter()
82 .zip(other.iter())
83 .all(|(left, right)| left.is_same(right))
84 }
85 }
86}
87
88impl<Key, Value> IsSame for BTreeMap<Key, Value>
89where
90 Key: IsSame + Ord,
91 Value: IsSame,
92{
93 fn is_same(&self, other: &Self) -> bool {
94 let mut left = self.iter();
95 let mut right = other.iter();
96
97 loop {
98 let a = left.next();
99 let b = right.next();
100 match (a, b) {
101 (None, None) => return true,
102 (Some((left_key, left_val)), Some((right_key, right_val)))
103 if left_key == right_key =>
104 {
105 if left_val.is_not_same(right_val) {
106 return false;
107 }
108 }
109 (_, _) => return false,
110 }
111 }
112 }
113}
114
115impl<Key> IsSame for BTreeSet<Key>
116where
117 Key: IsSame + Ord,
118{
119 fn is_same(&self, other: &Self) -> bool {
120 let mut left = self.iter();
121 let mut right = other.iter();
122
123 loop {
124 let a = left.next();
125 let b = right.next();
126 match (a, b) {
127 (None, None) => return true,
128 (Some(left_key), Some(right_key)) if left_key == right_key => (),
129 (_, _) => return false,
130 }
131 }
132 }
133}
134
135impl<Key, Value, State> IsSame for HashMap<Key, Value, State>
136where
137 Key: IsSame + Eq + Hash,
138 Value: IsSame,
139 State: BuildHasher,
140{
141 fn is_same(&self, other: &Self) -> bool {
142 if self.len() != other.len() {
147 return false;
148 }
149 for (left_key, left_val) in self {
150 if let Some(right_val) = other.get(left_key) {
151 if left_val.is_not_same(&right_val) {
152 return false;
153 }
154 } else {
155 return false;
156 }
157 }
158
159 true
160 }
161}
162
163impl<Key, State> IsSame for HashSet<Key, State>
164where
165 Key: IsSame + Eq + Hash,
166 State: BuildHasher,
167{
168 fn is_same(&self, other: &Self) -> bool {
169 self == other
170 }
171}
172
173impl IsSame for f32 {
174 fn is_same(&self, other: &Self) -> bool {
175 self.to_bits() == other.to_bits()
176 }
177}
178
179impl IsSame for f64 {
180 fn is_same(&self, other: &Self) -> bool {
181 self.to_bits() == other.to_bits()
182 }
183}
184
185impl<'a, T> IsSame for &'a T
186where
187 T: IsSame + ?Sized + 'a,
188{
189 fn is_same(&self, other: &Self) -> bool {
190 if (*self as *const T) == (*other as *const T) {
191 true
192 } else {
193 (*self).is_same(other)
194 }
195 }
196}
197
198impl<'a, T> IsSame for [T]
199where
200 T: IsSame + 'a,
201{
202 fn is_same(&self, other: &Self) -> bool {
203 if self.len() != other.len() {
204 false
205 } else {
206 for i in 0..self.len() {
207 if self[i].is_not_same(&other[i]) {
208 return false;
209 }
210 }
211 true
212 }
213 }
214}
215
216impl<Rhs> IsSame<Rhs> for PathBuf
217where
218 Rhs: AsRef<Path> + ?Sized,
219{
220 fn is_same(&self, other: &Rhs) -> bool {
221 self == other.as_ref()
222 }
223}
224
225impl<Rhs> IsSame<Rhs> for Path
226where
227 Rhs: AsRef<Path> + ?Sized,
228{
229 fn is_same(&self, other: &Rhs) -> bool {
230 self == other.as_ref()
231 }
232}
233
234macro_rules! simple_impl {
235 ($name:ty) => {
236 impl IsSame for $name {
237 fn is_same(&self, other: &Self) -> bool {
238 self == other
239 }
240 }
241 };
242}
243
244simple_impl!(u8);
245simple_impl!(u16);
246simple_impl!(u32);
247simple_impl!(u64);
248simple_impl!(u128);
249simple_impl!(usize);
250simple_impl!(i8);
251simple_impl!(i16);
252simple_impl!(i32);
253simple_impl!(i64);
254simple_impl!(i128);
255simple_impl!(isize);
256simple_impl!(bool);
257simple_impl!(char);
258simple_impl!(());
259simple_impl!(String);
260simple_impl!(str);
261simple_impl!(TypeId);
262
263macro_rules! tuple_impl {
264 ($($tyname:ident, $left:ident, $right:ident;)+) => {
265 impl<$($tyname),+> IsSame for ($($tyname,)+)
266 where
267 $($tyname : IsSame),+
268 {
269 fn is_same(&self, other: &Self) -> bool {
270 let ($(ref $left,)+) = self;
271 let ($(ref $right,)+) = other;
272 $( $left.is_same($right) )&&+
273 }
274 }
275 };
276}
277
278tuple_impl! {
279 T1, left, right;
280}
281
282tuple_impl! {
283 T1, left1, right1;
284 T2, left2, right2;
285}
286
287tuple_impl! {
288 T1, left1, right1;
289 T2, left2, right2;
290 T3, left3, right3;
291}
292
293tuple_impl! {
294 T1, left1, right1;
295 T2, left2, right2;
296 T3, left3, right3;
297 T4, left4, right4;
298}
299
300tuple_impl! {
301 T1, left1, right1;
302 T2, left2, right2;
303 T3, left3, right3;
304 T4, left4, right4;
305 T5, left5, right5;
306}
307
308tuple_impl! {
309 T1, left1, right1;
310 T2, left2, right2;
311 T3, left3, right3;
312 T4, left4, right4;
313 T5, left5, right5;
314 T6, left6, right6;
315}
316
317tuple_impl! {
318 T1, left1, right1;
319 T2, left2, right2;
320 T3, left3, right3;
321 T4, left4, right4;
322 T5, left5, right5;
323 T6, left6, right6;
324 T7, left7, right7;
325}
326
327tuple_impl! {
328 T1, left1, right1;
329 T2, left2, right2;
330 T3, left3, right3;
331 T4, left4, right4;
332 T5, left5, right5;
333 T6, left6, right6;
334 T7, left7, right7;
335 T8, left8, right8;
336}
337
338macro_rules! array_impl {
339 ($( $count:tt )+) => {$(
340 impl<T> IsSame for [T; $count]
341 where
342 T: IsSame,
343 {
344 fn is_same(&self, other: &Self) -> bool {
345 for i in 0..$count {
346 if self[i].is_not_same(&other[i]) {
347 return false;
348 }
349 }
350 true
351 }
352 }
353 )+};
354}
355
356array_impl!(
357 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
358 20 21 22 23 24 25 26 27 28 29 30 31 32
359);