rlp_derive (#6125)

* rlp_derive

* RlpEncodableWrapper, RlpDecodableWrapper

* use rlp_derive in parity

* fixed broken transaction Action serialization
This commit is contained in:
Marek Kotewicz 2017-08-20 06:01:46 +02:00 committed by Gav Wood
parent 5ed14c1064
commit 407c8c3fb9
23 changed files with 429 additions and 751 deletions

20
Cargo.lock generated
View File

@ -301,6 +301,7 @@ dependencies = [
"ethcore-util 1.8.0",
"ethjson 0.1.0",
"rlp 0.2.0",
"rlp_derive 0.1.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -526,6 +527,7 @@ dependencies = [
"price-info 1.7.0",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0",
"rlp_derive 0.1.0",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -652,6 +654,7 @@ dependencies = [
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0",
"rlp_derive 0.1.0",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2305,7 +2308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "0.3.10"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -2396,6 +2399,15 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rlp_derive"
version = "0.1.0"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocksdb"
version = "0.4.5"
@ -2588,7 +2600,7 @@ name = "serde_derive"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2730,7 +2742,7 @@ name = "syn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -3384,7 +3396,7 @@ dependencies = [
"checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd"
"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
"checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a"
"checksum quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6732e32663c9c271bfc7c1823486b471f18c47a2dbf87c066897b7b51afc83be"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
"checksum rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c83adcb08e5b922e804fe1918142b422602ef11f2fd670b0b52218cb5984a20"
"checksum rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "767d91bacddf07d442fe39257bf04fd95897d1c47c545d009f6beb03efd038f8"

View File

@ -47,6 +47,7 @@ num_cpus = "1.2"
price-info = { path = "../price-info" }
rand = "0.3"
rlp = { path = "../util/rlp" }
rlp_derive = { path = "../util/rlp_derive" }
rust-crypto = "0.2.34"
rustc-hex = "1.0"
semver = "0.6"

View File

@ -21,6 +21,7 @@ ethcore-devtools = { path = "../../devtools" }
evm = { path = "../evm" }
vm = { path = "../vm" }
rlp = { path = "../../util/rlp" }
rlp_derive = { path = "../../util/rlp_derive" }
time = "0.1"
smallvec = "0.4"
futures = "0.1"

View File

@ -76,6 +76,8 @@ extern crate futures;
extern crate itertools;
extern crate rand;
extern crate rlp;
#[macro_use]
extern crate rlp_derive;
extern crate serde;
extern crate smallvec;
extern crate stats;

View File

@ -650,7 +650,7 @@ pub mod header {
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
/// Potentially incomplete headers request.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Start block.
pub start: Field<HashOrNumber>,
@ -662,27 +662,6 @@ pub mod header {
pub reverse: bool,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
start: rlp.val_at(0)?,
skip: rlp.val_at(1)?,
max: rlp.val_at(2)?,
reverse: rlp.val_at(3)?
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4)
.append(&self.start)
.append(&self.skip)
.append(&self.max)
.append(&self.reverse);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@ -784,26 +763,12 @@ pub mod header_proof {
use util::{Bytes, U256, H256};
/// Potentially incomplete header proof request.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block number.
pub num: Field<u64>,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
num: rlp.val_at(0)?,
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(1).append(&self.num);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@ -889,30 +854,15 @@ pub mod header_proof {
/// Request and response for transaction index.
pub mod transaction_index {
use super::{Field, NoSuchOutput, OutputKind, Output};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::H256;
/// Potentially incomplete transaction index request.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Transaction hash to get index for.
pub hash: Field<H256>,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
hash: rlp.val_at(0)?,
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(1).append(&self.hash);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@ -959,7 +909,7 @@ pub mod transaction_index {
}
/// The output of a request for transaction index.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Response {
/// Block number.
pub num: u64,
@ -976,55 +926,21 @@ pub mod transaction_index {
f(1, Output::Hash(self.hash));
}
}
impl Decodable for Response {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Response {
num: rlp.val_at(0)?,
hash: rlp.val_at(1)?,
index: rlp.val_at(2)?,
})
}
}
impl Encodable for Response {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3)
.append(&self.num)
.append(&self.hash)
.append(&self.index);
}
}
}
/// Request and response for block receipts
pub mod block_receipts {
use super::{Field, NoSuchOutput, OutputKind, Output};
use ethcore::receipt::Receipt;
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::H256;
/// Potentially incomplete block receipts request.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block hash to get receipts for.
pub hash: Field<H256>,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
hash: rlp.val_at(0)?,
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(1).append(&self.hash);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@ -1068,7 +984,7 @@ pub mod block_receipts {
}
/// The output of a request for block receipts.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct Response {
/// The block receipts.
pub receipts: Vec<Receipt>
@ -1078,20 +994,6 @@ pub mod block_receipts {
/// Fill reusable outputs by providing them to the function.
fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
}
impl Decodable for Response {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Response {
receipts: rlp.as_list()?,
})
}
}
impl Encodable for Response {
fn rlp_append(&self, s: &mut RlpStream) {
s.append_list(&self.receipts);
}
}
}
/// Request and response for a block body
@ -1102,26 +1004,12 @@ pub mod block_body {
use util::H256;
/// Potentially incomplete block body request.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block hash to get receipts for.
pub hash: Field<H256>,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
hash: rlp.val_at(0)?,
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(1).append(&self.hash);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@ -1201,11 +1089,10 @@ pub mod block_body {
/// A request for an account proof.
pub mod account {
use super::{Field, NoSuchOutput, OutputKind, Output};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::{Bytes, U256, H256};
/// Potentially incomplete request for an account proof.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block hash to request state proof for.
pub block_hash: Field<H256>,
@ -1213,23 +1100,6 @@ pub mod account {
pub address_hash: Field<H256>,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
block_hash: rlp.val_at(0)?,
address_hash: rlp.val_at(1)?,
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2)
.append(&self.block_hash)
.append(&self.address_hash);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@ -1292,7 +1162,7 @@ pub mod account {
}
/// The output of a request for an account state proof.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Response {
/// Inclusion/exclusion proof
pub proof: Vec<Bytes>,
@ -1313,39 +1183,15 @@ pub mod account {
f(1, Output::Hash(self.storage_root));
}
}
impl Decodable for Response {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Response {
proof: rlp.list_at(0)?,
nonce: rlp.val_at(1)?,
balance: rlp.val_at(2)?,
code_hash: rlp.val_at(3)?,
storage_root: rlp.val_at(4)?
})
}
}
impl Encodable for Response {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(5)
.append_list::<Vec<u8>,_>(&self.proof[..])
.append(&self.nonce)
.append(&self.balance)
.append(&self.code_hash)
.append(&self.storage_root);
}
}
}
/// A request for a storage proof.
pub mod storage {
use super::{Field, NoSuchOutput, OutputKind, Output};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::{Bytes, H256};
/// Potentially incomplete request for an storage proof.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block hash to request state proof for.
pub block_hash: Field<H256>,
@ -1355,25 +1201,6 @@ pub mod storage {
pub key_hash: Field<H256>,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
block_hash: rlp.val_at(0)?,
address_hash: rlp.val_at(1)?,
key_hash: rlp.val_at(2)?,
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3)
.append(&self.block_hash)
.append(&self.address_hash)
.append(&self.key_hash);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@ -1450,7 +1277,7 @@ pub mod storage {
}
/// The output of a request for an account state proof.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Response {
/// Inclusion/exclusion proof
pub proof: Vec<Bytes>,
@ -1464,33 +1291,15 @@ pub mod storage {
f(0, Output::Hash(self.value));
}
}
impl Decodable for Response {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Response {
proof: rlp.list_at(0)?,
value: rlp.val_at(1)?,
})
}
}
impl Encodable for Response {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2)
.append_list::<Vec<u8>,_>(&self.proof[..])
.append(&self.value);
}
}
}
/// A request for contract code.
pub mod contract_code {
use super::{Field, NoSuchOutput, OutputKind, Output};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::{Bytes, H256};
/// Potentially incomplete contract code request.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// The block hash to request the state for.
pub block_hash: Field<H256>,
@ -1498,23 +1307,6 @@ pub mod contract_code {
pub code_hash: Field<H256>,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
block_hash: rlp.val_at(0)?,
code_hash: rlp.val_at(1)?,
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2)
.append(&self.block_hash)
.append(&self.code_hash);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@ -1573,7 +1365,7 @@ pub mod contract_code {
}
/// The output of a request for
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct Response {
/// The requested code.
pub code: Bytes,
@ -1583,21 +1375,6 @@ pub mod contract_code {
/// Fill reusable outputs by providing them to the function.
fn fill_outputs<F>(&self, _: F) where F: FnMut(usize, Output) {}
}
impl Decodable for Response {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Response {
code: rlp.as_val()?,
})
}
}
impl Encodable for Response {
fn rlp_append(&self, s: &mut RlpStream) {
s.append(&self.code);
}
}
}
/// A request for proof of execution.
@ -1608,7 +1385,7 @@ pub mod execution {
use util::{Bytes, Address, U256, H256, DBValue};
/// Potentially incomplete execution proof request.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// The block hash to request the state for.
pub block_hash: Field<H256>,
@ -1626,38 +1403,6 @@ pub mod execution {
pub data: Bytes,
}
impl Decodable for Incomplete {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
block_hash: rlp.val_at(0)?,
from: rlp.val_at(1)?,
action: rlp.val_at(2)?,
gas: rlp.val_at(3)?,
gas_price: rlp.val_at(4)?,
value: rlp.val_at(5)?,
data: rlp.val_at(6)?,
})
}
}
impl Encodable for Incomplete {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(7)
.append(&self.block_hash)
.append(&self.from);
match self.action {
Action::Create => s.append_empty_data(),
Action::Call(ref addr) => s.append(addr),
};
s.append(&self.gas)
.append(&self.gas_price)
.append(&self.value)
.append(&self.data);
}
}
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;

