Skip to content

Commit e114cfb

Browse files
committed
Expose U128, add u128 conversions.
1 parent 6e04748 commit e114cfb

File tree

3 files changed

+125
-58
lines changed

3 files changed

+125
-58
lines changed

primitive-types/src/lib.rs

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
//! Primitive types shared by Substrate and Parity Ethereum.
1010
//!
11-
//! Those are uint types `U256` and `U512`, and fixed hash types `H160`,
11+
//! Those are uint types `U128`, `U256` and `U512`, and fixed hash types `H160`,
1212
//! `H256` and `H512`, with optional serde serialization, parity-codec and
1313
//! rlp encoding.
1414
@@ -32,16 +32,75 @@ extern crate impl_codec;
3232
#[macro_use]
3333
extern crate impl_rlp;
3434

35+
construct_uint! {
36+
/// 128-bit unsigned integer.
37+
pub struct U128(2);
38+
}
39+
3540
construct_uint! {
3641
/// 256-bit unsigned integer.
3742
pub struct U256(4);
3843
}
44+
45+
construct_uint! {
46+
/// 512-bits unsigned integer.
47+
pub struct U512(8);
48+
}
49+
50+
construct_fixed_hash! {
51+
/// Fixed-size uninterpreted hash type with 20 bytes (160 bits) size.
52+
pub struct H160(20);
53+
}
54+
construct_fixed_hash! {
55+
/// Fixed-size uninterpreted hash type with 32 bytes (256 bits) size.
56+
pub struct H256(32);
57+
}
58+
construct_fixed_hash! {
59+
/// Fixed-size uninterpreted hash type with 64 bytes (512 bits) size.
60+
pub struct H512(64);
61+
}
62+
3963
#[cfg(feature = "impl-serde")]
40-
impl_uint_serde!(U256, 4);
64+
mod serde {
65+
use super::*;
66+
67+
impl_uint_serde!(U128, 2);
68+
impl_uint_serde!(U256, 4);
69+
impl_uint_serde!(U512, 8);
70+
71+
impl_fixed_hash_serde!(H160, 20);
72+
impl_fixed_hash_serde!(H256, 32);
73+
impl_fixed_hash_serde!(H512, 64);
74+
}
75+
4176
#[cfg(feature = "impl-codec")]
42-
impl_uint_codec!(U256, 4);
77+
mod codec {
78+
use super::*;
79+
80+
impl_uint_codec!(U128, 2);
81+
impl_uint_codec!(U256, 4);
82+
impl_uint_codec!(U512, 8);
83+
84+
impl_fixed_hash_codec!(H160, 20);
85+
impl_fixed_hash_codec!(H256, 32);
86+
impl_fixed_hash_codec!(H512, 64);
87+
}
88+
4389
#[cfg(feature = "impl-rlp")]
44-
impl_uint_rlp!(U256, 4);
90+
mod rlp {
91+
use super::*;
92+
93+
impl_uint_rlp!(U128, 2);
94+
impl_uint_rlp!(U256, 4);
95+
impl_uint_rlp!(U512, 8);
96+
97+
impl_fixed_hash_rlp!(H160, 20);
98+
impl_fixed_hash_rlp!(H256, 32);
99+
impl_fixed_hash_rlp!(H512, 64);
100+
}
101+
102+
103+
impl_fixed_hash_conversions!(H256, H160);
45104

46105
impl U256 {
47106
/// Multiplies two 256-bit integers to produce full 512-bit integer
@@ -105,49 +164,3 @@ impl<'a> From<&'a U512> for U256 {
105164
U256(ret)
106165
}
107166
}
108-
109-
construct_uint! {
110-
/// 512-bits unsigned integer.
111-
pub struct U512(8);
112-
}
113-
#[cfg(feature = "impl-serde")]
114-
impl_uint_serde!(U512, 8);
115-
#[cfg(feature = "impl-codec")]
116-
impl_uint_codec!(U512, 8);
117-
#[cfg(feature = "impl-rlp")]
118-
impl_uint_rlp!(U512, 8);
119-
120-
construct_fixed_hash! {
121-
/// Fixed-size uninterpreted hash type with 20 bytes (160 bits) size.
122-
pub struct H160(20);
123-
}
124-
#[cfg(feature = "impl-serde")]
125-
impl_fixed_hash_serde!(H160, 20);
126-
#[cfg(feature = "impl-codec")]
127-
impl_fixed_hash_codec!(H160, 20);
128-
#[cfg(feature = "impl-rlp")]
129-
impl_fixed_hash_rlp!(H160, 20);
130-
131-
impl_fixed_hash_conversions!(H256, H160);
132-
133-
construct_fixed_hash! {
134-
/// Fixed-size uninterpreted hash type with 32 bytes (256 bits) size.
135-
pub struct H256(32);
136-
}
137-
#[cfg(feature = "impl-serde")]
138-
impl_fixed_hash_serde!(H256, 32);
139-
#[cfg(feature = "impl-codec")]
140-
impl_fixed_hash_codec!(H256, 32);
141-
#[cfg(feature = "impl-rlp")]
142-
impl_fixed_hash_rlp!(H256, 32);
143-
144-
construct_fixed_hash! {
145-
/// Fixed-size uninterpreted hash type with 64 bytes (512 bits) size.
146-
pub struct H512(64);
147-
}
148-
#[cfg(feature = "impl-serde")]
149-
impl_fixed_hash_serde!(H512, 64);
150-
#[cfg(feature = "impl-codec")]
151-
impl_fixed_hash_codec!(H512, 64);
152-
#[cfg(feature = "impl-rlp")]
153-
impl_fixed_hash_rlp!(H512, 64);

