Custom attribute for binary serialization (#3922)

* derive(Binary) -> binary

* ethcore types refact

* fixup ethcore

* make binary optional

* fix common types

* fix updater

* remove condition
This commit is contained in:
Nikolay Volf
2016-12-21 18:09:35 +04:00
committed by Gav Wood
parent b369939f20
commit af501e6467
39 changed files with 268 additions and 160 deletions

View File

@@ -111,7 +111,7 @@ fn push_invoke_signature_aster(
let arg_ty = &inputs[skip-1].ty;
let mut tree = builder.item()
.attr().word("derive(Binary)")
.attr().word("binary")
.attr().word("allow(non_camel_case_types)")
.struct_(name_str.as_str())
.field(arg_name.as_str())
@@ -140,7 +140,7 @@ fn push_invoke_signature_aster(
FunctionRetTy::Ty(ref ty) => {
let name_str = format!("{}_output", named_signature.ident.name.as_str());
let tree = builder.item()
.attr().word("derive(Binary)")
.attr().word("binary")
.attr().word("allow(non_camel_case_types)")
.struct_(name_str.as_str())
.field(format!("payload")).ty().build(ty.clone());
@@ -326,7 +326,7 @@ pub fn has_ptr(ty: &P<ast::Ty>) -> bool {
/// fn commit(&self, f: u32) -> u32
///
/// the expanded implementation will generate method for the client like that
/// #[derive(Serialize)]
/// #[binary]
/// struct Request<'a> {
/// f: &'a u32,
/// }
@@ -358,7 +358,7 @@ fn implement_client_method_body(
.build(static_ty.clone());
let mut tree = builder.item()
.attr().word("derive(Binary)")
.attr().word("binary")
.struct_("Request")
.generics()
.lifetime_name("'a")

View File

@@ -42,6 +42,10 @@ extern crate rustc_plugin;
#[cfg(not(feature = "with-syntex"))]
use syntax::feature_gate::AttributeType;
#[cfg(feature = "with-syntex")]
use syntax::{ast, fold};
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
@@ -56,29 +60,44 @@ pub fn expand(src: &std::path::Path, dst: &std::path::Path) {
}
#[cfg(feature = "with-syntex")]
pub fn register_cleaner(reg: &mut syntex::Registry) {
use syntax::{ast, fold};
struct StripAttributeFolder<'a> {
attr_title: &'a str,
}
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
struct StripAttributeFolder;
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == &"ipc" => { return None; }
ast::MetaItemKind::Word(ref n) if n == &"ipc" => { return None; }
_ => {}
}
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
#[cfg(feature = "with-syntex")]
impl<'a> fold::Folder for StripAttributeFolder<'a> {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == self.attr_title => { return None; }
ast::MetaItemKind::Word(ref n) if n == self.attr_title => { return None; }
_ => {}
}
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
#[cfg(feature = "with-syntex")]
pub fn register_cleaner_ipc(reg: &mut syntex::Registry) {
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
let mut folder = StripAttributeFolder { attr_title: "ipc" };
fold::Folder::fold_crate(&mut folder, krate)
}
reg.add_post_expansion_pass(strip_attributes);
}
#[cfg(feature = "with-syntex")]
pub fn register_cleaner_binary(reg: &mut syntex::Registry) {
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
let mut folder = StripAttributeFolder { attr_title: "binary" };
fold::Folder::fold_crate(&mut folder, krate)
}
reg.add_post_expansion_pass(strip_attributes);
@@ -90,9 +109,10 @@ pub fn register(reg: &mut syntex::Registry) {
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("ipc", codegen::expand_ipc_implementation);
reg.add_decorator("derive_Binary", serialization::expand_serialization_implementation);
reg.add_decorator("binary", serialization::expand_serialization_implementation);
register_cleaner(reg);
register_cleaner_ipc(reg);
register_cleaner_binary(reg);
}
#[cfg(not(feature = "with-syntex"))]
@@ -102,11 +122,12 @@ pub fn register(reg: &mut rustc_plugin::Registry) {
syntax::ext::base::MultiDecorator(
Box::new(codegen::expand_ipc_implementation)));
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Binary"),
syntax::parse::token::intern("binary"),
syntax::ext::base::MultiDecorator(
Box::new(serialization::expand_serialization_implementation)));
reg.register_attribute("ipc".to_owned(), AttributeType::Normal);
reg.register_attribute("binary".to_owned(), AttributeType::Normal);
}
#[derive(Debug)]
@@ -124,13 +145,31 @@ pub fn derive_ipc_cond(src_path: &str, has_feature: bool) -> Result<(), Error> {
}
pub fn cleanup_ipc(src_path: &str) -> Result<(), Error> {
cleanup(src_path, AttributeKind::Ipc)
}
pub fn cleanup_binary(src_path: &str) -> Result<(), Error> {
cleanup(src_path, AttributeKind::Binary)
}
enum AttributeKind {
Ipc,
Binary,
}
fn cleanup(src_path: &str, attr: AttributeKind) -> Result<(), Error> {
use std::env;
use std::path::{Path, PathBuf};
let out_dir = env::var_os("OUT_DIR").unwrap();
let file_name = try!(PathBuf::from(src_path).file_name().ok_or(Error::InvalidFileName).map(|val| val.to_str().unwrap().to_owned()));
let mut registry = syntex::Registry::new();
register_cleaner(&mut registry);
match attr {
AttributeKind::Ipc => { register_cleaner_ipc(&mut registry); }
AttributeKind::Binary => { register_cleaner_binary(&mut registry); }
}
if let Err(_) = registry.expand("", &Path::new(src_path), &Path::new(&out_dir).join(&file_name))
{
// will be reported by compiler
@@ -190,3 +229,8 @@ pub fn derive_binary(src_path: &str) -> Result<(), Error> {
Ok(())
}
pub fn derive_binary_cond(src_path: &str, has_feature: bool) -> Result<(), Error> {
if has_feature { derive_binary(src_path) }
else { cleanup_binary(src_path) }
}