View File

@ -25,11 +25,9 @@ use engines::epoch::{Transition as EpochTransition};
use header::BlockNumber;
use receipt::Receipt;
use rlp::*;
use util::*;
use util::{HeapSizeOf, H256, H264, U256};
use util::kvdb::PREFIX_LEN as DB_PREFIX_LEN;
/// Represents index of extra data in database
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
pub enum ExtrasIndex {
@ -184,7 +182,7 @@ impl Key<EpochTransitions> for u64 {
}
/// Familial details concerning a block
#[derive(Debug, Clone)]
#[derive(Debug, Clone, RlpEncodable, RlpDecodable)]
pub struct BlockDetails {
/// Block number
pub number: BlockNumber,
@ -202,30 +200,8 @@ impl HeapSizeOf for BlockDetails {
}
}
impl Decodable for BlockDetails {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let details = BlockDetails {
number: rlp.val_at(0)?,
total_difficulty: rlp.val_at(1)?,
parent: rlp.val_at(2)?,
children: rlp.list_at(3)?,
};
Ok(details)
}
}
impl Encodable for BlockDetails {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4);
s.append(&self.number);
s.append(&self.total_difficulty);
s.append(&self.parent);
s.append_list(&self.children);
}
}
/// Represents address of certain transaction within block
#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Clone, RlpEncodable, RlpDecodable)]
pub struct TransactionAddress {
/// Block hash
pub block_hash: H256,
@ -237,27 +213,8 @@ impl HeapSizeOf for TransactionAddress {
fn heap_size_of_children(&self) -> usize { 0 }
}
impl Decodable for TransactionAddress {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let tx_address = TransactionAddress {
block_hash: rlp.val_at(0)?,
index: rlp.val_at(1)?,
};
Ok(tx_address)
}
}
impl Encodable for TransactionAddress {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2);
s.append(&self.block_hash);
s.append(&self.index);
}
}
/// Contains all block receipts.
#[derive(Clone)]
#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct BlockReceipts {
pub receipts: Vec<Receipt>,
}
@ -270,20 +227,6 @@ impl BlockReceipts {
}
}
impl Decodable for BlockReceipts {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(BlockReceipts {
receipts: rlp.as_list()?,
})
}
}
impl Encodable for BlockReceipts {
fn rlp_append(&self, s: &mut RlpStream) {
s.append_list(&self.receipts);
}
}
impl HeapSizeOf for BlockReceipts {
fn heap_size_of_children(&self) -> usize {
self.receipts.heap_size_of_children()
@ -291,27 +234,12 @@ impl HeapSizeOf for BlockReceipts {
}
/// Candidate transitions to an epoch with specific number.
#[derive(Clone)]
#[derive(Clone, RlpEncodable, RlpDecodable)]
pub struct EpochTransitions {
pub number: u64,
pub candidates: Vec<EpochTransition>,
}
impl Encodable for EpochTransitions {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2).append(&self.number).append_list(&self.candidates);
}
}
impl Decodable for EpochTransitions {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(EpochTransitions {
number: rlp.val_at(0)?,
candidates: rlp.list_at(1)?,
})
}
}
#[cfg(test)]
mod tests {
use rlp::*;

View File

@ -15,12 +15,11 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use bloomchain as bc;
use rlp::*;
use util::HeapSizeOf;
use basic_types::LogBloom;
/// Helper structure representing bloom of the trace.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct Bloom(LogBloom);
impl From<LogBloom> for Bloom {
@ -43,18 +42,6 @@ impl Into<bc::Bloom> for Bloom {
}
}
impl Decodable for Bloom {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
LogBloom::decode(rlp).map(Bloom)
}
}
impl Encodable for Bloom {
fn rlp_append(&self, s: &mut RlpStream) {
Encodable::rlp_append(&self.0, s)
}
}
impl HeapSizeOf for Bloom {
fn heap_size_of_children(&self) -> usize {
0

View File

@ -16,14 +16,12 @@
//! Epoch verifiers and transitions.
use util::H256;
use error::Error;
use header::Header;
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::H256;
/// A full epoch transition.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, RlpEncodable, RlpDecodable)]
pub struct Transition {
/// Block hash at which the transition occurred.
pub block_hash: H256,
@ -33,46 +31,14 @@ pub struct Transition {
pub proof: Vec<u8>,
}
impl Encodable for Transition {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3)
.append(&self.block_hash)
.append(&self.block_number)
.append(&self.proof);
}
}
impl Decodable for Transition {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Transition {
block_hash: rlp.val_at(0)?,
block_number: rlp.val_at(1)?,
proof: rlp.val_at(2)?,
})
}
}
/// An epoch transition pending a finality proof.
/// Not all transitions need one.
#[derive(RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct PendingTransition {
/// "transition/epoch" proof from the engine.
pub proof: Vec<u8>,
}
impl Encodable for PendingTransition {
fn rlp_append(&self, s: &mut RlpStream) {
s.append(&self.proof);
}
}
impl Decodable for PendingTransition {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(PendingTransition {
proof: rlp.as_val()?,
})
}
}
/// Verifier for all blocks within an epoch with self-contained state.
///
/// See docs on `Engine` relating to proving functions for more details.

