Skip to content

Commit 8e12159

Browse files
author
Andronik Ordian
authored
uint: manually implement Eq and Hash (#390)
* uint: manually implement some traits * uint: remove unused attr and add Eq tests * uint: fix formatting * uint: add a comment why a manual impl is used * uint: simply Eq impl * uint: simplify Hash and add a regression test * uint: fmt and changelog update
1 parent a4a9745 commit 8e12159

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

uint/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ The format is based on [Keep a Changelog].
55
[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/
66

77
## [Unreleased]
8+
- Added a manual impl of `Eq` and `Hash`. [#390](https://github.com/paritytech/parity-common/pull/390)
89

910
## [0.8.3] - 2020-04-27
1011
- Added `arbitrary` feature. [#378](https://github.com/paritytech/parity-common/pull/378)

uint/src/uint.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ macro_rules! construct_uint {
445445
/// Little-endian large integer type
446446
#[repr(C)]
447447
$(#[$attr])*
448-
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
448+
#[derive(Copy, Clone)]
449449
$visibility struct $name (pub [u64; $n_words]);
450450

451451
/// Get a reference to the underlying little-endian words.
@@ -1462,6 +1462,23 @@ macro_rules! construct_uint {
14621462
}
14631463
}
14641464

1465+
// We implement `Eq` and `Hash` manually to workaround
1466+
// https://github.com/rust-lang/rust/issues/61415
1467+
impl $crate::core_::cmp::PartialEq for $name {
1468+
fn eq(&self, other: &$name) -> bool {
1469+
self.as_ref() == other.as_ref()
1470+
}
1471+
}
1472+
1473+
impl $crate::core_::cmp::Eq for $name {}
1474+
1475+
impl $crate::core_::hash::Hash for $name {
1476+
fn hash<H: $crate::core_::hash::Hasher>(&self, state: &mut H) {
1477+
// use the impl as slice &[u64]
1478+
self.as_ref().hash(state);
1479+
}
1480+
}
1481+
14651482
impl $crate::core_::cmp::Ord for $name {
14661483
fn cmp(&self, other: &$name) -> $crate::core_::cmp::Ordering {
14671484
self.as_ref().iter().rev().cmp(other.as_ref().iter().rev())

uint/tests/uint_tests.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,26 @@ construct_uint! {
2020
pub struct U512(8);
2121
}
2222

23+
#[cfg(feature = "std")]
24+
#[test]
25+
fn hash_impl_is_the_same_as_for_a_slice() {
26+
use core::hash::{Hash, Hasher as _};
27+
use std::collections::hash_map::DefaultHasher;
28+
29+
let uint_hash = {
30+
let mut h = DefaultHasher::new();
31+
let uint = U256::from(123u64);
32+
Hash::hash(&uint, &mut h);
33+
h.finish()
34+
};
35+
let slice_hash = {
36+
let mut h = DefaultHasher::new();
37+
Hash::hash(&[123u64, 0, 0, 0], &mut h);
38+
h.finish()
39+
};
40+
assert_eq!(uint_hash, slice_hash);
41+
}
42+
2343
#[test]
2444
fn u128_conversions() {
2545
let mut a = U256::from(u128::max_value());
@@ -281,7 +301,6 @@ fn uint256_bits_test() {
281301
}
282302

283303
#[test]
284-
#[cfg_attr(feature = "dev", allow(eq_op))]
285304
fn uint256_comp_test() {
286305
let small = U256([10u64, 0, 0, 0]);
287306
let big = U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]);
@@ -296,6 +315,10 @@ fn uint256_comp_test() {
296315
assert!(bigger >= big);
297316
assert!(bigger >= small);
298317
assert!(small <= small);
318+
assert_eq!(small, small);
319+
assert_eq!(biggest, biggest);
320+
assert_ne!(big, biggest);
321+
assert_ne!(big, bigger);
299322
}
300323

301324
#[test]
@@ -1010,10 +1033,10 @@ fn into_fixed_array() {
10101033
fn test_u256_from_fixed_array() {
10111034
let ary = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 123];
10121035
let num: U256 = ary.into();
1013-
assert_eq!(num, U256::from(std::u64::MAX) + 1 + 123);
1036+
assert_eq!(num, U256::from(core::u64::MAX) + 1 + 123);
10141037

10151038
let a_ref: &U256 = &ary.into();
1016-
assert_eq!(a_ref, &(U256::from(std::u64::MAX) + 1 + 123));
1039+
assert_eq!(a_ref, &(U256::from(core::u64::MAX) + 1 + 123));
10171040
}
10181041

10191042
#[test]

0 commit comments

Comments
 (0)