Merge pull request #92 from paritytech/td-u128
Expose U128, add u128 conversions.
This commit is contained in:
commit
5b56003075
|
@ -8,7 +8,7 @@
|
|||
|
||||
//! Primitive types shared by Substrate and Parity Ethereum.
|
||||
//!
|
||||
//! Those are uint types `U256` and `U512`, and fixed hash types `H160`,
|
||||
//! Those are uint types `U128`, `U256` and `U512`, and fixed hash types `H160`,
|
||||
//! `H256` and `H512`, with optional serde serialization, parity-codec and
|
||||
//! rlp encoding.
|
||||
|
||||
|
@ -32,16 +32,73 @@ extern crate impl_codec;
|
|||
#[macro_use]
|
||||
extern crate impl_rlp;
|
||||
|
||||
construct_uint! {
|
||||
/// 128-bit unsigned integer.
|
||||
pub struct U128(2);
|
||||
}
|
||||
construct_uint! {
|
||||
/// 256-bit unsigned integer.
|
||||
pub struct U256(4);
|
||||
}
|
||||
construct_uint! {
|
||||
/// 512-bits unsigned integer.
|
||||
pub struct U512(8);
|
||||
}
|
||||
|
||||
construct_fixed_hash! {
|
||||
/// Fixed-size uninterpreted hash type with 20 bytes (160 bits) size.
|
||||
pub struct H160(20);
|
||||
}
|
||||
construct_fixed_hash! {
|
||||
/// Fixed-size uninterpreted hash type with 32 bytes (256 bits) size.
|
||||
pub struct H256(32);
|
||||
}
|
||||
construct_fixed_hash! {
|
||||
/// Fixed-size uninterpreted hash type with 64 bytes (512 bits) size.
|
||||
pub struct H512(64);
|
||||
}
|
||||
|
||||
#[cfg(feature = "impl-serde")]
|
||||
impl_uint_serde!(U256, 4);
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
impl_uint_serde!(U128, 2);
|
||||
impl_uint_serde!(U256, 4);
|
||||
impl_uint_serde!(U512, 8);
|
||||
|
||||
impl_fixed_hash_serde!(H160, 20);
|
||||
impl_fixed_hash_serde!(H256, 32);
|
||||
impl_fixed_hash_serde!(H512, 64);
|
||||
}
|
||||
|
||||
#[cfg(feature = "impl-codec")]
|
||||
impl_uint_codec!(U256, 4);
|
||||
mod codec {
|
||||
use super::*;
|
||||
|
||||
impl_uint_codec!(U128, 2);
|
||||
impl_uint_codec!(U256, 4);
|
||||
impl_uint_codec!(U512, 8);
|
||||
|
||||
impl_fixed_hash_codec!(H160, 20);
|
||||
impl_fixed_hash_codec!(H256, 32);
|
||||
impl_fixed_hash_codec!(H512, 64);
|
||||
}
|
||||
|
||||
#[cfg(feature = "impl-rlp")]
|
||||
impl_uint_rlp!(U256, 4);
|
||||
mod rlp {
|
||||
use super::*;
|
||||
|
||||
impl_uint_rlp!(U128, 2);
|
||||
impl_uint_rlp!(U256, 4);
|
||||
impl_uint_rlp!(U512, 8);
|
||||
|
||||
impl_fixed_hash_rlp!(H160, 20);
|
||||
impl_fixed_hash_rlp!(H256, 32);
|
||||
impl_fixed_hash_rlp!(H512, 64);
|
||||
}
|
||||
|
||||
|
||||
impl_fixed_hash_conversions!(H256, H160);
|
||||
|
||||
impl U256 {
|
||||
/// Multiplies two 256-bit integers to produce full 512-bit integer
|
||||
|
@ -105,49 +162,3 @@ impl<'a> From<&'a U512> for U256 {
|
|||
U256(ret)
|
||||
}
|
||||
}
|
||||
|
||||
construct_uint! {
|
||||
/// 512-bits unsigned integer.
|
||||
pub struct U512(8);
|
||||
}
|
||||
#[cfg(feature = "impl-serde")]
|
||||
impl_uint_serde!(U512, 8);
|
||||
#[cfg(feature = "impl-codec")]
|
||||
impl_uint_codec!(U512, 8);
|
||||
#[cfg(feature = "impl-rlp")]
|
||||
impl_uint_rlp!(U512, 8);
|
||||
|
||||
construct_fixed_hash! {
|
||||
/// Fixed-size uninterpreted hash type with 20 bytes (160 bits) size.
|
||||
pub struct H160(20);
|
||||
}
|
||||
#[cfg(feature = "impl-serde")]
|
||||
impl_fixed_hash_serde!(H160, 20);
|
||||
#[cfg(feature = "impl-codec")]
|
||||
impl_fixed_hash_codec!(H160, 20);
|
||||
#[cfg(feature = "impl-rlp")]
|
||||
impl_fixed_hash_rlp!(H160, 20);
|
||||
|
||||
impl_fixed_hash_conversions!(H256, H160);
|
||||
|
||||
construct_fixed_hash! {
|
||||
/// Fixed-size uninterpreted hash type with 32 bytes (256 bits) size.
|
||||
pub struct H256(32);
|
||||
}
|
||||
#[cfg(feature = "impl-serde")]
|
||||
impl_fixed_hash_serde!(H256, 32);
|
||||
#[cfg(feature = "impl-codec")]
|
||||
impl_fixed_hash_codec!(H256, 32);
|
||||
#[cfg(feature = "impl-rlp")]
|
||||
impl_fixed_hash_rlp!(H256, 32);
|
||||
|
||||
construct_fixed_hash! {
|
||||
/// Fixed-size uninterpreted hash type with 64 bytes (512 bits) size.
|
||||
pub struct H512(64);
|
||||
}
|
||||
#[cfg(feature = "impl-serde")]
|
||||
impl_fixed_hash_serde!(H512, 64);
|
||||
#[cfg(feature = "impl-codec")]
|
||||
impl_fixed_hash_codec!(H512, 64);
|
||||
#[cfg(feature = "impl-rlp")]
|
||||
impl_fixed_hash_rlp!(H512, 64);
|
||||
|
|
|
@ -346,7 +346,58 @@ pub fn split_u128(a: u128) -> (u64, u64) {
|
|||
|
||||
#[macro_export]
|
||||
macro_rules! construct_uint {
|
||||
( $(#[$attr:meta])* $visibility:vis struct $name:ident (1); ) => {
|
||||
construct_uint!{ @construct $(#[$attr])* $visibility struct $name (1); }
|
||||
};
|
||||
|
||||
( $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => {
|
||||
construct_uint! { @construct $(#[$attr])* $visibility struct $name ($n_words); }
|
||||
|
||||
impl $crate::core_::convert::From<u128> for $name {
|
||||
fn from(value: u128) -> $name {
|
||||
let mut ret = [0; $n_words];
|
||||
ret[0] = value as u64;
|
||||
ret[1] = (value >> 64) as u64;
|
||||
$name(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::core_::convert::From<i128> for $name {
|
||||
fn from(value: i128) -> $name {
|
||||
match value >= 0 {
|
||||
true => From::from(value as u128),
|
||||
false => { panic!("Unsigned integer can't be created from negative value"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $name {
|
||||
/// Low 2 words (u128)
|
||||
#[inline]
|
||||
pub fn low_u128(&self) -> u128 {
|
||||
let &$name(ref arr) = self;
|
||||
((arr[1] as u128) << 64) + arr[0] as u128
|
||||
}
|
||||
|
||||
/// Conversion to u128 with overflow checking
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the number is larger than 2^128.
|
||||
#[inline]
|
||||
pub fn as_u128(&self) -> u128 {
|
||||
let &$name(ref arr) = self;
|
||||
for i in 2..$n_words {
|
||||
if arr[i] != 0 {
|
||||
panic!("Integer overflow when casting to u128")
|
||||
}
|
||||
|
||||
}
|
||||
self.low_u128()
|
||||
}
|
||||
}
|
||||
};
|
||||
( @construct $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => {
|
||||
/// Little-endian large integer type
|
||||
#[repr(C)]
|
||||
$(#[$attr])*
|
||||
|
@ -366,7 +417,6 @@ macro_rules! construct_uint {
|
|||
}
|
||||
|
||||
impl $name {
|
||||
|
||||
/// Maximum value.
|
||||
pub const MAX: $name = $name([u64::max_value(); $n_words]);
|
||||
|
||||
|
@ -414,7 +464,7 @@ macro_rules! construct_uint {
|
|||
pub fn as_u32(&self) -> u32 {
|
||||
let &$name(ref arr) = self;
|
||||
if (arr[0] & (0xffffffffu64 << 32)) != 0 {
|
||||
panic!("Integer overflow when casting U256")
|
||||
panic!("Integer overflow when casting to u32")
|
||||
}
|
||||
self.as_u64() as u32
|
||||
}
|
||||
|
@ -429,7 +479,7 @@ macro_rules! construct_uint {
|
|||
let &$name(ref arr) = self;
|
||||
for i in 1..$n_words {
|
||||
if arr[i] != 0 {
|
||||
panic!("Integer overflow when casting U256")
|
||||
panic!("Integer overflow when casting to u64")
|
||||
}
|
||||
}
|
||||
arr[0]
|
||||
|
@ -445,11 +495,11 @@ macro_rules! construct_uint {
|
|||
let &$name(ref arr) = self;
|
||||
for i in 1..$n_words {
|
||||
if arr[i] != 0 {
|
||||
panic!("Integer overflow when casting U256")
|
||||
panic!("Integer overflow when casting to usize")
|
||||
}
|
||||
}
|
||||
if arr[0] > usize::max_value() as u64 {
|
||||
panic!("Integer overflow when casting U256")
|
||||
panic!("Integer overflow when casting to usize")
|
||||
}
|
||||
arr[0] as usize
|
||||
}
|
||||
|
@ -821,7 +871,6 @@ macro_rules! construct_uint {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl_map_from!($name, u8, u64);
|
||||
impl_map_from!($name, u16, u64);
|
||||
impl_map_from!($name, u32, u64);
|
||||
|
@ -841,7 +890,7 @@ macro_rules! construct_uint {
|
|||
impl_map_from!($name, i32, i64);
|
||||
impl_map_from!($name, isize, i64);
|
||||
|
||||
// Converts from big endian representation of U256
|
||||
// Converts from big endian representation.
|
||||
impl<'a> $crate::core_::convert::From<&'a [u8]> for $name {
|
||||
fn from(bytes: &[u8]) -> $name {
|
||||
Self::from_big_endian(bytes)
|
||||
|
|
|
@ -22,6 +22,16 @@ construct_uint! {
|
|||
pub struct U512(8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_conversions() {
|
||||
let mut a = U256::from(u128::max_value());
|
||||
assert_eq!(a.low_u128(), u128::max_value());
|
||||
a += 2u128.into();
|
||||
assert_eq!(a.low_u128(), 1u128);
|
||||
a -= 3u128.into();
|
||||
assert_eq!(a.low_u128(), u128::max_value() - 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uint256_checked_ops() {
|
||||
let z = U256::from(0);
|
||||
|
|
Loading…
Reference in New Issue