View File

@ -101,6 +101,9 @@ extern crate num;
extern crate price_info;
extern crate rand;
extern crate rlp;
#[macro_use]
extern crate rlp_derive;
extern crate rustc_hex;
extern crate semver;
extern crate stats;

View File

@ -27,7 +27,7 @@ use std::path::{Path, PathBuf};
use util::Bytes;
use util::hash::H256;
use rlp::{self, Encodable, RlpStream, UntrustedRlp};
use rlp::{RlpStream, UntrustedRlp};
use super::ManifestData;
@ -49,24 +49,9 @@ pub trait SnapshotWriter {
}
// (hash, len, offset)
#[derive(RlpEncodable, RlpDecodable)]
struct ChunkInfo(H256, u64, u64);
impl Encodable for ChunkInfo {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3);
s.append(&self.0).append(&self.1).append(&self.2);
}
}
impl rlp::Decodable for ChunkInfo {
fn decode(rlp: &UntrustedRlp) -> Result<Self, rlp::DecoderError> {
let hash = rlp.val_at(0)?;
let len = rlp.val_at(1)?;
let off = rlp.val_at(2)?;
Ok(ChunkInfo(hash, len, off))
}
}
/// A packed snapshot writer. This writes snapshots to a single concatenated file.
///
/// The file format is very simple and consists of three parts:

