Merge pull request #22 from paritytech/refactor/rlp-optionally-independent-of-ethereum-types

[rlp] make it possible to use rlp without pulling in ethereum-types
This commit is contained in:
Andronik Ordian 2018-08-20 12:23:17 +03:00 committed by GitHub
commit abe18ea03c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 99 additions and 77 deletions

View File

@ -3,11 +3,18 @@ description = "Recursive-length prefix encoding, decoding, and compression"
repository = "https://github.com/paritytech/parity"
license = "MIT/Apache-2.0"
name = "rlp"
version = "0.2.1"
version = "0.2.2"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
byteorder = "1.0"
elastic-array = "0.10"
ethereum-types = "0.3"
rustc-hex = "1.0"
ethereum-types = { version = "0.3", optional = true }
rustc-hex = {version = "2.0", default-features = false }
[dev-dependencies]
hex-literal = "0.1"
[features]
default = ["ethereum"]
ethereum = ["ethereum-types"]

View File

@ -6,9 +6,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{cmp, mem, str};
use std::{mem, str};
use byteorder::{ByteOrder, BigEndian};
use bigint::{U128, U256, H64, H128, H160, H256, H512, H520, Bloom};
use traits::{Encodable, Decodable};
use stream::RlpStream;
use {Rlp, DecoderError};
@ -179,87 +178,94 @@ impl Decodable for usize {
}
}
macro_rules! impl_encodable_for_hash {
($name: ident) => {
impl Encodable for $name {
fn rlp_append(&self, s: &mut RlpStream) {
s.encoder().encode_value(self);
#[cfg(feature = "ethereum")]
mod ethereum_traits {
use super::*;
use std::cmp;
use ethereum_types::{U128, U256, H64, H128, H160, H256, H512, H520, Bloom};
macro_rules! impl_encodable_for_hash {
($name: ident) => {
impl Encodable for $name {
fn rlp_append(&self, s: &mut RlpStream) {
s.encoder().encode_value(self);
}
}
}
}
}
macro_rules! impl_decodable_for_hash {
($name: ident, $size: expr) => {
impl Decodable for $name {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) {
cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort),
cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig),
cmp::Ordering::Equal => {
let mut t = [0u8; $size];
t.copy_from_slice(bytes);
Ok($name(t))
}
})
macro_rules! impl_decodable_for_hash {
($name: ident, $size: expr) => {
impl Decodable for $name {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) {
cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort),
cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig),
cmp::Ordering::Equal => {
let mut t = [0u8; $size];
t.copy_from_slice(bytes);
Ok($name(t))
}
})
}
}
}
}
}
impl_encodable_for_hash!(H64);
impl_encodable_for_hash!(H128);
impl_encodable_for_hash!(H160);
impl_encodable_for_hash!(H256);
impl_encodable_for_hash!(H512);
impl_encodable_for_hash!(H520);
impl_encodable_for_hash!(Bloom);
impl_decodable_for_hash!(H64, 8);
impl_decodable_for_hash!(H128, 16);
impl_decodable_for_hash!(H160, 20);
impl_decodable_for_hash!(H256, 32);
impl_decodable_for_hash!(H512, 64);
impl_decodable_for_hash!(H520, 65);
impl_decodable_for_hash!(Bloom, 256);
macro_rules! impl_encodable_for_uint {
($name: ident, $size: expr) => {
impl Encodable for $name {
fn rlp_append(&self, s: &mut RlpStream) {
let leading_empty_bytes = $size - (self.bits() + 7) / 8;
let mut buffer = [0u8; $size];
self.to_big_endian(&mut buffer);
s.encoder().encode_value(&buffer[leading_empty_bytes..]);
macro_rules! impl_encodable_for_uint {
($name: ident, $size: expr) => {
impl Encodable for $name {
fn rlp_append(&self, s: &mut RlpStream) {
let leading_empty_bytes = $size - (self.bits() + 7) / 8;
let mut buffer = [0u8; $size];
self.to_big_endian(&mut buffer);
s.encoder().encode_value(&buffer[leading_empty_bytes..]);
}
}
}
}
}
macro_rules! impl_decodable_for_uint {
($name: ident, $size: expr) => {
impl Decodable for $name {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
rlp.decoder().decode_value(|bytes| {
if !bytes.is_empty() && bytes[0] == 0 {
Err(DecoderError::RlpInvalidIndirection)
} else if bytes.len() <= $size {
Ok($name::from(bytes))
} else {
Err(DecoderError::RlpIsTooBig)
}
})
macro_rules! impl_decodable_for_uint {
($name: ident, $size: expr) => {
impl Decodable for $name {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
rlp.decoder().decode_value(|bytes| {
if !bytes.is_empty() && bytes[0] == 0 {
Err(DecoderError::RlpInvalidIndirection)
} else if bytes.len() <= $size {
Ok($name::from(bytes))
} else {
Err(DecoderError::RlpIsTooBig)
}
})
}
}
}
}
impl_encodable_for_hash!(H64);
impl_encodable_for_hash!(H128);
impl_encodable_for_hash!(H160);
impl_encodable_for_hash!(H256);
impl_encodable_for_hash!(H512);
impl_encodable_for_hash!(H520);
impl_encodable_for_hash!(Bloom);
impl_decodable_for_hash!(H64, 8);
impl_decodable_for_hash!(H128, 16);
impl_decodable_for_hash!(H160, 20);
impl_decodable_for_hash!(H256, 32);
impl_decodable_for_hash!(H512, 64);
impl_decodable_for_hash!(H520, 65);
impl_decodable_for_hash!(Bloom, 256);
impl_encodable_for_uint!(U256, 32);
impl_encodable_for_uint!(U128, 16);
impl_decodable_for_uint!(U256, 32);
impl_decodable_for_uint!(U128, 16);
}
impl_encodable_for_uint!(U256, 32);
impl_encodable_for_uint!(U128, 16);
impl_decodable_for_uint!(U256, 32);
impl_decodable_for_uint!(U128, 16);
impl<'a> Encodable for &'a str {
fn rlp_append(&self, s: &mut RlpStream) {
s.encoder().encode_value(self.as_bytes());

View File

@ -33,9 +33,13 @@
//! * You don't want to decode whole rlp at once.
extern crate byteorder;
extern crate ethereum_types as bigint;
#[cfg(feature = "ethereum")]
extern crate ethereum_types;
extern crate elastic_array;
extern crate rustc_hex;
#[cfg(test)]
#[macro_use]
extern crate hex_literal;
mod traits;
mod error;

View File

@ -118,7 +118,7 @@ impl<'a> fmt::Display for Rlp<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.prototype() {
Ok(Prototype::Null) => write!(f, "null"),
Ok(Prototype::Data(_)) => write!(f, "\"0x{}\"", self.data().unwrap().to_hex()),
Ok(Prototype::Data(_)) => write!(f, "\"0x{}\"", self.data().unwrap().to_hex::<String>()),
Ok(Prototype::List(len)) => {
write!(f, "[")?;
for i in 0..len-1 {
@ -389,8 +389,7 @@ mod tests {
#[test]
fn test_rlp_display() {
use rustc_hex::FromHex;
let data = "f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".from_hex().unwrap();
let data = hex!("f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
let rlp = Rlp::new(&data);
assert_eq!(format!("{}", rlp), "[\"0x05\", \"0x010efbef67941f79b2\", \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\", \"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\"]");
}

View File

@ -6,11 +6,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate ethereum_types as bigint;
#[cfg(feature = "ethereum")]
extern crate ethereum_types;
extern crate rlp;
use std::{fmt, cmp};
use bigint::{U256, H160};
#[cfg(feature = "ethereum")]
use ethereum_types::{U256, H160};
use rlp::{Encodable, Decodable, Rlp, RlpStream, DecoderError};
#[test]
@ -130,6 +132,7 @@ fn encode_u64() {
run_encode_tests(tests);
}
#[cfg(feature = "ethereum")]
#[test]
fn encode_u256() {
let tests = vec![ETestPair(U256::from(0u64), vec![0x80u8]),
@ -162,6 +165,7 @@ fn encode_str() {
run_encode_tests(tests);
}
#[cfg(feature = "ethereum")]
#[test]
fn encode_address() {
let tests = vec![
@ -272,6 +276,7 @@ fn decode_untrusted_u64() {
run_decode_tests(tests);
}
#[cfg(feature = "ethereum")]
#[test]
fn decode_untrusted_u256() {
let tests = vec![DTestPair(U256::from(0u64), vec![0x80u8]),
@ -306,6 +311,7 @@ fn decode_untrusted_str() {
run_decode_tests(tests);
}
#[cfg(feature = "ethereum")]
#[test]
fn decode_untrusted_address() {
let tests = vec![

View File

@ -8,8 +8,8 @@ license = "GPL-3.0"
[dependencies]
elastic-array = "0.10"
hashdb = { version = "0.2", path = "../hashdb" }
rlp = { version = "0.2.1", path = "../rlp" }
hashdb = { version = "0.2", path = "../hashdb", default_features = false }
rlp = { version = "0.2", path = "../rlp", default_features = false }
[dev-dependencies]
trie-standardmap = { version = "0.1", path = "../trie-standardmap" }