update to published rlp-derive (#11489)

This commit is contained in:
Andronik Ordian 2020-02-13 15:34:51 +01:00 committed by GitHub
parent 9477bae6dc
commit 3424697313
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 27 additions and 501 deletions

37
Cargo.lock generated
View File

@ -710,7 +710,7 @@ dependencies = [
"parity-util-mem",
"patricia-trie-ethereum",
"rlp",
"rlp_derive",
"rlp-derive",
"rustc-hex 2.1.0",
"unexpected",
"vm",
@ -1010,7 +1010,7 @@ dependencies = [
"hex-literal",
"maplit",
"rlp",
"rlp_derive",
"rlp-derive",
]
[[package]]
@ -1307,8 +1307,8 @@ dependencies = [
"rand 0.7.2",
"rayon",
"rlp",
"rlp-derive",
"rlp_compress",
"rlp_derive",
"rustc-hex 1.0.0",
"tempdir",
"triehash-ethereum",
@ -1359,7 +1359,7 @@ dependencies = [
"parity-util-mem",
"parking_lot 0.10.0",
"rlp",
"rlp_derive",
"rlp-derive",
]
[[package]]
@ -1415,7 +1415,7 @@ dependencies = [
"patricia-trie-ethereum",
"rand 0.7.2",
"rlp",
"rlp_derive",
"rlp-derive",
"serde",
"serde_derive",
"smallvec 1.2.0",
@ -1566,7 +1566,7 @@ dependencies = [
"patricia-trie-ethereum",
"registrar",
"rlp",
"rlp_derive",
"rlp-derive",
"rustc-hex 1.0.0",
"serde",
"serde_derive",
@ -4317,6 +4317,17 @@ dependencies = [
"rustc-hex 2.1.0",
]
[[package]]
name = "rlp-derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a"
dependencies = [
"proc-macro2 1.0.8",
"quote 1.0.2",
"syn 1.0.14",
]
[[package]]
name = "rlp_compress"
version = "0.1.0"
@ -4326,16 +4337,6 @@ dependencies = [
"rlp",
]
[[package]]
name = "rlp_derive"
version = "0.1.0"
dependencies = [
"proc-macro2 1.0.8",
"quote 1.0.2",
"rlp",
"syn 1.0.14",
]
[[package]]
name = "rocksdb"
version = "0.13.0"
@ -4709,7 +4710,7 @@ dependencies = [
"rand 0.7.2",
"rand_xorshift 0.2.0",
"rlp",
"rlp_derive",
"rlp-derive",
"scopeguard 1.0.0",
"snapshot-tests",
"spec",
@ -5358,7 +5359,7 @@ dependencies = [
"parity-util-mem",
"parking_lot 0.10.0",
"rlp",
"rlp_derive",
"rlp-derive",
"vm",
]

View File

@ -24,7 +24,7 @@ parking_lot = "0.10.0"
rayon = "1.0"
rlp = "0.4.0"
rlp_compress = { path = "../../util/rlp-compress" }
rlp_derive = { path = "../../util/rlp-derive" }
rlp-derive = "0.1"
triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" }
[dev-dependencies]

View File

@ -14,4 +14,4 @@ kvdb = "0.4.0"
parity-util-mem = "0.5.1"
parking_lot = "0.10.0"
rlp = "0.4.0"
rlp_derive = { path = "../../util/rlp-derive" }
rlp-derive = "0.1"

View File

@ -30,7 +30,7 @@ vm = { path = "../vm" }
fastmap = { path = "../../util/fastmap" }
failsafe = { version = "0.3.0", default-features = false, features = ["parking_lot_mutex"] }
rlp = "0.4.0"
rlp_derive = { path = "../../util/rlp-derive" }
rlp-derive = "0.1"
smallvec = "1.2.0"
futures = "0.1"
rand = "0.7"

View File

@ -37,7 +37,7 @@ trie-db = "0.20.0"
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
registrar = { path = "../../util/registrar" }
rlp = "0.4.0"
rlp_derive = { path = "../../util/rlp-derive" }
rlp-derive = "0.1"
rustc-hex = "1.0"
serde = "1.0"
serde_derive = "1.0"

View File

@ -36,7 +36,7 @@ rand = "0.7"
rand_xorshift = "0.2"
parking_lot = "0.10.0"
rlp = "0.4.2"
rlp_derive = { path = "../../util/rlp-derive" }
rlp-derive = "0.1"
scopeguard = "1.0.0"
snappy = { package = "parity-snappy", version ="0.1.0" }
state-db = { path = "../state-db" }

View File

@ -17,7 +17,7 @@ parity-bytes = "0.1.0"
parity-util-mem = "0.5.1"
parking_lot = "0.10.0"
rlp = "0.4.0"
rlp_derive = { path = "../../util/rlp-derive" }
rlp-derive = "0.1"
vm = { path = "../vm" }
[dev-dependencies]

View File

@ -17,7 +17,7 @@ parity-util-mem = "0.5.1"
parity-snappy = "0.1"
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
rlp = "0.4.0"
rlp_derive = { path = "../../util/rlp-derive" }
rlp-derive = "0.1"
unexpected = { path = "../../util/unexpected" }
vm = { path = "../vm"}

View File

@ -15,7 +15,7 @@ crc = "1"
ethereum-types = "0.8.0"
maplit = "1"
rlp = "0.4"
rlp_derive = { path = "../rlp-derive" }
rlp-derive = "0.1"
[dev-dependencies]
hex-literal = "0.2"

View File

@ -1,17 +0,0 @@
[package]
name = "rlp_derive"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[lib]
name = "rlp_derive"
proc-macro = true
[dependencies]
syn = "1.0.14"
quote = "1.0.2"
proc-macro2 = "1.0.8"
[dev-dependencies]
rlp = "0.4.0"

View File

@ -1,193 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use proc_macro2::TokenStream;
use quote::quote;
struct ParseQuotes {
single: TokenStream,
list: TokenStream,
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) -> TokenStream {
let body = match ast.data {
syn::Data::Struct(ref s) => s,
_ => panic!("#[derive(RlpDecodable)] is only defined for structs."),
};
let mut default_attribute_encountered = false;
let stmts: Vec<_> = body
.fields
.iter()
.enumerate()
.map(|(i, field)| decodable_field(
i,
field,
decodable_parse_quotes(),
&mut default_attribute_encountered,
)).collect();
let name = &ast.ident;
let impl_block = quote! {
impl rlp::Decodable for #name {
fn decode(rlp: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
let result = #name {
#(#stmts)*
};
Ok(result)
}
}
};
quote! {
const _: () = {
extern crate rlp;
#impl_block
};
}
}
pub fn impl_decodable_wrapper(ast: &syn::DeriveInput) -> TokenStream {
let body = match ast.data {
syn::Data::Struct(ref s) => s,
_ => panic!("#[derive(RlpDecodableWrapper)] is only defined for structs."),
};
let stmt = {
let fields: Vec<_> = body.fields.iter().collect();
if fields.len() == 1 {
let field = fields.first().expect("fields.len() == 1; qed");
let mut default_attribute_encountered = false;
decodable_field(
0,
field,
decodable_wrapper_parse_quotes(),
&mut default_attribute_encountered,
)
} else {
panic!("#[derive(RlpEncodableWrapper)] is only defined for structs with one field.")
}
};
let name = &ast.ident;
let impl_block = quote! {
impl rlp::Decodable for #name {
fn decode(rlp: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
let result = #name {
#stmt
};
Ok(result)
}
}
};
quote! {
const _: () = {
extern crate rlp;
#impl_block
};
}
}
fn decodable_field(
index: usize,
field: &syn::Field,
quotes: ParseQuotes,
default_attribute_encountered: &mut bool,
) -> TokenStream {
let id = match field.ident {
Some(ref ident) => quote! { #ident },
None => {
let index: syn::Index = index.into();
quote! { #index }
}
};
let index = index - *default_attribute_encountered as usize;
let index = quote! { #index };
let single = quotes.single;
let list = quotes.list;
let attributes = &field.attrs;
let default = if let Some(attr) = attributes.iter().find(|attr| attr.path.is_ident("rlp")) {
if *default_attribute_encountered {
panic!("only 1 #[rlp(default)] attribute is allowed in a struct")
}
match attr.parse_args() {
Ok(proc_macro2::TokenTree::Ident(ident)) if ident.to_string() == "default" => {},
_ => panic!("only #[rlp(default)] attribute is supported"),
}
*default_attribute_encountered = true;
true
} else {
false
};
match field.ty {
syn::Type::Path(ref path) => {
let ident = &path
.path
.segments
.first()
.expect("there must be at least 1 segment")
.ident;
let ident_type = ident.to_string();
if &ident_type == "Vec" {
if quotes.takes_index {
if default {
quote! { #id: #list(#index).unwrap_or_default(), }
} else {
quote! { #id: #list(#index)?, }
}
} else {
quote! { #id: #list()?, }
}
} else {
if quotes.takes_index {
if default {
quote! { #id: #single(#index).unwrap_or_default(), }
} else {
quote! { #id: #single(#index)?, }
}
} else {
quote! { #id: #single()?, }
}
}
}
_ => panic!("rlp_derive not supported"),
}
}

View File

@ -1,134 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use proc_macro2::TokenStream;
use quote::quote;
pub fn impl_encodable(ast: &syn::DeriveInput) -> TokenStream {
let body = match ast.data {
syn::Data::Struct(ref s) => s,
_ => panic!("#[derive(RlpEncodable)] is only defined for structs."),
};
let stmts: Vec<_> = body
.fields
.iter()
.enumerate()
.map(|(i, field)| encodable_field(i, field))
.collect();
let name = &ast.ident;
let stmts_len = stmts.len();
let stmts_len = quote! { #stmts_len };
let impl_block = quote! {
impl rlp::Encodable for #name {
fn rlp_append(&self, stream: &mut rlp::RlpStream) {
stream.begin_list(#stmts_len);
#(#stmts)*
}
}
};
quote! {
const _: () = {
extern crate rlp;
#impl_block
};
}
}
pub fn impl_encodable_wrapper(ast: &syn::DeriveInput) -> TokenStream {
let body = match ast.data {
syn::Data::Struct(ref s) => s,
_ => panic!("#[derive(RlpEncodableWrapper)] is only defined for structs."),
};
let stmt = {
let fields: Vec<_> = body.fields.iter().collect();
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.")
}
};
let name = &ast.ident;
let impl_block = quote! {
impl rlp::Encodable for #name {
fn rlp_append(&self, stream: &mut rlp::RlpStream) {
#stmt
}
}
};
quote! {
const _: () = {
extern crate rlp;
#impl_block
};
}
}
fn encodable_field(index: usize, field: &syn::Field) -> TokenStream {
let ident = match field.ident {
Some(ref ident) => quote! { #ident },
None => {
let index: syn::Index = index.into();
quote! { #index }
}
};
let id = quote! { self.#ident };
match field.ty {
syn::Type::Path(ref path) => {
let top_segment = path
.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.arguments {
syn::PathArguments::AngleBracketed(ref angle) => {
let ty = angle
.args
.first()
.expect("Vec has only one angle bracketed type; qed");
match *ty {
syn::GenericArgument::Type(syn::Type::Path(ref path)) => {
&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

@ -1,52 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
extern crate proc_macro;
mod de;
mod en;
use de::{impl_decodable, impl_decodable_wrapper};
use en::{impl_encodable, impl_encodable_wrapper};
use proc_macro::TokenStream;
#[proc_macro_derive(RlpEncodable, attributes(rlp))]
pub fn encodable(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
let gen = impl_encodable(&ast);
gen.into()
}
#[proc_macro_derive(RlpEncodableWrapper)]
pub fn encodable_wrapper(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
let gen = impl_encodable_wrapper(&ast);
gen.into()
}
#[proc_macro_derive(RlpDecodable, attributes(rlp))]
pub fn decodable(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
let gen = impl_decodable(&ast);
gen.into()
}
#[proc_macro_derive(RlpDecodableWrapper)]
pub fn decodable_wrapper(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
let gen = impl_decodable_wrapper(&ast);
gen.into()
}

View File

@ -1,79 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use rlp::{decode, encode};
use rlp_derive::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper};
#[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);
assert_eq!(out, expected);
let decoded = decode(&expected).expect("decode failure");
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);
assert_eq!(out, expected);
let decoded = decode(&expected).expect("decode failure");
assert_eq!(foo, decoded);
}
#[test]
fn test_encode_foo_default() {
#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)]
struct FooDefault {
a: String,
/// It works with other attributes.
#[rlp(default)]
b: Option<Vec<u8>>,
}
let attack_of = String::from("clones");
let foo = Foo { a: attack_of.clone() };
let expected = vec![0xc7, 0x86, b'c', b'l', b'o', b'n', b'e', b's'];
let out = encode(&foo);
assert_eq!(out, expected);
let foo_default = FooDefault { a: attack_of.clone(), b: None };
let decoded = decode(&expected).expect("default failure");
assert_eq!(foo_default, decoded);
let foo_some = FooDefault { a: attack_of.clone(), b: Some(vec![1, 2, 3]) };
let out = encode(&foo_some);
assert_eq!(decode(&out), Ok(foo_some));
}