Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions util/rlp-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
[package]
name = "rlp_derive"
version = "0.1.0"
authors = ["debris <marek.kotewicz@gmail.com>"]
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"

[lib]
name = "rlp_derive"
proc-macro = true

[dependencies]
syn = "0.15"
quote = "0.6"
proc-macro2 = "0.4"
syn = "1.0.14"
quote = "1.0.2"
proc-macro2 = "1.0.8"

[dev-dependencies]
rlp = "0.4.0"
28 changes: 17 additions & 11 deletions util/rlp-derive/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
// 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 syn;
use proc_macro2::{TokenStream, Span};
use proc_macro2::TokenStream;
use quote::quote;

struct ParseQuotes {
single: TokenStream,
Expand Down Expand Up @@ -45,10 +45,14 @@ pub fn impl_decodable(ast: &syn::DeriveInput) -> TokenStream {
_ => panic!("#[derive(RlpDecodable)] is only defined for structs."),
};

let stmts: Vec<_> = body.fields.iter().enumerate().map(decodable_field_map).collect();
let stmts: Vec<_> = body
.fields
.iter()
.enumerate()
.map(decodable_field_map)
.collect();
let name = &ast.ident;

let dummy_const = syn::Ident::new(&format!("_IMPL_RLP_DECODABLE_FOR_{}", name), Span::call_site());
let impl_block = quote! {
impl rlp::Decodable for #name {
fn decode(rlp: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
Expand All @@ -62,8 +66,7 @@ pub fn impl_decodable(ast: &syn::DeriveInput) -> TokenStream {
};

quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
const _: () = {
extern crate rlp;
Comment thread
niklasad1 marked this conversation as resolved.
#impl_block
};
Expand All @@ -88,7 +91,6 @@ pub fn impl_decodable_wrapper(ast: &syn::DeriveInput) -> TokenStream {

let name = &ast.ident;

let dummy_const = syn::Ident::new(&format!("_IMPL_RLP_DECODABLE_FOR_{}", name), Span::call_site());
let impl_block = quote! {
impl rlp::Decodable for #name {
fn decode(rlp: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
Expand All @@ -102,8 +104,7 @@ pub fn impl_decodable_wrapper(ast: &syn::DeriveInput) -> TokenStream {
};

quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
const _: () = {
extern crate rlp;
#impl_block
};
Expand All @@ -130,7 +131,12 @@ fn decodable_field(index: usize, field: &syn::Field, quotes: ParseQuotes) -> Tok

match field.ty {
syn::Type::Path(ref path) => {
let ident = &path.path.segments.first().expect("there must be at least 1 segment").value().ident;
let ident = &path
.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)?, }
Expand All @@ -144,7 +150,7 @@ fn decodable_field(index: usize, field: &syn::Field, quotes: ParseQuotes) -> Tok
quote! { #id: #single()?, }
}
}
},
}
_ => panic!("rlp_derive not supported"),
}
}
49 changes: 32 additions & 17 deletions util/rlp-derive/src/en.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,25 @@
// 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 syn;
use proc_macro2::{TokenStream, Span};
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(encodable_field_map).collect();
let stmts: Vec<_> = body
.fields
.iter()
.enumerate()
.map(encodable_field_map)
.collect();
let name = &ast.ident;

let stmts_len = stmts.len();
let stmts_len = quote! { #stmts_len };
let dummy_const = syn::Ident::new(&format!("_IMPL_RLP_ENCODABLE_FOR_{}", name), Span::call_site());
let impl_block = quote! {
impl rlp::Encodable for #name {
fn rlp_append(&self, stream: &mut rlp::RlpStream) {
Expand All @@ -39,8 +43,7 @@ pub fn impl_encodable(ast: &syn::DeriveInput) -> TokenStream {
};

quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
const _: () = {
extern crate rlp;
#impl_block
};
Expand All @@ -65,7 +68,6 @@ pub fn impl_encodable_wrapper(ast: &syn::DeriveInput) -> TokenStream {

let name = &ast.ident;

let dummy_const = syn::Ident::new(&format!("_IMPL_RLP_ENCODABLE_FOR_{}", name), Span::call_site());
let impl_block = quote! {
impl rlp::Encodable for #name {
fn rlp_append(&self, stream: &mut rlp::RlpStream) {
Expand All @@ -75,8 +77,7 @@ pub fn impl_encodable_wrapper(ast: &syn::DeriveInput) -> TokenStream {
};

quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
const _: () = {
extern crate rlp;
#impl_block
};
Expand All @@ -100,24 +101,38 @@ fn encodable_field(index: usize, field: &syn::Field) -> TokenStream {

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.value().ident;
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.value().arguments {
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.value() {
syn::GenericArgument::Type(syn::Type::Path(ref path)) => &path.path.segments.first().expect("there must be at least 1 segment").value().ident,
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"),
}
}
10 changes: 3 additions & 7 deletions util/rlp-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,13 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.

extern crate proc_macro;
extern crate proc_macro2;
extern crate syn;
#[macro_use]
extern crate quote;

mod en;
mod de;
mod en;

use proc_macro::TokenStream;
use en::{impl_encodable, impl_encodable_wrapper};
use de::{impl_decodable, impl_decodable_wrapper};
use en::{impl_encodable, impl_encodable_wrapper};
use proc_macro::TokenStream;

#[proc_macro_derive(RlpEncodable)]
pub fn encodable(input: TokenStream) -> TokenStream {
Expand Down
15 changes: 4 additions & 11 deletions util/rlp-derive/tests/rlp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@
// 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 rlp;
#[macro_use]
extern crate rlp_derive;

use rlp::{encode, decode};
use rlp::{decode, encode};
use rlp_derive::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper};

#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)]
struct Foo {
Expand All @@ -32,9 +29,7 @@ struct FooWrapper {

#[test]
fn test_encode_foo() {
let foo = Foo {
a: "cat".into(),
};
let foo = Foo { a: "cat".into() };

let expected = vec![0xc4, 0x83, b'c', b'a', b't'];
let out = encode(&foo);
Expand All @@ -46,9 +41,7 @@ fn test_encode_foo() {

#[test]
fn test_encode_foo_wrapper() {
let foo = FooWrapper {
a: "cat".into(),
};
let foo = FooWrapper { a: "cat".into() };

let expected = vec![0x83, b'c', b'a', b't'];
let out = encode(&foo);
Expand Down