rlp encoding and decoding u256

This commit is contained in:
debris 2015-11-26 15:00:17 +01:00
parent f95265d6ae
commit 4fcf044edd
3 changed files with 85 additions and 0 deletions

View File

@ -8,6 +8,7 @@
use std::fmt;
use std::error::Error as StdError;
use uint::{U128, U256};
/// TODO: optimise some conversations
pub trait ToBytes {
@ -82,6 +83,26 @@ impl_map_to_bytes!(usize, u64);
impl_map_to_bytes!(u16, 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();
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)]
pub enum FromBytesError {
UnexpectedEnd
@ -101,6 +122,7 @@ pub type FromBytesResult<T> = Result<T, FromBytesError>;
/// implements "Sized", so the compiler can deducate the size
/// of the return type
/// TODO: check size of bytes before conversation and return appropriate error
pub trait FromBytes: Sized {
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
}
@ -149,3 +171,16 @@ macro_rules! impl_map_from_bytes {
impl_map_from_bytes!(usize, u64);
impl_map_from_bytes!(u16, 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);

View File

@ -522,8 +522,10 @@ impl Encoder for BasicEncoder {
#[cfg(test)]
mod tests {
use std::{fmt, cmp};
use std::str::FromStr;
use rlp;
use rlp::{Rlp, RlpStream, Decodable};
use uint::U256;
#[test]
fn rlp_at() {
@ -643,6 +645,21 @@ mod 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]
fn encode_str() {
let tests = vec![
@ -769,6 +786,21 @@ mod 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]
fn decode_str() {
let tests = vec![

View File

@ -180,6 +180,12 @@ macro_rules! construct_uint {
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
fn mul_u32(self, other: u32) -> $name {
let $name(ref arr) = self;
@ -507,6 +513,7 @@ mod tests {
#[test]
pub fn uint256_bits_test() {
assert_eq!(U256::from(0u64).bits(), 0);
assert_eq!(U256::from(255u64).bits(), 8);
assert_eq!(U256::from(256u64).bits(), 9);
assert_eq!(U256::from(300u64).bits(), 9);
@ -523,11 +530,22 @@ mod tests {
assert_eq!(shl.bits(), 0);
//// Bit set check
//// 01010
assert!(!U256::from(10u8).bit(0));
assert!(U256::from(10u8).bit(1));
assert!(!U256::from(10u8).bit(2));
assert!(U256::from(10u8).bit(3));
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]