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" repository = "https://github.com/paritytech/parity"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
name = "rlp" name = "rlp"
version = "0.2.1" version = "0.2.2"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
byteorder = "1.0" byteorder = "1.0"
elastic-array = "0.10" elastic-array = "0.10"
ethereum-types = "0.3" ethereum-types = { version = "0.3", optional = true }
rustc-hex = "1.0" 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 // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::{cmp, mem, str}; use std::{mem, str};
use byteorder::{ByteOrder, BigEndian}; use byteorder::{ByteOrder, BigEndian};
use bigint::{U128, U256, H64, H128, H160, H256, H512, H520, Bloom};
use traits::{Encodable, Decodable}; use traits::{Encodable, Decodable};
use stream::RlpStream; use stream::RlpStream;
use {Rlp, DecoderError}; use {Rlp, DecoderError};
@ -179,87 +178,94 @@ impl Decodable for usize {
} }
} }
macro_rules! impl_encodable_for_hash { #[cfg(feature = "ethereum")]
($name: ident) => { mod ethereum_traits {
impl Encodable for $name { use super::*;
fn rlp_append(&self, s: &mut RlpStream) { use std::cmp;
s.encoder().encode_value(self); 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 { macro_rules! impl_decodable_for_hash {
($name: ident, $size: expr) => { ($name: ident, $size: expr) => {
impl Decodable for $name { impl Decodable for $name {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> { fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) { rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) {
cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort), cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort),
cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig), cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig),
cmp::Ordering::Equal => { cmp::Ordering::Equal => {
let mut t = [0u8; $size]; let mut t = [0u8; $size];
t.copy_from_slice(bytes); t.copy_from_slice(bytes);
Ok($name(t)) Ok($name(t))
} }
}) })
}
} }
} }
} }
}
impl_encodable_for_hash!(H64); macro_rules! impl_encodable_for_uint {
impl_encodable_for_hash!(H128); ($name: ident, $size: expr) => {
impl_encodable_for_hash!(H160); impl Encodable for $name {
impl_encodable_for_hash!(H256); fn rlp_append(&self, s: &mut RlpStream) {
impl_encodable_for_hash!(H512); let leading_empty_bytes = $size - (self.bits() + 7) / 8;
impl_encodable_for_hash!(H520); let mut buffer = [0u8; $size];
impl_encodable_for_hash!(Bloom); self.to_big_endian(&mut buffer);
s.encoder().encode_value(&buffer[leading_empty_bytes..]);
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_decodable_for_uint { macro_rules! impl_decodable_for_uint {
($name: ident, $size: expr) => { ($name: ident, $size: expr) => {
impl Decodable for $name { impl Decodable for $name {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> { fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
rlp.decoder().decode_value(|bytes| { rlp.decoder().decode_value(|bytes| {
if !bytes.is_empty() && bytes[0] == 0 { if !bytes.is_empty() && bytes[0] == 0 {
Err(DecoderError::RlpInvalidIndirection) Err(DecoderError::RlpInvalidIndirection)
} else if bytes.len() <= $size { } else if bytes.len() <= $size {
Ok($name::from(bytes)) Ok($name::from(bytes))
} else { } else {
Err(DecoderError::RlpIsTooBig) 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 { impl<'a> Encodable for &'a str {
fn rlp_append(&self, s: &mut RlpStream) { fn rlp_append(&self, s: &mut RlpStream) {
s.encoder().encode_value(self.as_bytes()); s.encoder().encode_value(self.as_bytes());

View File

@ -33,9 +33,13 @@
//! * You don't want to decode whole rlp at once. //! * You don't want to decode whole rlp at once.
extern crate byteorder; extern crate byteorder;
extern crate ethereum_types as bigint; #[cfg(feature = "ethereum")]
extern crate ethereum_types;
extern crate elastic_array; extern crate elastic_array;
extern crate rustc_hex; extern crate rustc_hex;
#[cfg(test)]
#[macro_use]
extern crate hex_literal;
mod traits; mod traits;
mod error; 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> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.prototype() { match self.prototype() {
Ok(Prototype::Null) => write!(f, "null"), 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)) => { Ok(Prototype::List(len)) => {
write!(f, "[")?; write!(f, "[")?;
for i in 0..len-1 { for i in 0..len-1 {
@ -389,8 +389,7 @@ mod tests {
#[test] #[test]
fn test_rlp_display() { fn test_rlp_display() {
use rustc_hex::FromHex; let data = hex!("f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
let data = "f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".from_hex().unwrap();
let rlp = Rlp::new(&data); let rlp = Rlp::new(&data);
assert_eq!(format!("{}", rlp), "[\"0x05\", \"0x010efbef67941f79b2\", \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\", \"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\"]"); assert_eq!(format!("{}", rlp), "[\"0x05\", \"0x010efbef67941f79b2\", \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\", \"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\"]");
} }

View File

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

View File

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