View File

@ -1,10 +1,9 @@
use bloomchain::Bloom;
use bloomchain::group::{BloomGroup, GroupPosition};
use rlp::*;
use basic_types::LogBloom;
/// Helper structure representing bloom of the trace.
#[derive(Clone)]
#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct BlockTracesBloom(LogBloom);
impl From<LogBloom> for BlockTracesBloom {
@ -28,7 +27,7 @@ impl Into<Bloom> for BlockTracesBloom {
}
/// Represents group of X consecutive blooms.
#[derive(Clone)]
#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct BlockTracesBloomGroup {
blooms: Vec<BlockTracesBloom>,
}
@ -59,34 +58,6 @@ impl Into<BloomGroup> for BlockTracesBloomGroup {
}
}
impl Decodable for BlockTracesBloom {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
LogBloom::decode(rlp).map(BlockTracesBloom)
}
}
impl Encodable for BlockTracesBloom {
fn rlp_append(&self, s: &mut RlpStream) {
Encodable::rlp_append(&self.0, s)
}
}
impl Decodable for BlockTracesBloomGroup {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let blooms = rlp.as_list()?;
let group = BlockTracesBloomGroup {
blooms: blooms
};
Ok(group)
}
}
impl Encodable for BlockTracesBloomGroup {
fn rlp_append(&self, s: &mut RlpStream) {
s.append_list(&self.blooms);
}
}
/// Represents `BloomGroup` position in database.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct TraceGroupPosition {

View File

