diff --git a/ipc/codegen/src/lib.rs b/ipc/codegen/src/lib.rs
index a29678df0..126aa3a85 100644
--- a/ipc/codegen/src/lib.rs
+++ b/ipc/codegen/src/lib.rs
@@ -54,6 +54,7 @@ pub fn register(reg: &mut syntex::Registry) {
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Ipc", codegen::expand_ipc_implementation);
+ reg.add_decorator("derive_Binary", serialization::expand_serialization_implementation);
}
#[cfg(not(feature = "with-syntex"))]
@@ -62,4 +63,8 @@ pub fn register(reg: &mut rustc_plugin::Registry) {
syntax::parse::token::intern("derive_Ipc"),
syntax::ext::base::MultiDecorator(
Box::new(codegen::expand_ipc_implementation)));
+ reg.register_syntax_extension(
+ syntax::parse::token::intern("derive_Binary"),
+ syntax::ext::base::MultiDecorator(
+ Box::new(serialization::expand_serialization_implementation)));
}
diff --git a/ipc/codegen/src/lib.rs.in b/ipc/codegen/src/lib.rs.in
index 46a2c9ca5..08c8ad998 100644
--- a/ipc/codegen/src/lib.rs.in
+++ b/ipc/codegen/src/lib.rs.in
@@ -15,4 +15,5 @@
// along with Parity. If not, see .
mod codegen;
+mod serialization;
pub mod typegen;
diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs
new file mode 100644
index 000000000..205b13f67
--- /dev/null
+++ b/ipc/codegen/src/serialization.rs
@@ -0,0 +1,202 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity 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 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. If not, see .
+use aster;
+
+use syntax::ast::{
+ MetaItem,
+ Item,
+ ImplItemKind,
+ ImplItem,
+ MethodSig,
+ Arg,
+ PatKind,
+ FunctionRetTy,
+ Ty,
+ TraitRef,
+ Ident,
+ Generics,
+};
+
+use syntax::ast;
+use syntax::codemap::Span;
+use syntax::ext::base::{Annotatable, ExtCtxt};
+use syntax::ext::build::AstBuilder;
+use syntax::ptr::P;
+
+pub struct Error;
+
+pub fn expand_serialization_implementation(
+ cx: &mut ExtCtxt,
+ span: Span,
+ meta_item: &MetaItem,
+ annotatable: &Annotatable,
+ push: &mut FnMut(Annotatable)
+) {
+ let item = match *annotatable {
+ Annotatable::Item(ref item) => item,
+ _ => {
+ cx.span_err(meta_item.span, "`#[derive(Binary)]` may only be applied to structs and enums");
+ return;
+ }
+ };
+
+ let builder = aster::AstBuilder::new().span(span);
+
+ let impl_item = match serialize_item(cx, &builder, &item) {
+ Ok(item) => item,
+ Err(Error) => {
+ // An error occured, but it should have been reported already.
+ return;
+ }
+ };
+
+ push(Annotatable::Item(impl_item))
+}
+
+fn serialize_item(
+ cx: &ExtCtxt,
+ builder: &aster::AstBuilder,
+ item: &Item,
+) -> Result
, Error> {
+ let generics = match item.node {
+ ast::ItemKind::Struct(_, ref generics) => generics,
+ ast::ItemKind::Enum(_, ref generics) => generics,
+ _ => {
+ cx.span_err(
+ item.span,
+ "`#[derive(Serialize)]` may only be applied to structs and enums");
+ return Err(Error);
+ }
+ };
+
+ let impl_generics = build_impl_generics(cx, builder, item, generics);
+
+ let ty = builder.ty().path()
+ .segment(item.ident).with_generics(impl_generics.clone()).build()
+ .build();
+
+ let where_clause = &impl_generics.where_clause;
+
+ let binary_expressions = try!(binary_expr(cx,
+ &builder,
+ &item,
+ &impl_generics,
+ ty.clone()));
+
+ Ok(quote_item!(cx,
+ impl $impl_generics ::ipc::BinaryConvertable for $ty $where_clause {
+ fn size(&self) -> usize {
+ $size_expr
+ }
+
+ fn to_bytes(buffer: &mut [u8]) {
+ $write_expr
+ }
+
+ fn from_bytes(buffer: &[u8]) -> Self {
+ $create_expr
+ }
+ }
+ ).unwrap())
+}
+
+fn binary_expr(
+ cx: &ExtCtxt,
+ builder: &aster::AstBuilder,
+ item: &Item,
+ impl_generics: &ast::Generics,
+ ty: P,
+) -> Result {
+ match item.node {
+ ast::ItemKind::Struct(ref variant_data, _) => {
+ binary_expr_struct(
+ cx,
+ builder,
+ impl_generics,
+ ty,
+ item.span,
+ variant_data,
+ )
+ }
+ ast::ItemKind::Enum(ref enum_def, _) => {
+ binary_expr_enum(
+ cx,
+ builder,
+ item.ident,
+ impl_generics,
+ ty,
+ enum_def,
+ )
+ }
+ _ => {
+ cx.span_bug(item.span,
+ "expected ItemStruct or ItemEnum in #[derive(Serialize)]");
+ }
+ }
+}
+
+struct BinaryExpressions {
+ size: P,
+ write: P,
+ read: P,
+}
+
+fn serialize_tuple_struct(
+ cx: &ExtCtxt,
+ builder: &aster::AstBuilder,
+ impl_generics: &ast::Generics,
+ ty: P,
+ fields: usize,
+) -> Result, Error> {
+ let type_name = field.ty;
+ let id = field.id;
+
+ Ok(BinaryExpressions {
+ size: quote_expr!(cx, self. $id .size() ),
+ write: quote_stmt!(cx, self. $id .write(buffer); ),
+ read: quote_expr!(cx, Self { $id: $type_name ::from_bytes(buffer) }),
+ });
+}
+
+fn binary_expr_struct(
+ cx: &ExtCtxt,
+ builder: &aster::AstBuilder,
+ impl_generics: &ast::Generics,
+ ty: P,
+ span: Span,
+ variant_data: &ast::VariantData,
+) -> Result {
+ match *variant_data {
+ ast::VariantData::Tuple(ref fields, _) => {
+ binary_expr_struct_tuple(
+ cx,
+ &builder,
+ impl_generics,
+ ty,
+ fields,
+ )
+ }
+ ast::VariantData::Struct(ref fields, _) => {
+ binary_expr_struct_inner(
+ cx,
+ &builder,
+ impl_generics,
+ ty,
+ fields,
+ )
+ }
+ }
+}
diff --git a/ipc/codegen/src/typegen.rs b/ipc/codegen/src/typegen.rs
index e6e828ee7..0699bccb0 100644
--- a/ipc/codegen/src/typegen.rs
+++ b/ipc/codegen/src/typegen.rs
@@ -50,7 +50,8 @@ fn is_new_entry(path: &Path) -> Option {
ident == "H256" ||
ident == "U256" ||
ident == "H2048" ||
- ident == "Address"
+ ident == "Address" ||
+ ident == "Bytes"
}
};
diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs
new file mode 100644
index 000000000..3b9b0a561
--- /dev/null
+++ b/ipc/rpc/src/binary.rs
@@ -0,0 +1,25 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity 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 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. If not, see .
+
+//! Binary representation of types
+
+trait BinaryConvertable {
+ fn size(&self) -> usize;
+
+ fn to_bytes(buffer: &mut [u8]);
+
+ fn from_bytes(buffer: &[u8]) -> Self;
+}
diff --git a/ipc/rpc/src/lib.rs b/ipc/rpc/src/lib.rs
index c2165b6e5..c771fb1b1 100644
--- a/ipc/rpc/src/lib.rs
+++ b/ipc/rpc/src/lib.rs
@@ -21,4 +21,4 @@ extern crate semver;
extern crate nanomsg;
pub mod interface;
-pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket};
+pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket, BinaryConvertable};