Merge pull request #3 from gavofyork/rlp_u256
rlp encoding and decoding u256
This commit is contained in:
commit
8cf5305d28
@ -10,19 +10,53 @@ extern crate test;
|
|||||||
extern crate ethcore_util;
|
extern crate ethcore_util;
|
||||||
|
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
use ethcore_util::rlp;
|
use std::str::FromStr;
|
||||||
use ethcore_util::rlp::{RlpStream, Rlp, Decodable};
|
use ethcore_util::rlp::{RlpStream, Rlp, Decodable};
|
||||||
|
use ethcore_util::uint::U256;
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_stream_value(b: &mut Bencher) {
|
fn bench_stream_u64_value(b: &mut Bencher) {
|
||||||
b.iter( || {
|
b.iter( || {
|
||||||
//1029
|
//1029
|
||||||
let mut stream = RlpStream::new();
|
let mut stream = RlpStream::new();
|
||||||
stream.append(&1029u32);
|
stream.append(&1029u64);
|
||||||
let _ = stream.out().unwrap();
|
let _ = stream.out().unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_decode_u64_value(b: &mut Bencher) {
|
||||||
|
b.iter( || {
|
||||||
|
// 1029
|
||||||
|
let data = vec![0x82, 0x04, 0x05];
|
||||||
|
let rlp = Rlp::new(&data);
|
||||||
|
let _ = u64::decode(&rlp).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_stream_u256_value(b: &mut Bencher) {
|
||||||
|
b.iter( || {
|
||||||
|
//u256
|
||||||
|
let mut stream = RlpStream::new();
|
||||||
|
stream.append(&U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap());
|
||||||
|
let _ = stream.out().unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_decode_u256_value(b: &mut Bencher) {
|
||||||
|
b.iter( || {
|
||||||
|
// u256
|
||||||
|
let data = vec![0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
|
||||||
|
0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0];
|
||||||
|
let rlp = Rlp::new(&data);
|
||||||
|
let _ = U256::decode(&rlp).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_stream_nested_empty_lists(b: &mut Bencher) {
|
fn bench_stream_nested_empty_lists(b: &mut Bencher) {
|
||||||
b.iter( || {
|
b.iter( || {
|
||||||
@ -41,17 +75,17 @@ fn bench_decode_nested_empty_lists(b: &mut Bencher) {
|
|||||||
// [ [], [[]], [ [], [[]] ] ]
|
// [ [], [[]], [ [], [[]] ] ]
|
||||||
let data = vec![0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0];
|
let data = vec![0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0];
|
||||||
let rlp = Rlp::new(&data);
|
let rlp = Rlp::new(&data);
|
||||||
let v0: Vec<u8> = Decodable::decode(&rlp.at(0).unwrap()).unwrap();
|
let _v0: Vec<u8> = Decodable::decode(&rlp.at(0).unwrap()).unwrap();
|
||||||
let v1: Vec<Vec<u8>> = Decodable::decode(&rlp.at(1).unwrap()).unwrap();
|
let _v1: Vec<Vec<u8>> = Decodable::decode(&rlp.at(1).unwrap()).unwrap();
|
||||||
let v2a: Vec<u8> = Decodable::decode(&rlp.at(2).unwrap().at(0).unwrap()).unwrap();
|
let _v2a: Vec<u8> = Decodable::decode(&rlp.at(2).unwrap().at(0).unwrap()).unwrap();
|
||||||
let v2b: Vec<Vec<u8>> = Decodable::decode(&rlp.at(2).unwrap().at(1).unwrap()).unwrap();
|
let _v2b: Vec<Vec<u8>> = Decodable::decode(&rlp.at(2).unwrap().at(1).unwrap()).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_stream_1000_empty_lists(b: &mut Bencher) {
|
fn bench_stream_1000_empty_lists(b: &mut Bencher) {
|
||||||
b.iter( || {
|
b.iter( || {
|
||||||
let mut stream = RlpStream::new();
|
let mut stream = RlpStream::new_list(1000);
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
stream.append_list(0);
|
stream.append_list(0);
|
||||||
}
|
}
|
||||||
|
37
src/bytes.rs
37
src/bytes.rs
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
|
use uint::{U128, U256};
|
||||||
|
|
||||||
/// TODO: optimise some conversations
|
/// TODO: optimise some conversations
|
||||||
pub trait ToBytes {
|
pub trait ToBytes {
|
||||||
@ -59,6 +60,7 @@ impl ToBytes for u64 {
|
|||||||
fn to_bytes(&self) -> Vec<u8> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
let mut res= vec![];
|
let mut res= vec![];
|
||||||
let count = self.to_bytes_len();
|
let count = self.to_bytes_len();
|
||||||
|
res.reserve(count);
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
let j = count - 1 - i;
|
let j = count - 1 - i;
|
||||||
res.push((*self >> (j * 8)) as u8);
|
res.push((*self >> (j * 8)) as u8);
|
||||||
@ -82,6 +84,27 @@ impl_map_to_bytes!(usize, u64);
|
|||||||
impl_map_to_bytes!(u16, u64);
|
impl_map_to_bytes!(u16, u64);
|
||||||
impl_map_to_bytes!(u32, u64);
|
impl_map_to_bytes!(u32, u64);
|
||||||
|
|
||||||
|
macro_rules! impl_uint_to_bytes {
|
||||||
|
($name: ident) => {
|
||||||
|
impl ToBytes for $name {
|
||||||
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
let mut res= vec![];
|
||||||
|
let count = self.to_bytes_len();
|
||||||
|
res.reserve(count);
|
||||||
|
for i in 0..count {
|
||||||
|
let j = count - 1 - i;
|
||||||
|
res.push(self.byte(j));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_uint_to_bytes!(U256);
|
||||||
|
impl_uint_to_bytes!(U128);
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum FromBytesError {
|
pub enum FromBytesError {
|
||||||
UnexpectedEnd
|
UnexpectedEnd
|
||||||
@ -101,6 +124,7 @@ pub type FromBytesResult<T> = Result<T, FromBytesError>;
|
|||||||
|
|
||||||
/// implements "Sized", so the compiler can deducate the size
|
/// implements "Sized", so the compiler can deducate the size
|
||||||
/// of the return type
|
/// of the return type
|
||||||
|
/// TODO: check size of bytes before conversation and return appropriate error
|
||||||
pub trait FromBytes: Sized {
|
pub trait FromBytes: Sized {
|
||||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
|
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
|
||||||
}
|
}
|
||||||
@ -149,3 +173,16 @@ macro_rules! impl_map_from_bytes {
|
|||||||
impl_map_from_bytes!(usize, u64);
|
impl_map_from_bytes!(usize, u64);
|
||||||
impl_map_from_bytes!(u16, u64);
|
impl_map_from_bytes!(u16, u64);
|
||||||
impl_map_from_bytes!(u32, u64);
|
impl_map_from_bytes!(u32, u64);
|
||||||
|
|
||||||
|
macro_rules! impl_uint_from_bytes {
|
||||||
|
($name: ident) => {
|
||||||
|
impl FromBytes for $name {
|
||||||
|
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
|
||||||
|
Ok($name::from(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_uint_from_bytes!(U256);
|
||||||
|
impl_uint_from_bytes!(U128);
|
||||||
|
32
src/rlp.rs
32
src/rlp.rs
@ -522,8 +522,10 @@ impl Encoder for BasicEncoder {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{fmt, cmp};
|
use std::{fmt, cmp};
|
||||||
|
use std::str::FromStr;
|
||||||
use rlp;
|
use rlp;
|
||||||
use rlp::{Rlp, RlpStream, Decodable};
|
use rlp::{Rlp, RlpStream, Decodable};
|
||||||
|
use uint::U256;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rlp_at() {
|
fn rlp_at() {
|
||||||
@ -643,6 +645,21 @@ mod tests {
|
|||||||
run_encode_tests(tests);
|
run_encode_tests(tests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn encode_u256() {
|
||||||
|
let tests = vec![
|
||||||
|
ETestPair(U256::from(0u64), vec![0x80u8]),
|
||||||
|
ETestPair(U256::from(0x1000000u64), vec![0x84, 0x01, 0x00, 0x00, 0x00]),
|
||||||
|
ETestPair(U256::from(0xffffffffu64), vec![0x84, 0xff, 0xff, 0xff, 0xff]),
|
||||||
|
ETestPair(U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap(),
|
||||||
|
vec![0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
|
||||||
|
0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0])
|
||||||
|
];
|
||||||
|
run_encode_tests(tests);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encode_str() {
|
fn encode_str() {
|
||||||
let tests = vec![
|
let tests = vec![
|
||||||
@ -769,6 +786,21 @@ mod tests {
|
|||||||
run_decode_tests(tests);
|
run_decode_tests(tests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_u256() {
|
||||||
|
let tests = vec![
|
||||||
|
DTestPair(U256::from(0u64), vec![0x80u8]),
|
||||||
|
DTestPair(U256::from(0x1000000u64), vec![0x84, 0x01, 0x00, 0x00, 0x00]),
|
||||||
|
DTestPair(U256::from(0xffffffffu64), vec![0x84, 0xff, 0xff, 0xff, 0xff]),
|
||||||
|
DTestPair(U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap(),
|
||||||
|
vec![0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
|
||||||
|
0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0])
|
||||||
|
];
|
||||||
|
run_decode_tests(tests);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_str() {
|
fn decode_str() {
|
||||||
let tests = vec![
|
let tests = vec![
|
||||||
|
19
src/uint.rs
19
src/uint.rs
@ -180,6 +180,12 @@ macro_rules! construct_uint {
|
|||||||
arr[index / 64] & (1 << (index % 64)) != 0
|
arr[index / 64] & (1 << (index % 64)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn byte(&self, index: usize) -> u8 {
|
||||||
|
let &$name(ref arr) = self;
|
||||||
|
(arr[index / 8] >> ((index % 8)) * 8) as u8
|
||||||
|
}
|
||||||
|
|
||||||
/// Multiplication by u32
|
/// Multiplication by u32
|
||||||
fn mul_u32(self, other: u32) -> $name {
|
fn mul_u32(self, other: u32) -> $name {
|
||||||
let $name(ref arr) = self;
|
let $name(ref arr) = self;
|
||||||
@ -227,7 +233,6 @@ macro_rules! construct_uint {
|
|||||||
type Err = FromHexError;
|
type Err = FromHexError;
|
||||||
|
|
||||||
fn from_str(value: &str) -> Result<$name, Self::Err> {
|
fn from_str(value: &str) -> Result<$name, Self::Err> {
|
||||||
println!("{}", value);
|
|
||||||
let bytes: &[u8] = &try!(value.from_hex());
|
let bytes: &[u8] = &try!(value.from_hex());
|
||||||
Ok(From::from(bytes))
|
Ok(From::from(bytes))
|
||||||
}
|
}
|
||||||
@ -507,6 +512,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn uint256_bits_test() {
|
pub fn uint256_bits_test() {
|
||||||
|
assert_eq!(U256::from(0u64).bits(), 0);
|
||||||
assert_eq!(U256::from(255u64).bits(), 8);
|
assert_eq!(U256::from(255u64).bits(), 8);
|
||||||
assert_eq!(U256::from(256u64).bits(), 9);
|
assert_eq!(U256::from(256u64).bits(), 9);
|
||||||
assert_eq!(U256::from(300u64).bits(), 9);
|
assert_eq!(U256::from(300u64).bits(), 9);
|
||||||
@ -523,11 +529,22 @@ mod tests {
|
|||||||
assert_eq!(shl.bits(), 0);
|
assert_eq!(shl.bits(), 0);
|
||||||
|
|
||||||
//// Bit set check
|
//// Bit set check
|
||||||
|
//// 01010
|
||||||
assert!(!U256::from(10u8).bit(0));
|
assert!(!U256::from(10u8).bit(0));
|
||||||
assert!(U256::from(10u8).bit(1));
|
assert!(U256::from(10u8).bit(1));
|
||||||
assert!(!U256::from(10u8).bit(2));
|
assert!(!U256::from(10u8).bit(2));
|
||||||
assert!(U256::from(10u8).bit(3));
|
assert!(U256::from(10u8).bit(3));
|
||||||
assert!(!U256::from(10u8).bit(4));
|
assert!(!U256::from(10u8).bit(4));
|
||||||
|
|
||||||
|
//// byte check
|
||||||
|
assert_eq!(U256::from(10u8).byte(0), 10);
|
||||||
|
assert_eq!(U256::from(0xffu64).byte(0), 0xff);
|
||||||
|
assert_eq!(U256::from(0xffu64).byte(1), 0);
|
||||||
|
assert_eq!(U256::from(0x01ffu64).byte(0), 0xff);
|
||||||
|
assert_eq!(U256::from(0x01ffu64).byte(1), 0x1);
|
||||||
|
assert_eq!(U256([0u64, 0xfc, 0, 0]).byte(8), 0xfc);
|
||||||
|
assert_eq!(U256([0u64, 0, 0, u64::max_value()]).byte(31), 0xff);
|
||||||
|
assert_eq!(U256([0u64, 0, 0, (u64::max_value() >> 8) + 1]).byte(31), 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user