@ -77,7 +77,7 @@ impl Decodable for FlatTrace {
}
/// Represents all traces produced by a single transaction.
#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct FlatTransactionTraces(Vec<FlatTrace>);
impl From<Vec<FlatTrace>> for FlatTransactionTraces {
@ -99,18 +99,6 @@ impl FlatTransactionTraces {
}
}
impl Encodable for FlatTransactionTraces {
fn rlp_append(&self, s: &mut RlpStream) {
s.append_list(&self.0);
}
}
impl Decodable for FlatTransactionTraces {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(FlatTransactionTraces(rlp.as_list()?))
}
}
impl Into<Vec<FlatTrace>> for FlatTransactionTraces {
fn into(self) -> Vec<FlatTrace> {
self.0
@ -118,7 +106,7 @@ impl Into<Vec<FlatTrace>> for FlatTransactionTraces {
}
/// Represents all traces produced by transactions in a single block.
#[derive(Debug, PartialEq, Clone, Default)]
#[derive(Debug, PartialEq, Clone, Default, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct FlatBlockTraces(Vec<FlatTransactionTraces>);
impl HeapSizeOf for FlatBlockTraces {
@ -140,18 +128,6 @@ impl FlatBlockTraces {
}
}
impl Encodable for FlatBlockTraces {
fn rlp_append(&self, s: &mut RlpStream) {
s.append_list(&self.0);
}
}
impl Decodable for FlatBlockTraces {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(FlatBlockTraces(rlp.as_list()?))
}
}
impl Into<Vec<FlatTransactionTraces>> for FlatBlockTraces {
fn into(self) -> Vec<FlatTransactionTraces> {
self.0

View File

@ -27,7 +27,7 @@ use evm::CallType;
use super::error::Error;
/// `Call` result.
#[derive(Debug, Clone, PartialEq, Default)]
#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct CallResult {
/// Gas used by call.
@ -36,27 +36,8 @@ pub struct CallResult {
pub output: Bytes,
}
impl Encodable for CallResult {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2);
s.append(&self.gas_used);
s.append(&self.output);
}
}
impl Decodable for CallResult {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let res = CallResult {
gas_used: rlp.val_at(0)?,
output: rlp.val_at(1)?,
};
Ok(res)
}
}
/// `Create` result.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct CreateResult {
/// Gas used by create.
@ -67,27 +48,6 @@ pub struct CreateResult {
pub address: Address,
}
impl Encodable for CreateResult {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3);
s.append(&self.gas_used);
s.append(&self.code);
s.append(&self.address);
}
}
impl Decodable for CreateResult {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let res = CreateResult {
gas_used: rlp.val_at(0)?,
code: rlp.val_at(1)?,
address: rlp.val_at(2)?,
};
Ok(res)
}
}
impl CreateResult {
/// Returns bloom.
pub fn bloom(&self) -> LogBloom {
@ -96,7 +56,7 @@ impl CreateResult {
}
/// Description of a _call_ action, either a `CALL` operation or a message transction.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Call {
/// The sending account.
@ -126,33 +86,6 @@ impl From<ActionParams> for Call {
}
}
impl Encodable for Call {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(6);
s.append(&self.from);
s.append(&self.to);
s.append(&self.value);
s.append(&self.gas);
s.append(&self.input);
s.append(&self.call_type);
}
}
impl Decodable for Call {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let res = Call {
from: rlp.val_at(0)?,
to: rlp.val_at(1)?,
value: rlp.val_at(2)?,
gas: rlp.val_at(3)?,
input: rlp.val_at(4)?,
call_type: rlp.val_at(5)?,
};
Ok(res)
}
}
impl Call {
/// Returns call action bloom.
/// The bloom contains from and to addresses.
@ -163,7 +96,7 @@ impl Call {
}
/// Description of a _create_ action, either a `CREATE` operation or a create transction.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Create {
/// The address of the creator.
@ -187,29 +120,6 @@ impl From<ActionParams> for Create {
}
}
impl Encodable for Create {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4);
s.append(&self.from);
s.append(&self.value);
s.append(&self.gas);
s.append(&self.init);
}
}
impl Decodable for Create {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let res = Create {
from: rlp.val_at(0)?,
value: rlp.val_at(1)?,
gas: rlp.val_at(2)?,
init: rlp.val_at(3)?,
};
Ok(res)
}
}
impl Create {
/// Returns bloom create action bloom.
/// The bloom contains only from address.
@ -219,7 +129,7 @@ impl Create {
}
/// Suicide action.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Suicide {
/// Suicided address.
@ -238,28 +148,6 @@ impl Suicide {
}
}
impl Encodable for Suicide {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3);
s.append(&self.address);
s.append(&self.refund_address);
s.append(&self.balance);
}
}
impl Decodable for Suicide {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let res = Suicide {
address: rlp.val_at(0)?,
refund_address: rlp.val_at(1)?,
balance: rlp.val_at(2)?,
};
Ok(res)
}
}
/// Description of an action that we trace; will be either a call or a create.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
@ -394,7 +282,7 @@ impl Res {
}
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A diff of some chunk of memory.
pub struct MemoryDiff {
@ -404,24 +292,7 @@ pub struct MemoryDiff {
pub data: Bytes,
}
impl Encodable for MemoryDiff {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2);
s.append(&self.offset);
s.append(&self.data);
}
}
impl Decodable for MemoryDiff {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(MemoryDiff {
offset: rlp.val_at(0)?,
data: rlp.val_at(1)?,
})
}
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A diff of some storage value.
pub struct StorageDiff {
@ -431,24 +302,7 @@ pub struct StorageDiff {
pub value: U256,
}
impl Encodable for StorageDiff {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2);
s.append(&self.location);
s.append(&self.value);
}
}
impl Decodable for StorageDiff {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(StorageDiff {
location: rlp.val_at(0)?,
value: rlp.val_at(1)?,
})
}
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of an executed VM operation.
pub struct VMExecutedOperation {
@ -462,28 +316,7 @@ pub struct VMExecutedOperation {
pub store_diff: Option<StorageDiff>,
}
impl Encodable for VMExecutedOperation {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4);
s.append(&self.gas_used);
s.append_list(&self.stack_push);
s.append(&self.mem_diff);
s.append(&self.store_diff);
}
}
impl Decodable for VMExecutedOperation {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(VMExecutedOperation {
gas_used: rlp.val_at(0)?,
stack_push: rlp.list_at(1)?,
mem_diff: rlp.val_at(2)?,
store_diff: rlp.val_at(3)?,
})
}
}
#[derive(Debug, Clone, PartialEq, Default)]
#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of the execution of a single VM operation.
pub struct VMOperation {
@ -497,30 +330,7 @@ pub struct VMOperation {
pub executed: Option<VMExecutedOperation>,
}
impl Encodable for VMOperation {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4);
s.append(&self.pc);
s.append(&self.instruction);
s.append(&self.gas_cost);
s.append(&self.executed);
}
}
impl Decodable for VMOperation {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let res = VMOperation {
pc: rlp.val_at(0)?,
instruction: rlp.val_at(1)?,
gas_cost: rlp.val_at(2)?,
executed: rlp.val_at(3)?,
};
Ok(res)
}
}
#[derive(Debug, Clone, PartialEq, Default)]
#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of a full VM trace for a CALL/CREATE.
pub struct VMTrace {
@ -534,26 +344,3 @@ pub struct VMTrace {
/// Thre is a 1:1 correspondance between these and a CALL/CREATE/CALLCODE/DELEGATECALL instruction.
pub subs: Vec<VMTrace>,
}
impl Encodable for VMTrace {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4);
s.append(&self.parent_step);
s.append(&self.code);
s.append_list(&self.operations);
s.append_list(&self.subs);
}
}
impl Decodable for VMTrace {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let res = VMTrace {
parent_step: rlp.val_at(0)?,
code: rlp.val_at(1)?,
operations: rlp.list_at(2)?,
subs: rlp.list_at(3)?,
};
Ok(res)
}
}