uint/src/uint.rs

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ macro_rules! impl_mul_from {
305305
}
306306
}
307307
}
308+
#[macro_export]
309+
#[doc(hidden)]
310+
macro_rules! impl_if {
311+
( $t:tt ) => ( $t )
312+
}
308313

309314
#[macro_export]
310315
#[doc(hidden)]
@@ -346,7 +351,58 @@ pub fn split_u128(a: u128) -> (u64, u64) {
346351

347352
#[macro_export]
348353
macro_rules! construct_uint {
354+
( $(#[$attr:meta])* $visibility:vis struct $name:ident (1); ) => {
355+
construct_uint!{ @construct $($attr)* $visibility struct $name (1); }
356+
};
357+
349358
( $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => {
359+
construct_uint! { @construct $($attr)* $visibility struct $name ($n_words); }
360+
361+
impl $crate::core_::convert::From<u128> for $name {
362+
fn from(value: u128) -> $name {
363+
let mut ret = [0; $n_words];
364+
ret[0] = value as u64;
365+
ret[1] = (value >> 64) as u64;
366+
$name(ret)
367+
}
368+
}
369+
370+
impl $crate::core_::convert::From<i128> for $name {
371+
fn from(value: i128) -> $name {
372+
match value >= 0 {
373+
true => From::from(value as u128),
374+
false => { panic!("Unsigned integer can't be created from negative value"); }
375+
}
376+
}
377+
}
378+
379+
impl $name {
380+
/// Low 2 words (u128)
381+
#[inline]
382+
pub fn low_u128(&self) -> u128 {
383+
let &$name(ref arr) = self;
384+
((arr[1] as u128) << 64) + arr[0] as u128
385+
}
386+
387+
/// Conversion to u128 with overflow checking
388+
///
389+
/// # Panics
390+
///
391+
/// Panics if the number is larger than 2^128.
392+
#[inline]
393+
pub fn as_u128(&self) -> u128 {
394+
let &$name(ref arr) = self;
395+
for i in (2..$n_words) {
396+
if arr[i] != 0 {
397+
panic!("Integer overflow when casting to u128")
398+
}
399+
400+
}
401+
self.low_u128()
402+
}
403+
}
404+
};
405+
( @construct $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => {
350406
/// Little-endian large integer type
351407
#[repr(C)]
352408
$(#[$attr])*
@@ -366,7 +422,6 @@ macro_rules! construct_uint {
366422
}
367423

368424
impl $name {
369-
370425
/// Maximum value.
371426
pub const MAX: $name = $name([u64::max_value(); $n_words]);
372427

@@ -414,7 +469,7 @@ macro_rules! construct_uint {
414469
pub fn as_u32(&self) -> u32 {
415470
let &$name(ref arr) = self;
416471
if (arr[0] & (0xffffffffu64 << 32)) != 0 {
417-
panic!("Integer overflow when casting U256")
472+
panic!("Integer overflow when casting to u64")
418473
}
419474
self.as_u64() as u32
420475
}
@@ -429,7 +484,7 @@ macro_rules! construct_uint {
429484
let &$name(ref arr) = self;
430485
for i in 1..$n_words {
431486
if arr[i] != 0 {
432-
panic!("Integer overflow when casting U256")
487+
panic!("Integer overflow when casting to u64")
433488
}
434489
}
435490
arr[0]
@@ -445,11 +500,11 @@ macro_rules! construct_uint {
445500
let &$name(ref arr) = self;
446501
for i in 1..$n_words {
447502
if arr[i] != 0 {
448-
panic!("Integer overflow when casting U256")
503+
panic!("Integer overflow when casting to usize")
449504
}
450505
}
451506
if arr[0] > usize::max_value() as u64 {
452-
panic!("Integer overflow when casting U256")
507+
panic!("Integer overflow when casting to usize")
453508
}
454509
arr[0] as usize
455510
}
@@ -821,7 +876,6 @@ macro_rules! construct_uint {
821876
}
822877
}
823878

824-
825879
impl_map_from!($name, u8, u64);
826880
impl_map_from!($name, u16, u64);
827881
impl_map_from!($name, u32, u64);
@@ -841,7 +895,7 @@ macro_rules! construct_uint {
841895
impl_map_from!($name, i32, i64);
842896
impl_map_from!($name, isize, i64);
843897

844-
// Converts from big endian representation of U256
898+
// Converts from big endian representation of $name
845899
impl<'a> $crate::core_::convert::From<&'a [u8]> for $name {
846900
fn from(bytes: &[u8]) -> $name {
847901
Self::from_big_endian(bytes)

uint/tests/uint_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ construct_uint! {
2424

2525
#[test]
2626
fn uint256_checked_ops() {
27-
let z = U256::from(0);
27+
let z = U256::from(0u128);
2828
let a = U256::from(10);
2929
let b = !U256::from(1);
3030

0 commit comments

Comments
 (0)