Skip to content

Commit 5b133ae

Browse files
authored
Merge pull request #376 from cuviper/slice-eq
`impl PartialEq` between `Slice` and `[]`/arrays
2 parents b56f035 + 3c1aa95 commit 5b133ae

File tree

3 files changed

+113
-8
lines changed

3 files changed

+113
-8
lines changed

src/map/slice.rs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{
22
Bucket, Entries, IndexMap, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values,
33
ValuesMut,
44
};
5-
use crate::util::try_simplify_range;
5+
use crate::util::{slice_eq, try_simplify_range};
66

77
use alloc::boxed::Box;
88
use alloc::vec::Vec;
@@ -335,9 +335,55 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Slice<K, V> {
335335
}
336336
}
337337

338-
impl<K: PartialEq, V: PartialEq> PartialEq for Slice<K, V> {
339-
fn eq(&self, other: &Self) -> bool {
340-
self.len() == other.len() && self.iter().eq(other)
338+
impl<K, V, K2, V2> PartialEq<Slice<K2, V2>> for Slice<K, V>
339+
where
340+
K: PartialEq<K2>,
341+
V: PartialEq<V2>,
342+
{
343+
fn eq(&self, other: &Slice<K2, V2>) -> bool {
344+
slice_eq(&self.entries, &other.entries, |b1, b2| {
345+
b1.key == b2.key && b1.value == b2.value
346+
})
347+
}
348+
}
349+
350+
impl<K, V, K2, V2> PartialEq<[(K2, V2)]> for Slice<K, V>
351+
where
352+
K: PartialEq<K2>,
353+
V: PartialEq<V2>,
354+
{
355+
fn eq(&self, other: &[(K2, V2)]) -> bool {
356+
slice_eq(&self.entries, other, |b, t| b.key == t.0 && b.value == t.1)
357+
}
358+
}
359+
360+
impl<K, V, K2, V2> PartialEq<Slice<K2, V2>> for [(K, V)]
361+
where
362+
K: PartialEq<K2>,
363+
V: PartialEq<V2>,
364+
{
365+
fn eq(&self, other: &Slice<K2, V2>) -> bool {
366+
slice_eq(self, &other.entries, |t, b| t.0 == b.key && t.1 == b.value)
367+
}
368+
}
369+
370+
impl<K, V, K2, V2, const N: usize> PartialEq<[(K2, V2); N]> for Slice<K, V>
371+
where
372+
K: PartialEq<K2>,
373+
V: PartialEq<V2>,
374+
{
375+
fn eq(&self, other: &[(K2, V2); N]) -> bool {
376+
<Self as PartialEq<[_]>>::eq(self, other)
377+
}
378+
}
379+
380+
impl<K, V, const N: usize, K2, V2> PartialEq<Slice<K2, V2>> for [(K, V); N]
381+
where
382+
K: PartialEq<K2>,
383+
V: PartialEq<V2>,
384+
{
385+
fn eq(&self, other: &Slice<K2, V2>) -> bool {
386+
<[_] as PartialEq<_>>::eq(self, other)
341387
}
342388
}
343389

src/set/slice.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{Bucket, Entries, IndexSet, IntoIter, Iter};
2-
use crate::util::try_simplify_range;
2+
use crate::util::{slice_eq, try_simplify_range};
33

44
use alloc::boxed::Box;
55
use alloc::vec::Vec;
@@ -222,9 +222,48 @@ impl<T: fmt::Debug> fmt::Debug for Slice<T> {
222222
}
223223
}
224224

225-
impl<T: PartialEq> PartialEq for Slice<T> {
226-
fn eq(&self, other: &Self) -> bool {
227-
self.len() == other.len() && self.iter().eq(other)
225+
impl<T, U> PartialEq<Slice<U>> for Slice<T>
226+
where
227+
T: PartialEq<U>,
228+
{
229+
fn eq(&self, other: &Slice<U>) -> bool {
230+
slice_eq(&self.entries, &other.entries, |b1, b2| b1.key == b2.key)
231+
}
232+
}
233+
234+
impl<T, U> PartialEq<[U]> for Slice<T>
235+
where
236+
T: PartialEq<U>,
237+
{
238+
fn eq(&self, other: &[U]) -> bool {
239+
slice_eq(&self.entries, other, |b, o| b.key == *o)
240+
}
241+
}
242+
243+
impl<T, U> PartialEq<Slice<U>> for [T]
244+
where
245+
T: PartialEq<U>,
246+
{
247+
fn eq(&self, other: &Slice<U>) -> bool {
248+
slice_eq(self, &other.entries, |o, b| *o == b.key)
249+
}
250+
}
251+
252+
impl<T, U, const N: usize> PartialEq<[U; N]> for Slice<T>
253+
where
254+
T: PartialEq<U>,
255+
{
256+
fn eq(&self, other: &[U; N]) -> bool {
257+
<Self as PartialEq<[U]>>::eq(self, other)
258+
}
259+
}
260+
261+
impl<T, const N: usize, U> PartialEq<Slice<U>> for [T; N]
262+
where
263+
T: PartialEq<U>,
264+
{
265+
fn eq(&self, other: &Slice<U>) -> bool {
266+
<[T] as PartialEq<Slice<U>>>::eq(self, other)
228267
}
229268
}
230269

src/util.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,23 @@ where
5656
}
5757
Some(start..end)
5858
}
59+
60+
// Generic slice equality -- copied from the standard library but adding a custom comparator,
61+
// allowing for our `Bucket` wrapper on either or both sides.
62+
pub(crate) fn slice_eq<T, U>(left: &[T], right: &[U], eq: impl Fn(&T, &U) -> bool) -> bool {
63+
if left.len() != right.len() {
64+
return false;
65+
}
66+
67+
// Implemented as explicit indexing rather
68+
// than zipped iterators for performance reasons.
69+
// See PR https://github.com/rust-lang/rust/pull/116846
70+
for i in 0..left.len() {
71+
// bound checks are optimized away
72+
if !eq(&left[i], &right[i]) {
73+
return false;
74+
}
75+
}
76+
77+
true
78+
}

0 commit comments

Comments
 (0)