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