View File

@ -56,6 +56,15 @@ impl Decodable for Action {
}
}
impl Encodable for Action {
fn rlp_append(&self, s: &mut RlpStream) {
match *self {
Action::Create => s.append_internal(&""),
Action::Call(ref addr) => s.append_internal(addr),
};
}
}
/// Transaction activation condition.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Condition {
@ -90,10 +99,7 @@ impl Transaction {
s.append(&self.nonce);
s.append(&self.gas_price);
s.append(&self.gas);
match self.action {
Action::Create => s.append_empty_data(),
Action::Call(ref to) => s.append(to)
};
s.append(&self.action);
s.append(&self.value);
s.append(&self.data);
if let Some(n) = network_id {
@ -308,10 +314,7 @@ impl UnverifiedTransaction {
s.append(&self.nonce);
s.append(&self.gas_price);
s.append(&self.gas);
match self.action {
Action::Create => s.append_empty_data(),
Action::Call(ref to) => s.append(to)
};
s.append(&self.action);
s.append(&self.value);
s.append(&self.data);
s.append(&self.v);

View File

@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
rlp = { path = "../../util/rlp" }
rlp_derive = { path = "../../util/rlp_derive" }
ethcore-util = { path = "../../util" }
ethjson = { path = "../../json" }
bloomable = { path = "../../util/bloomable" }

View File

@ -16,11 +16,10 @@
//! Basic account type -- the decoded RLP from the state trie.
use rlp::*;
use util::{U256, H256};
/// Basic account type.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct BasicAccount {
/// Nonce of the account.
pub nonce: U256,
@ -31,24 +30,3 @@ pub struct BasicAccount {
/// Code hash of the account.
pub code_hash: H256,
}
impl Encodable for BasicAccount {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4)
.append(&self.nonce)
.append(&self.balance)
.append(&self.storage_root)
.append(&self.code_hash);
}
}
impl Decodable for BasicAccount {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(BasicAccount {
nonce: rlp.val_at(0)?,
balance: rlp.val_at(1)?,
storage_root: rlp.val_at(2)?,
code_hash: rlp.val_at(3)?,
})
}
}

View File

@ -19,6 +19,8 @@
extern crate ethcore_util as util;
extern crate ethjson;
extern crate rlp;
#[macro_use]
extern crate rlp_derive;
extern crate bloomable;
#[cfg(test)]

View File

@ -19,7 +19,6 @@
use std::ops::Deref;
use util::{H256, Address, Bytes, HeapSizeOf, Hashable};
use bloomable::Bloomable;
use rlp::*;
use {BlockNumber};
use ethjson;
@ -27,7 +26,7 @@ use ethjson;
pub type LogBloom = ::util::H2048;
/// A record of execution for a `LOG` operation.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
#[derive(Default, Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct LogEntry {
/// The address of the contract executing at the point of the `LOG` operation.
pub address: Address,
@ -37,26 +36,6 @@ pub struct LogEntry {
pub data: Bytes,
}
impl Encodable for LogEntry {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3);
s.append(&self.address);
s.append_list(&self.topics);
s.append(&self.data);
}
}
impl Decodable for LogEntry {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let entry = LogEntry {
address: rlp.val_at(0)?,
topics: rlp.list_at(1)?,
data: rlp.val_at(2)?,
};
Ok(entry)
}
}
impl HeapSizeOf for LogEntry {
fn heap_size_of_children(&self) -> usize {
self.topics.heap_size_of_children() + self.data.heap_size_of_children()

View File

@ -0,0 +1,15 @@
[package]
name = "rlp_derive"
version = "0.1.0"
authors = ["debris <marek.kotewicz@gmail.com>"]
[lib]
name = "rlp_derive"
proc-macro = true
[dependencies]
syn = "0.11.11"
quote = "0.3.15"
[dev-dependencies]
rlp = { path = "../rlp" }

139
util/rlp_derive/src/de.rs Normal file
View File

@ -0,0 +1,139 @@
use {syn, quote};
struct ParseQuotes {
single: quote::Tokens,
list: quote::Tokens,
takes_index: bool,
}
fn decodable_parse_quotes() -> ParseQuotes {
ParseQuotes {
single: quote! { rlp.val_at },
list: quote! { rlp.list_at },
takes_index: true,
}
}
fn decodable_wrapper_parse_quotes() -> ParseQuotes {
ParseQuotes {
single: quote! { rlp.as_val },
list: quote! { rlp.as_list },
takes_index: false,
}
}
pub fn impl_decodable(ast: &syn::DeriveInput) -> quote::Tokens {
let body = match ast.body {
syn::Body::Struct(ref s) => s,
_ => panic!("#[derive(RlpDecodable)] is only defined for structs."),
};
let stmts: Vec<_> = match *body {
syn::VariantData::Struct(ref fields) | syn::VariantData::Tuple(ref fields) =>
fields.iter().enumerate().map(decodable_field_map).collect(),
syn::VariantData::Unit => panic!("#[derive(RlpDecodable)] is not defined for Unit structs."),
};
let name = &ast.ident;
let dummy_const = syn::Ident::new(format!("_IMPL_RLP_DECODABLE_FOR_{}", name));
let impl_block = quote! {
impl rlp::Decodable for #name {
fn decode(rlp: &rlp::UntrustedRlp) -> Result<Self, rlp::DecoderError> {
let result = #name {
#(#stmts)*
};
Ok(result)
}
}
};
quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate rlp;
#impl_block
};
}
}
pub fn impl_decodable_wrapper(ast: &syn::DeriveInput) -> quote::Tokens {
let body = match ast.body {
syn::Body::Struct(ref s) => s,
_ => panic!("#[derive(RlpDecodableWrapper)] is only defined for structs."),
};
let stmt = match *body {
syn::VariantData::Struct(ref fields) | syn::VariantData::Tuple(ref fields) => {
if fields.len() == 1 {
let field = fields.first().expect("fields.len() == 1; qed");
decodable_field(0, field, decodable_wrapper_parse_quotes())
} else {
panic!("#[derive(RlpDecodableWrapper)] is only defined for structs with one field.")
}
},
syn::VariantData::Unit => panic!("#[derive(RlpDecodableWrapper)] is not defined for Unit structs."),
};
let name = &ast.ident;
let dummy_const = syn::Ident::new(format!("_IMPL_RLP_DECODABLE_FOR_{}", name));
let impl_block = quote! {
impl rlp::Decodable for #name {
fn decode(rlp: &rlp::UntrustedRlp) -> Result<Self, rlp::DecoderError> {
let result = #name {
#stmt
};
Ok(result)
}
}
};
quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate rlp;
#impl_block
};
}
}
fn decodable_field_map(tuple: (usize, &syn::Field)) -> quote::Tokens {
decodable_field(tuple.0, tuple.1, decodable_parse_quotes())
}
fn decodable_field(index: usize, field: &syn::Field, quotes: ParseQuotes) -> quote::Tokens {
let ident = match field.ident {
Some(ref ident) => ident.to_string(),
None => index.to_string(),
};
let id = syn::Ident::new(ident);
let index = syn::Ident::new(index.to_string());
let single = quotes.single;
let list = quotes.list;
match field.ty {
syn::Ty::Path(_, ref path) => {
let ident = &path.segments.first().expect("there must be at least 1 segment").ident;
if &ident.to_string() == "Vec" {
if quotes.takes_index {
quote! { #id: #list(#index)?, }
} else {
quote! { #id: #list()?, }
}
} else {
if quotes.takes_index {
quote! { #id: #single(#index)?, }
} else {
quote! { #id: #single()?, }
}
}
},
_ => panic!("rlp_derive not supported"),
}
}

110
util/rlp_derive/src/en.rs Normal file
View File

@ -0,0 +1,110 @@
use {syn, quote};
pub fn impl_encodable(ast: &syn::DeriveInput) -> quote::Tokens {
let body = match ast.body {
syn::Body::Struct(ref s) => s,
_ => panic!("#[derive(RlpEncodable)] is only defined for structs."),
};
let stmts: Vec<_> = match *body {
syn::VariantData::Struct(ref fields) | syn::VariantData::Tuple(ref fields) =>
fields.iter().enumerate().map(encodable_field_map).collect(),
syn::VariantData::Unit => panic!("#[derive(RlpEncodable)] is not defined for Unit structs."),
};
let name = &ast.ident;
let stmts_len = syn::Ident::new(stmts.len().to_string());
let dummy_const = syn::Ident::new(format!("_IMPL_RLP_ENCODABLE_FOR_{}", name));
let impl_block = quote! {
impl rlp::Encodable for #name {
fn rlp_append(&self, stream: &mut rlp::RlpStream) {
stream.begin_list(#stmts_len);
#(#stmts)*
}
}
};
quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate rlp;
#impl_block
};
}
}
pub fn impl_encodable_wrapper(ast: &syn::DeriveInput) -> quote::Tokens {
let body = match ast.body {
syn::Body::Struct(ref s) => s,
_ => panic!("#[derive(RlpEncodableWrapper)] is only defined for structs."),
};
let stmt = match *body {
syn::VariantData::Struct(ref fields) | syn::VariantData::Tuple(ref fields) => {
if fields.len() == 1 {
let field = fields.first().expect("fields.len() == 1; qed");
encodable_field(0, field)
} else {
panic!("#[derive(RlpEncodableWrapper)] is only defined for structs with one field.")
}
},
syn::VariantData::Unit => panic!("#[derive(RlpEncodableWrapper)] is not defined for Unit structs."),
};
let name = &ast.ident;
let dummy_const = syn::Ident::new(format!("_IMPL_RLP_ENCODABLE_FOR_{}", name));
let impl_block = quote! {
impl rlp::Encodable for #name {
fn rlp_append(&self, stream: &mut rlp::RlpStream) {
#stmt
}
}
};
quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate rlp;
#impl_block
};
}
}
fn encodable_field_map(tuple: (usize, &syn::Field)) -> quote::Tokens {
encodable_field(tuple.0, tuple.1)
}
fn encodable_field(index: usize, field: &syn::Field) -> quote::Tokens {
let ident = match field.ident {
Some(ref ident) => ident.to_string(),
None => index.to_string(),
};
let id = syn::Ident::new(format!("self.{}", ident));
match field.ty {
syn::Ty::Path(_, ref path) => {
let top_segment = path.segments.first().expect("there must be at least 1 segment");
let ident = &top_segment.ident;
if &ident.to_string() == "Vec" {
let inner_ident = match top_segment.parameters {
syn::PathParameters::AngleBracketed(ref angle) => {
let ty = angle.types.first().expect("Vec has only one angle bracketed type; qed");
match *ty {
syn::Ty::Path(_, ref path) => &path.segments.first().expect("there must be at least 1 segment").ident,
_ => panic!("rlp_derive not supported"),
}
},
_ => unreachable!("Vec has only one angle bracketed type; qed"),
};
quote! { stream.append_list::<#inner_ident, _>(&#id); }
} else {
quote! { stream.append(&#id); }
}
},
_ => panic!("rlp_derive not supported"),
}
}

View File

@ -0,0 +1,43 @@
extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
mod en;
mod de;
use proc_macro::TokenStream;
use en::{impl_encodable, impl_encodable_wrapper};
use de::{impl_decodable, impl_decodable_wrapper};
#[proc_macro_derive(RlpEncodable)]
pub fn encodable(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
let gen = impl_encodable(&ast);
gen.parse().unwrap()
}
#[proc_macro_derive(RlpEncodableWrapper)]
pub fn encodable_wrapper(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
let gen = impl_encodable_wrapper(&ast);
gen.parse().unwrap()
}
#[proc_macro_derive(RlpDecodable)]
pub fn decodable(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
let gen = impl_decodable(&ast);
gen.parse().unwrap()
}
#[proc_macro_derive(RlpDecodableWrapper)]
pub fn decodable_wrapper(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
let gen = impl_decodable_wrapper(&ast);
gen.parse().unwrap()
}

View File

@ -0,0 +1,44 @@
extern crate rlp;
#[macro_use]
extern crate rlp_derive;
use rlp::{encode, decode};
#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)]
struct Foo {
a: String,
}
#[derive(Debug, PartialEq, RlpEncodableWrapper, RlpDecodableWrapper)]
struct FooWrapper {
a: String,
}
#[test]
fn test_encode_foo() {
let foo = Foo {
a: "cat".into(),
};
let expected = vec![0xc4, 0x83, b'c', b'a', b't'];
let out = encode(&foo).into_vec();
assert_eq!(out, expected);
let decoded = decode(&expected);
assert_eq!(foo, decoded);
}
#[test]
fn test_encode_foo_wrapper() {
let foo = FooWrapper {
a: "cat".into(),
};
let expected = vec![0x83, b'c', b'a', b't'];
let out = encode(&foo).into_vec();
assert_eq!(out, expected);
let decoded = decode(&expected);
assert_eq!(foo, decoded);
}