Merge pull request #97 from paritytech/sp-more-convert
Move `ethereum-types` to `parity-common` repo and more conversion functions for U128
This commit is contained in:
commit
52401dbe88
|
@ -20,4 +20,6 @@ members = [
|
|||
"uint",
|
||||
"parity-util-mem",
|
||||
"primitive-types",
|
||||
"ethereum-types",
|
||||
"ethbloom",
|
||||
]
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "ethbloom"
|
||||
version = "0.6.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
description = "Ethereum bloom filter"
|
||||
license = "MIT"
|
||||
documentation = "https://docs.rs/ethbloom"
|
||||
homepage = "https://github.com/paritytech/parity-common"
|
||||
repository = "https://github.com/paritytech/parity-common"
|
||||
|
||||
[dependencies]
|
||||
tiny-keccak = "1.4"
|
||||
crunchy = { version = "0.2.1", default-features = false, features = ["limit_256"] }
|
||||
fixed-hash = { path = "../fixed-hash", version = "0.3", default-features = false }
|
||||
impl-serde = { path = "../primitive-types/impls/serde", version = "0.1", default-features = false, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = { version = "0.4" }
|
||||
hex-literal = "0.1.1"
|
||||
|
||||
[features]
|
||||
default = ["std", "heapsize", "serialize", "fixed-hash/libc", "fixed-hash/rustc-hex"]
|
||||
std = ["fixed-hash/std", "crunchy/std"]
|
||||
heapsize = ["fixed-hash/heapsize"]
|
||||
serialize = ["std", "impl-serde"]
|
|
@ -0,0 +1,126 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
extern crate rustc_hex;
|
||||
extern crate tiny_keccak;
|
||||
extern crate ethbloom;
|
||||
|
||||
use test::Bencher;
|
||||
use rustc_hex::FromHex;
|
||||
use tiny_keccak::keccak256;
|
||||
use ethbloom::{Bloom, Input};
|
||||
|
||||
fn test_bloom() -> Bloom {
|
||||
use std::str::FromStr;
|
||||
Bloom::from_str(
|
||||
"00000000000000000000000000000000\
|
||||
00000000100000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000002020000000000000000000000\
|
||||
00000000000000000000000800000000\
|
||||
10000000000000000000000000000000\
|
||||
00000000000000000000001000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000"
|
||||
).unwrap()
|
||||
}
|
||||
|
||||
fn test_topic() -> Vec<u8> {
|
||||
"02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc".from_hex().unwrap()
|
||||
}
|
||||
|
||||
fn test_address() -> Vec<u8> {
|
||||
"ef2d6d194084c2de36e0dabfce45d046b37d1106".from_hex().unwrap()
|
||||
}
|
||||
|
||||
fn test_dummy() -> Vec<u8> {
|
||||
b"123456".to_vec()
|
||||
}
|
||||
|
||||
fn test_dummy2() -> Vec<u8> {
|
||||
b"654321".to_vec()
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn accrue_raw(b: &mut Bencher) {
|
||||
let mut bloom = Bloom::default();
|
||||
let topic = test_topic();
|
||||
let address = test_address();
|
||||
b.iter(|| {
|
||||
bloom.accrue(Input::Raw(&topic));
|
||||
bloom.accrue(Input::Raw(&address));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn accrue_hash(b: &mut Bencher) {
|
||||
let mut bloom = Bloom::default();
|
||||
let topic = keccak256(&test_topic());
|
||||
let address = keccak256(&test_address());
|
||||
b.iter(|| {
|
||||
bloom.accrue(Input::Hash(&topic));
|
||||
bloom.accrue(Input::Hash(&address));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn contains_input_raw(b: &mut Bencher) {
|
||||
let bloom = test_bloom();
|
||||
let topic = test_topic();
|
||||
let address = test_address();
|
||||
b.iter(|| {
|
||||
assert!(bloom.contains_input(Input::Raw(&topic)));
|
||||
assert!(bloom.contains_input(Input::Raw(&address)));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn does_not_contain_raw(b: &mut Bencher) {
|
||||
let bloom = test_bloom();
|
||||
let dummy = test_dummy();
|
||||
let dummy2 = test_dummy2();
|
||||
b.iter(|| {
|
||||
assert!(!bloom.contains_input(Input::Raw(&dummy)));
|
||||
assert!(!bloom.contains_input(Input::Raw(&dummy2)));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn contains_input_hash(b: &mut Bencher) {
|
||||
let bloom = test_bloom();
|
||||
let topic = keccak256(&test_topic());
|
||||
let address = keccak256(&test_address());
|
||||
b.iter(|| {
|
||||
assert!(bloom.contains_input(Input::Hash(&topic)));
|
||||
assert!(bloom.contains_input(Input::Hash(&address)));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn does_not_contain_hash(b: &mut Bencher) {
|
||||
let bloom = test_bloom();
|
||||
let dummy = keccak256(&test_dummy());
|
||||
let dummy2 = keccak256(&test_dummy2());
|
||||
b.iter(|| {
|
||||
assert!(!bloom.contains_input(Input::Hash(&dummy)));
|
||||
assert!(!bloom.contains_input(Input::Hash(&dummy2)));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn does_not_contain_random_hash(b: &mut Bencher) {
|
||||
let bloom = test_bloom();
|
||||
let dummy: Vec<_> = (0..255u8).into_iter().map(|i| keccak256(&[i])).collect();
|
||||
b.iter(|| {
|
||||
for d in &dummy {
|
||||
assert!(!bloom.contains_input(Input::Hash(d)));
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
extern crate rand;
|
||||
|
||||
#[macro_use]
|
||||
extern crate crunchy;
|
||||
|
||||
use test::{Bencher, black_box};
|
||||
use rand::Rng;
|
||||
|
||||
fn random_data() -> [u8; 256] {
|
||||
let mut res = [0u8; 256];
|
||||
rand::thread_rng().fill_bytes(&mut res);
|
||||
res
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn forwards_with_crunchy(b: &mut Bencher) {
|
||||
let mut data = random_data();
|
||||
b.iter(|| {
|
||||
let other_data = random_data();
|
||||
unroll! {
|
||||
for i in 0..255 {
|
||||
data[i] |= other_data[i];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
black_box(data);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn backwards_with_crunchy(b: &mut Bencher) {
|
||||
let mut data = random_data();
|
||||
b.iter(|| {
|
||||
let other_data = random_data();
|
||||
unroll! {
|
||||
for i in 0..255 {
|
||||
data[255-i] |= other_data[255-i];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
black_box(data);
|
||||
}
|
||||
|
||||
|
||||
#[bench]
|
||||
fn forwards_without_crunchy(b: &mut Bencher) {
|
||||
let mut data = random_data();
|
||||
b.iter(|| {
|
||||
let other_data = random_data();
|
||||
for i in 0..255 {
|
||||
data[i] |= other_data[i];
|
||||
}
|
||||
});
|
||||
|
||||
black_box(data);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn backwards_without_crunchy(b: &mut Bencher) {
|
||||
let mut data = random_data();
|
||||
b.iter(|| {
|
||||
let other_data = random_data();
|
||||
for i in 0..255 {
|
||||
data[255-i] |= other_data[255-i];
|
||||
}
|
||||
});
|
||||
|
||||
black_box(data);
|
||||
}
|
|
@ -0,0 +1,301 @@
|
|||
//!
|
||||
//! ```rust
|
||||
//! extern crate ethbloom;
|
||||
//! #[macro_use] extern crate hex_literal;
|
||||
//! use ethbloom::{Bloom, Input};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! use std::str::FromStr;
|
||||
//! let bloom = Bloom::from_str(
|
||||
//! "00000000000000000000000000000000\
|
||||
//! 00000000100000000000000000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000002020000000000000000000000\
|
||||
//! 00000000000000000000000800000000\
|
||||
//! 10000000000000000000000000000000\
|
||||
//! 00000000000000000000001000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000000000000000000000000000000\
|
||||
//! 00000000000000000000000000000000"
|
||||
//! ).unwrap();
|
||||
//! let address = hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106");
|
||||
//! let topic = hex!("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc");
|
||||
//!
|
||||
//! let mut my_bloom = Bloom::default();
|
||||
//! assert!(!my_bloom.contains_input(Input::Raw(&address)));
|
||||
//! assert!(!my_bloom.contains_input(Input::Raw(&topic)));
|
||||
//!
|
||||
//! my_bloom.accrue(Input::Raw(&address));
|
||||
//! assert!(my_bloom.contains_input(Input::Raw(&address)));
|
||||
//! assert!(!my_bloom.contains_input(Input::Raw(&topic)));
|
||||
//!
|
||||
//! my_bloom.accrue(Input::Raw(&topic));
|
||||
//! assert!(my_bloom.contains_input(Input::Raw(&address)));
|
||||
//! assert!(my_bloom.contains_input(Input::Raw(&topic)));
|
||||
//! assert_eq!(my_bloom, bloom);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
|
||||
#![cfg_attr(not(feature="std"), no_std)]
|
||||
|
||||
#[cfg(feature="std")]
|
||||
extern crate core;
|
||||
|
||||
extern crate tiny_keccak;
|
||||
#[macro_use]
|
||||
extern crate crunchy;
|
||||
|
||||
#[macro_use]
|
||||
extern crate fixed_hash;
|
||||
|
||||
#[cfg(feature="serialize")]
|
||||
#[macro_use]
|
||||
extern crate impl_serde;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate hex_literal;
|
||||
|
||||
use core::{ops, mem};
|
||||
use tiny_keccak::keccak256;
|
||||
|
||||
#[cfg(feature="std")]
|
||||
use core::str;
|
||||
|
||||
// 3 according to yellowpaper
|
||||
const BLOOM_BITS: u32 = 3;
|
||||
const BLOOM_SIZE: usize = 256;
|
||||
|
||||
construct_fixed_hash!{
|
||||
/// Bloom hash type with 256 bytes (2048 bits) size.
|
||||
pub struct Bloom(BLOOM_SIZE);
|
||||
}
|
||||
|
||||
/// Returns log2.
|
||||
fn log2(x: usize) -> u32 {
|
||||
if x <= 1 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let n = x.leading_zeros();
|
||||
mem::size_of::<usize>() as u32 * 8 - n
|
||||
}
|
||||
|
||||
pub enum Input<'a> {
|
||||
Raw(&'a [u8]),
|
||||
Hash(&'a [u8; 32]),
|
||||
}
|
||||
|
||||
enum Hash<'a> {
|
||||
Ref(&'a [u8; 32]),
|
||||
Owned([u8; 32]),
|
||||
}
|
||||
|
||||
impl<'a> From<Input<'a>> for Hash<'a> {
|
||||
fn from(input: Input<'a>) -> Self {
|
||||
match input {
|
||||
Input::Raw(raw) => Hash::Owned(keccak256(raw)),
|
||||
Input::Hash(hash) => Hash::Ref(hash),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ops::Index<usize> for Hash<'a> {
|
||||
type Output = u8;
|
||||
|
||||
fn index(&self, index: usize) -> &u8 {
|
||||
match *self {
|
||||
Hash::Ref(r) => &r[index],
|
||||
Hash::Owned(ref hash) => &hash[index],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Hash<'a> {
|
||||
fn len(&self) -> usize {
|
||||
match *self {
|
||||
Hash::Ref(r) => r.len(),
|
||||
Hash::Owned(ref hash) => hash.len(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<BloomRef<'a>> for Bloom {
|
||||
fn eq(&self, other: &BloomRef<'a>) -> bool {
|
||||
let s_ref: &[u8] = &self.0;
|
||||
let o_ref: &[u8] = other.0;
|
||||
s_ref.eq(o_ref)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Input<'a>> for Bloom {
|
||||
fn from(input: Input<'a>) -> Bloom {
|
||||
let mut bloom = Bloom::default();
|
||||
bloom.accrue(input);
|
||||
bloom
|
||||
}
|
||||
}
|
||||
|
||||
impl Bloom {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.iter().all(|x| *x == 0)
|
||||
}
|
||||
|
||||
pub fn contains_input<'a>(&self, input: Input<'a>) -> bool {
|
||||
let bloom: Bloom = input.into();
|
||||
self.contains_bloom(&bloom)
|
||||
}
|
||||
|
||||
pub fn contains_bloom<'a, B>(&self, bloom: B) -> bool where BloomRef<'a>: From<B> {
|
||||
let bloom_ref: BloomRef = bloom.into();
|
||||
// workaround for https://github.com/rust-lang/rust/issues/43644
|
||||
self.contains_bloom_ref(bloom_ref)
|
||||
}
|
||||
|
||||
fn contains_bloom_ref(&self, bloom: BloomRef) -> bool {
|
||||
let self_ref: BloomRef = self.into();
|
||||
self_ref.contains_bloom(bloom)
|
||||
}
|
||||
|
||||
pub fn accrue<'a>(&mut self, input: Input<'a>) {
|
||||
let p = BLOOM_BITS;
|
||||
|
||||
let m = self.0.len();
|
||||
let bloom_bits = m * 8;
|
||||
let mask = bloom_bits - 1;
|
||||
let bloom_bytes = (log2(bloom_bits) + 7) / 8;
|
||||
|
||||
let hash: Hash = input.into();
|
||||
|
||||
// must be a power of 2
|
||||
assert_eq!(m & (m - 1), 0);
|
||||
// out of range
|
||||
assert!(p * bloom_bytes <= hash.len() as u32);
|
||||
|
||||
let mut ptr = 0;
|
||||
|
||||
assert_eq!(BLOOM_BITS, 3);
|
||||
unroll! {
|
||||
for i in 0..3 {
|
||||
let _ = i;
|
||||
let mut index = 0 as usize;
|
||||
for _ in 0..bloom_bytes {
|
||||
index = (index << 8) | hash[ptr] as usize;
|
||||
ptr += 1;
|
||||
}
|
||||
index &= mask;
|
||||
self.0[m - 1 - index / 8] |= 1 << (index % 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn accrue_bloom<'a, B>(&mut self, bloom: B) where BloomRef<'a>: From<B> {
|
||||
let bloom_ref: BloomRef = bloom.into();
|
||||
assert_eq!(self.0.len(), BLOOM_SIZE);
|
||||
assert_eq!(bloom_ref.0.len(), BLOOM_SIZE);
|
||||
for i in 0..BLOOM_SIZE {
|
||||
self.0[i] |= bloom_ref.0[i];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data(&self) -> &[u8; BLOOM_SIZE] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct BloomRef<'a>(&'a [u8; BLOOM_SIZE]);
|
||||
|
||||
impl<'a> BloomRef<'a> {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.iter().all(|x| *x == 0)
|
||||
}
|
||||
|
||||
pub fn contains_input<'b>(&self, input: Input<'b>) -> bool {
|
||||
let bloom: Bloom = input.into();
|
||||
self.contains_bloom(&bloom)
|
||||
}
|
||||
|
||||
pub fn contains_bloom<'b, B>(&self, bloom: B) -> bool where BloomRef<'b>: From<B> {
|
||||
let bloom_ref: BloomRef = bloom.into();
|
||||
assert_eq!(self.0.len(), BLOOM_SIZE);
|
||||
assert_eq!(bloom_ref.0.len(), BLOOM_SIZE);
|
||||
for i in 0..BLOOM_SIZE {
|
||||
let a = self.0[i];
|
||||
let b = bloom_ref.0[i];
|
||||
if (a & b) != b {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn data(&self) -> &'a [u8; BLOOM_SIZE] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a [u8; BLOOM_SIZE]> for BloomRef<'a> {
|
||||
fn from(data: &'a [u8; BLOOM_SIZE]) -> Self {
|
||||
BloomRef(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Bloom> for BloomRef<'a> {
|
||||
fn from(bloom: &'a Bloom) -> Self {
|
||||
BloomRef(&bloom.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl_fixed_hash_serde!(Bloom, BLOOM_SIZE);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Bloom, Input};
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
use std::str::FromStr;
|
||||
let bloom = Bloom::from_str(
|
||||
"00000000000000000000000000000000\
|
||||
00000000100000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000002020000000000000000000000\
|
||||
00000000000000000000000800000000\
|
||||
10000000000000000000000000000000\
|
||||
00000000000000000000001000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000\
|
||||
00000000000000000000000000000000"
|
||||
).unwrap();
|
||||
let address = hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106");
|
||||
let topic = hex!("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc");
|
||||
|
||||
let mut my_bloom = Bloom::default();
|
||||
assert!(!my_bloom.contains_input(Input::Raw(&address)));
|
||||
assert!(!my_bloom.contains_input(Input::Raw(&topic)));
|
||||
|
||||
my_bloom.accrue(Input::Raw(&address));
|
||||
assert!(my_bloom.contains_input(Input::Raw(&address)));
|
||||
assert!(!my_bloom.contains_input(Input::Raw(&topic)));
|
||||
|
||||
my_bloom.accrue(Input::Raw(&topic));
|
||||
assert!(my_bloom.contains_input(Input::Raw(&address)));
|
||||
assert!(my_bloom.contains_input(Input::Raw(&topic)));
|
||||
assert_eq!(my_bloom, bloom);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "ethereum-types"
|
||||
version = "0.5.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
license = "MIT"
|
||||
homepage = "https://github.com/paritytech/parity-common"
|
||||
description = "Ethereum types"
|
||||
|
||||
[dependencies]
|
||||
ethbloom = { path = "../ethbloom", version = "0.6", default-features = false }
|
||||
fixed-hash = { path = "../fixed-hash", version = "0.3", default-features = false, features = ["byteorder", "rustc-hex"] }
|
||||
uint = { path = "../uint", version = "0.6", default-features = false }
|
||||
primitive-types = { path = "../primitive-types", version = "0.2", features = ["rlp", "byteorder", "rustc-hex"], default-features = false }
|
||||
impl-serde = { path = "../primitive-types/impls/serde", version = "0.1", default-features = false, optional = true }
|
||||
impl-rlp = { path = "../primitive-types/impls/rlp", version = "0.1", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
default = ["std", "heapsize", "serialize"]
|
||||
std = ["uint/std", "fixed-hash/std", "ethbloom/std", "primitive-types/std"]
|
||||
heapsize = ["uint/heapsize", "primitive-types/heapsize", "fixed-hash/heapsize", "ethbloom/heapsize"]
|
||||
serialize = ["std", "impl-serde", "primitive-types/serde", "ethbloom/serialize"]
|
|
@ -0,0 +1,216 @@
|
|||
// Copyright 2015-2017 Parity Technologies
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! benchmarking for bigint
|
||||
//! should be started with:
|
||||
//! ```bash
|
||||
//! rustup run nightly cargo bench
|
||||
//! ```
|
||||
|
||||
#![feature(test)]
|
||||
#![feature(asm)]
|
||||
|
||||
extern crate test;
|
||||
extern crate bigint;
|
||||
|
||||
use test::{Bencher, black_box};
|
||||
use bigint::{U256, U512, U128};
|
||||
|
||||
#[bench]
|
||||
fn u256_add(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let n = black_box(10000);
|
||||
let zero = black_box(U256::zero());
|
||||
(0..n).fold(zero, |old, new| {
|
||||
old.overflowing_add(U256::from(black_box(new))).0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u256_sub(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let n = black_box(10000);
|
||||
let max = black_box(U256::max_value());
|
||||
(0..n).fold(max, |old, new| {
|
||||
old.overflowing_sub(U256::from(black_box(new))).0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u512_sub(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let n = black_box(10000);
|
||||
let max = black_box(U512::max_value());
|
||||
(0..n).fold(max, |old, new| {
|
||||
let new = black_box(new);
|
||||
let p = new % 2;
|
||||
old.overflowing_sub(U512([p, p, p, p, p, p, p, new])).0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u512_add(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let n = black_box(10000);
|
||||
let zero = black_box(U512::zero());
|
||||
(0..n).fold(zero, |old, new| {
|
||||
let new = black_box(new);
|
||||
old.overflowing_add(U512([new, new, new, new, new, new, new, new]))
|
||||
.0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u512_mul(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
(1..10000).fold(black_box(U512::one()), |old, new| {
|
||||
old.overflowing_mul(U512::from(black_box(new | 1))).0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u512_mul_small(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
(1..153).fold(black_box(U512::one()), |old, _| {
|
||||
old.overflowing_mul(U512::from(black_box(10))).0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u256_mul(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
(1..10000).fold(black_box(U256::one()), |old, new| {
|
||||
old.overflowing_mul(U256::from(black_box(new | 1))).0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u256_mul_small(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
(1..77).fold(black_box(U256::one()), |old, _| {
|
||||
old.overflowing_mul(U256::from(black_box(10))).0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u256_full_mul(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let n = black_box(10000);
|
||||
let one = black_box(U256::one());
|
||||
(1..n).map(|n| n | 1).fold(one, |old, new| {
|
||||
let new = black_box(new);
|
||||
let U512(ref u512words) = old.full_mul(U256([new, new, new, new]));
|
||||
U256([u512words[0], u512words[2], u512words[2], u512words[3]])
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[bench]
|
||||
fn u128_mul(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let n = black_box(10000);
|
||||
(1..n).fold(U128([12345u64, 0u64]), |old, new| {
|
||||
old.overflowing_mul(U128::from(new | 1)).0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u256_from_le(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let raw = black_box(
|
||||
[
|
||||
1u8,
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
11,
|
||||
13,
|
||||
17,
|
||||
19,
|
||||
23,
|
||||
29,
|
||||
31,
|
||||
37,
|
||||
41,
|
||||
43,
|
||||
47,
|
||||
53,
|
||||
59,
|
||||
61,
|
||||
67,
|
||||
71,
|
||||
73,
|
||||
79,
|
||||
83,
|
||||
89,
|
||||
97,
|
||||
101,
|
||||
103,
|
||||
107,
|
||||
109,
|
||||
113,
|
||||
127,
|
||||
],
|
||||
);
|
||||
let _ = U256::from_little_endian(&raw[..]);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn u256_from_be(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let raw = black_box(
|
||||
[
|
||||
1u8,
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
11,
|
||||
13,
|
||||
17,
|
||||
19,
|
||||
23,
|
||||
29,
|
||||
31,
|
||||
37,
|
||||
41,
|
||||
43,
|
||||
47,
|
||||
53,
|
||||
59,
|
||||
61,
|
||||
67,
|
||||
71,
|
||||
73,
|
||||
79,
|
||||
83,
|
||||
89,
|
||||
97,
|
||||
101,
|
||||
103,
|
||||
107,
|
||||
109,
|
||||
113,
|
||||
127,
|
||||
],
|
||||
);
|
||||
let _ = U256::from_big_endian(&raw[..]);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
use crate::{U64, U128, U256, U512};
|
||||
|
||||
pub trait BigEndianHash {
|
||||
type Uint;
|
||||
|
||||
fn from_uint(val: &Self::Uint) -> Self;
|
||||
fn into_uint(&self) -> Self::Uint;
|
||||
}
|
||||
|
||||
construct_fixed_hash!{ pub struct H32(4); }
|
||||
impl_fixed_hash_rlp!(H32, 4);
|
||||
#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H32, 4);
|
||||
|
||||
construct_fixed_hash!{ pub struct H64(8); }
|
||||
impl_fixed_hash_rlp!(H64, 8);
|
||||
#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H64, 8);
|
||||
|
||||
construct_fixed_hash!{ pub struct H128(16); }
|
||||
impl_fixed_hash_rlp!(H128, 16);
|
||||
#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H128, 16);
|
||||
|
||||
pub use primitive_types::H160;
|
||||
pub use primitive_types::H256;
|
||||
|
||||
construct_fixed_hash!{ pub struct H264(33); }
|
||||
impl_fixed_hash_rlp!(H264, 33);
|
||||
#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H264, 33);
|
||||
|
||||
pub use primitive_types::H512;
|
||||
|
||||
construct_fixed_hash!{ pub struct H520(65); }
|
||||
impl_fixed_hash_rlp!(H520, 65);
|
||||
#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H520, 65);
|
||||
|
||||
macro_rules! impl_uint_conversions {
|
||||
($hash: ident, $uint: ident) => {
|
||||
impl BigEndianHash for $hash {
|
||||
type Uint = $uint;
|
||||
|
||||
fn from_uint(value: &$uint) -> Self {
|
||||
let mut ret = $hash::zero();
|
||||
value.to_big_endian(ret.as_bytes_mut());
|
||||
ret
|
||||
}
|
||||
|
||||
fn into_uint(&self) -> $uint {
|
||||
$uint::from(self.as_ref() as &[u8])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_uint_conversions!(H64, U64);
|
||||
impl_uint_conversions!(H128, U128);
|
||||
impl_uint_conversions!(H256, U256);
|
||||
impl_uint_conversions!(H512, U512);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{H160, H256};
|
||||
use serde_json as ser;
|
||||
|
||||
#[test]
|
||||
fn test_serialize_h160() {
|
||||
let tests = vec![
|
||||
(H160::from_low_u64_be(0), "0x0000000000000000000000000000000000000000"),
|
||||
(H160::from_low_u64_be(2), "0x0000000000000000000000000000000000000002"),
|
||||
(H160::from_low_u64_be(15), "0x000000000000000000000000000000000000000f"),
|
||||
(H160::from_low_u64_be(16), "0x0000000000000000000000000000000000000010"),
|
||||
(H160::from_low_u64_be(1_000), "0x00000000000000000000000000000000000003e8"),
|
||||
(H160::from_low_u64_be(100_000), "0x00000000000000000000000000000000000186a0"),
|
||||
(H160::from_low_u64_be(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"),
|
||||
];
|
||||
|
||||
for (number, expected) in tests {
|
||||
assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap());
|
||||
assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_h256() {
|
||||
let tests = vec![
|
||||
(H256::from_low_u64_be(0), "0x0000000000000000000000000000000000000000000000000000000000000000"),
|
||||
(H256::from_low_u64_be(2), "0x0000000000000000000000000000000000000000000000000000000000000002"),
|
||||
(H256::from_low_u64_be(15), "0x000000000000000000000000000000000000000000000000000000000000000f"),
|
||||
(H256::from_low_u64_be(16), "0x0000000000000000000000000000000000000000000000000000000000000010"),
|
||||
(H256::from_low_u64_be(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"),
|
||||
(H256::from_low_u64_be(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"),
|
||||
(H256::from_low_u64_be(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"),
|
||||
];
|
||||
|
||||
for (number, expected) in tests {
|
||||
assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap());
|
||||
assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_invalid() {
|
||||
assert!(ser::from_str::<H256>("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"0\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"10\"").unwrap_err().is_data());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
#[macro_use]
|
||||
extern crate uint as uint_crate;
|
||||
#[macro_use]
|
||||
extern crate fixed_hash;
|
||||
extern crate ethbloom;
|
||||
extern crate primitive_types;
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
#[macro_use]
|
||||
extern crate impl_serde;
|
||||
|
||||
#[macro_use]
|
||||
extern crate impl_rlp;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate serde_json;
|
||||
|
||||
mod hash;
|
||||
mod uint;
|
||||
|
||||
pub use uint::{U64, U128, U256, U512};
|
||||
pub use hash::{BigEndianHash, H32, H64, H128, H160, H256, H264, H512, H520};
|
||||
pub use ethbloom::{Bloom, BloomRef, Input as BloomInput};
|
||||
|
||||
pub type Address = H160;
|
||||
pub type Secret = H256;
|
||||
pub type Public = H512;
|
||||
pub type Signature = H520;
|
|
@ -0,0 +1,177 @@
|
|||
construct_uint! {
|
||||
/// Unsigned 64-bit integer.
|
||||
pub struct U64(1);
|
||||
}
|
||||
impl_uint_rlp!(U64, 1);
|
||||
#[cfg(feature = "serialize")] impl_uint_serde!(U64, 1);
|
||||
|
||||
pub use primitive_types::{U128, U256, U512};
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{U256, U512};
|
||||
use std::u64::MAX;
|
||||
use serde_json as ser;
|
||||
|
||||
macro_rules! test_serialize {
|
||||
($name: ident, $test_name: ident) => {
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
let tests = vec![
|
||||
($name::from(0), "0x0"),
|
||||
($name::from(1), "0x1"),
|
||||
($name::from(2), "0x2"),
|
||||
($name::from(10), "0xa"),
|
||||
($name::from(15), "0xf"),
|
||||
($name::from(15), "0xf"),
|
||||
($name::from(16), "0x10"),
|
||||
($name::from(1_000), "0x3e8"),
|
||||
($name::from(100_000), "0x186a0"),
|
||||
($name::from(u64::max_value()), "0xffffffffffffffff"),
|
||||
($name::from(u64::max_value()) + 1, "0x10000000000000000"),
|
||||
];
|
||||
|
||||
for (number, expected) in tests {
|
||||
assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap());
|
||||
assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap());
|
||||
}
|
||||
|
||||
// Invalid examples
|
||||
assert!(ser::from_str::<$name>("\"0x\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<$name>("\"0xg\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<$name>("\"\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<$name>("\"10\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<$name>("\"0\"").unwrap_err().is_data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test_serialize!(U256, test_u256);
|
||||
test_serialize!(U512, test_u512);
|
||||
|
||||
#[test]
|
||||
fn test_serialize_large_values() {
|
||||
assert_eq!(
|
||||
ser::to_string_pretty(&!U256::zero()).unwrap(),
|
||||
"\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\""
|
||||
);
|
||||
assert!(
|
||||
ser::from_str::<U256>("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixed_arrays_roundtrip() {
|
||||
let raw: U256 = "7094875209347850239487502394881".into();
|
||||
let array: [u8; 32] = raw.into();
|
||||
let new_raw = array.into();
|
||||
|
||||
assert_eq!(raw, new_raw);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u256_multi_full_mul() {
|
||||
let result = U256([0, 0, 0, 0]).full_mul(U256([0, 0, 0, 0]));
|
||||
assert_eq!(U512([0, 0, 0, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([1, 0, 0, 0]).full_mul(U256([1, 0, 0, 0]));
|
||||
assert_eq!(U512([1, 0, 0, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([5, 0, 0, 0]).full_mul(U256([5, 0, 0, 0]));
|
||||
assert_eq!(U512([25, 0, 0, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([0, 5, 0, 0]).full_mul(U256([0, 5, 0, 0]));
|
||||
assert_eq!(U512([0, 0, 25, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([0, 0, 0, 4]).full_mul(U256([4, 0, 0, 0]));
|
||||
assert_eq!(U512([0, 0, 0, 16, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([0, 0, 0, 5]).full_mul(U256([2, 0, 0, 0]));
|
||||
assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([0, 0, 2, 0]).full_mul(U256([0, 5, 0, 0]));
|
||||
assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([0, 3, 0, 0]).full_mul(U256([0, 0, 3, 0]));
|
||||
assert_eq!(U512([0, 0, 0, 9, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([0, 0, 8, 0]).full_mul(U256([0, 0, 6, 0]));
|
||||
assert_eq!(U512([0, 0, 0, 0, 48, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([9, 0, 0, 0]).full_mul(U256([0, 3, 0, 0]));
|
||||
assert_eq!(U512([0, 27, 0, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, 0, 0, 0]));
|
||||
assert_eq!(U512([1, MAX-1, 0, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([0, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0]));
|
||||
assert_eq!(U512([0, 1, MAX-1, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0]));
|
||||
assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, 0, 0]));
|
||||
assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, 0, 0]));
|
||||
assert_eq!(U512([1, 0, MAX-1, MAX, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0]));
|
||||
assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, 0, 0, 0]));
|
||||
assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX]));
|
||||
assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, 0, 0, 0]));
|
||||
assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, 0, 0]));
|
||||
assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0]));
|
||||
assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, 0, 0]));
|
||||
assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX]));
|
||||
assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, 0]));
|
||||
assert_eq!(U512([1, 0, 0, MAX-1, MAX, MAX, 0, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, MAX]));
|
||||
assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, 0]));
|
||||
assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result);
|
||||
|
||||
let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, MAX]));
|
||||
assert_eq!(U512([1, 0, 0, 0, MAX-1, MAX, MAX, MAX]), result);
|
||||
|
||||
let result = U256([0, 0, 0, MAX]).full_mul(U256([0, 0, 0, MAX]));
|
||||
assert_eq!(U512([0, 0, 0, 0, 0, 0, 1, MAX-1]), result);
|
||||
|
||||
let result = U256([1, 0, 0, 0]).full_mul(U256([0, 0, 0, MAX]));
|
||||
assert_eq!(U512([0, 0, 0, MAX, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([1, 2, 3, 4]).full_mul(U256([5, 0, 0, 0]));
|
||||
assert_eq!(U512([5, 10, 15, 20, 0, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([1, 2, 3, 4]).full_mul(U256([0, 6, 0, 0]));
|
||||
assert_eq!(U512([0, 6, 12, 18, 24, 0, 0, 0]), result);
|
||||
|
||||
let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 7, 0]));
|
||||
assert_eq!(U512([0, 0, 7, 14, 21, 28, 0, 0]), result);
|
||||
|
||||
let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 0, 8]));
|
||||
assert_eq!(U512([0, 0, 0, 8, 16, 24, 32, 0]), result);
|
||||
|
||||
let result = U256([1, 2, 3, 4]).full_mul(U256([5, 6, 7, 8]));
|
||||
assert_eq!(U512([5, 16, 34, 60, 61, 52, 32, 0]), result);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "primitive-types"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
homepage = "https://github.com/paritytech/parity-common"
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright 2015-2019 Parity Technologies
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// TODO: Remove TryFrom and TryInto when Rust trait is stablized
|
||||
// https://github.com/paritytech/parity-common/issues/103
|
||||
//! Error, `TryFrom` and `TryInto` trait, should be removed when standard library stablize those.
|
||||
|
||||
/// Error type for conversion.
|
||||
pub enum Error {
|
||||
/// Overflow encountered.
|
||||
Overflow,
|
||||
}
|
||||
|
||||
/// An attempted conversion that consumes `self`, which may or may not be
|
||||
/// expensive.
|
||||
///
|
||||
/// Library authors should not directly implement this trait, but should prefer
|
||||
/// implementing the [`TryFrom`] trait, which offers greater flexibility and
|
||||
/// provides an equivalent `TryInto` implementation for free, thanks to a
|
||||
/// blanket implementation in the standard library. For more information on this,
|
||||
/// see the documentation for [`Into`].
|
||||
///
|
||||
/// [`TryFrom`]: trait.TryFrom.html
|
||||
/// [`Into`]: trait.Into.html
|
||||
pub trait TryInto<T>: Sized {
|
||||
/// The type returned in the event of a conversion error.
|
||||
type Error;
|
||||
|
||||
/// Performs the conversion.
|
||||
fn try_into(self) -> Result<T, Self::Error>;
|
||||
}
|
||||
|
||||
/// Attempt to construct `Self` via a conversion.
|
||||
pub trait TryFrom<T>: Sized {
|
||||
/// The type returned in the event of a conversion error.
|
||||
type Error;
|
||||
|
||||
/// Performs the conversion.
|
||||
fn try_from(value: T) -> Result<Self, Self::Error>;
|
||||
}
|
||||
|
||||
// TryFrom implies TryInto
|
||||
impl<T, U> TryInto<U> for T where U: TryFrom<T>
|
||||
{
|
||||
type Error = U::Error;
|
||||
|
||||
fn try_into(self) -> Result<U, U::Error> {
|
||||
U::try_from(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Never { }
|
||||
|
||||
// Infallible conversions are semantically equivalent to fallible conversions
|
||||
// with an uninhabited error type.
|
||||
impl<T, U> TryFrom<U> for T where T: From<U> {
|
||||
type Error = Never;
|
||||
|
||||
fn try_from(value: U) -> Result<Self, Self::Error> {
|
||||
Ok(T::from(value))
|
||||
}
|
||||
}
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
mod error;
|
||||
|
||||
pub use error::{Error, TryFrom, TryInto, Never};
|
||||
|
||||
#[macro_use]
|
||||
extern crate uint;
|
||||
|
||||
|
@ -97,7 +101,6 @@ mod rlp {
|
|||
impl_fixed_hash_rlp!(H512, 64);
|
||||
}
|
||||
|
||||
|
||||
impl_fixed_hash_conversions!(H256, H160);
|
||||
|
||||
impl U256 {
|
||||
|
@ -121,17 +124,69 @@ impl From<U256> for U512 {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<U512> for U256 {
|
||||
fn from(value: U512) -> U256 {
|
||||
impl TryFrom<U256> for U128 {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: U256) -> Result<U128, Error> {
|
||||
let U256(ref arr) = value;
|
||||
if arr[2] | arr[3] != 0 {
|
||||
return Err(Error::Overflow);
|
||||
}
|
||||
let mut ret = [0; 2];
|
||||
ret[0] = arr[0];
|
||||
ret[1] = arr[1];
|
||||
Ok(U128(ret))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<U512> for U256 {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: U512) -> Result<U256, Error> {
|
||||
let U512(ref arr) = value;
|
||||
if arr[4] | arr[5] | arr[6] | arr[7] != 0 {
|
||||
panic!("From<U512> for U256: encountered overflow")
|
||||
return Err(Error::Overflow);
|
||||
}
|
||||
let mut ret = [0; 4];
|
||||
ret[0] = arr[0];
|
||||
ret[1] = arr[1];
|
||||
ret[2] = arr[2];
|
||||
ret[3] = arr[3];
|
||||
Ok(U256(ret))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<U512> for U128 {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: U512) -> Result<U128, Error> {
|
||||
let U512(ref arr) = value;
|
||||
if arr[2] | arr[3] | arr[4] | arr[5] | arr[6] | arr[7] != 0 {
|
||||
return Err(Error::Overflow);
|
||||
}
|
||||
let mut ret = [0; 2];
|
||||
ret[0] = arr[0];
|
||||
ret[1] = arr[1];
|
||||
Ok(U128(ret))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<U128> for U512 {
|
||||
fn from(value: U128) -> U512 {
|
||||
let U128(ref arr) = value;
|
||||
let mut ret = [0; 8];
|
||||
ret[0] = arr[0];
|
||||
ret[1] = arr[1];
|
||||
U512(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<U128> for U256 {
|
||||
fn from(value: U128) -> U256 {
|
||||
let U128(ref arr) = value;
|
||||
let mut ret = [0; 4];
|
||||
ret[0] = arr[0];
|
||||
ret[1] = arr[1];
|
||||
U256(ret)
|
||||
}
|
||||
}
|
||||
|
@ -148,17 +203,19 @@ impl<'a> From<&'a U256> for U512 {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a U512> for U256 {
|
||||
fn from(value: &'a U512) -> U256 {
|
||||
impl<'a> TryFrom<&'a U512> for U256 {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: &'a U512) -> Result<U256, Error> {
|
||||
let U512(ref arr) = *value;
|
||||
if arr[4] | arr[5] | arr[6] | arr[7] != 0 {
|
||||
panic!("From<&U512> for U256: encountered overflow")
|
||||
return Err(Error::Overflow);
|
||||
}
|
||||
let mut ret = [0; 4];
|
||||
ret[0] = arr[0];
|
||||
ret[1] = arr[1];
|
||||
ret[2] = arr[2];
|
||||
ret[3] = arr[3];
|
||||
U256(ret)
|
||||
Ok(U256(ret))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue