mapping and custom serializers
This commit is contained in:
parent
6149423e47
commit
a9cceefaa4
@ -33,6 +33,8 @@ use syntax::ext::base::{Annotatable, ExtCtxt};
|
|||||||
use syntax::ext::build::AstBuilder;
|
use syntax::ext::build::AstBuilder;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
|
||||||
|
use super::typegen;
|
||||||
|
|
||||||
pub struct Error;
|
pub struct Error;
|
||||||
|
|
||||||
const RESERVED_MESSAGE_IDS: u16 = 16;
|
const RESERVED_MESSAGE_IDS: u16 = 16;
|
||||||
@ -62,7 +64,10 @@ pub fn expand_ipc_implementation(
|
|||||||
push_client(cx, &builder, &item, &dispatches, push);
|
push_client(cx, &builder, &item, &dispatches, push);
|
||||||
push_handshake_struct(cx, push);
|
push_handshake_struct(cx, push);
|
||||||
|
|
||||||
push(Annotatable::Item(impl_item))
|
push(Annotatable::Item(impl_item));
|
||||||
|
|
||||||
|
let all_tys = dispatches.iter().flat_map(|ref dispatch| &dispatch.input_arg_tys).cloned().collect::<Vec<P<Ty>>>();
|
||||||
|
typegen::match_unknown_tys(cx, &builder, &all_tys, push);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_handshake_struct(cx: &ExtCtxt, push: &mut FnMut(Annotatable)) {
|
fn push_handshake_struct(cx: &ExtCtxt, push: &mut FnMut(Annotatable)) {
|
||||||
@ -333,6 +338,9 @@ fn implement_client_method_body(
|
|||||||
-> P<ast::Expr>
|
-> P<ast::Expr>
|
||||||
{
|
{
|
||||||
let request = if dispatch.input_arg_names.len() > 0 {
|
let request = if dispatch.input_arg_names.len() > 0 {
|
||||||
|
|
||||||
|
let substitutes = typegen::match_unknown_tys(cx, builder, dispatch.input_arg_tys
|
||||||
|
|
||||||
let arg_name = dispatch.input_arg_names[0].as_str();
|
let arg_name = dispatch.input_arg_names[0].as_str();
|
||||||
let arg_ty = builder
|
let arg_ty = builder
|
||||||
.ty().ref_()
|
.ty().ref_()
|
||||||
|
@ -15,3 +15,4 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
mod codegen;
|
mod codegen;
|
||||||
|
pub mod typegen;
|
||||||
|
198
ipc/codegen/src/typegen.rs
Normal file
198
ipc/codegen/src/typegen.rs
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
use aster;
|
||||||
|
|
||||||
|
use syntax::ast::{
|
||||||
|
MetaItem,
|
||||||
|
Item,
|
||||||
|
ImplItemKind,
|
||||||
|
ImplItem,
|
||||||
|
MethodSig,
|
||||||
|
Arg,
|
||||||
|
PatKind,
|
||||||
|
FunctionRetTy,
|
||||||
|
Ty,
|
||||||
|
TyKind,
|
||||||
|
Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
use syntax::ast;
|
||||||
|
use syntax::codemap::Span;
|
||||||
|
use syntax::ext::base::{Annotatable, ExtCtxt};
|
||||||
|
use syntax::ext::build::AstBuilder;
|
||||||
|
use syntax::ptr::P;
|
||||||
|
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
fn is_new_entry(builder: &aster::AstBuilder, path: &Path) -> Option<String> {
|
||||||
|
let known = {
|
||||||
|
if path.segments.len() > 1 {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
let ident = format!("{}", path.segments[0].identifier.name.as_str());
|
||||||
|
|
||||||
|
ident == "u32" ||
|
||||||
|
ident == "u64" ||
|
||||||
|
ident == "usize" ||
|
||||||
|
ident == "i32" ||
|
||||||
|
ident == "i64" ||
|
||||||
|
ident == "String" ||
|
||||||
|
ident == "Option"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if known { None }
|
||||||
|
else { Some(path_str(path)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_str(path: &Path) -> String {
|
||||||
|
let mut res: String = "_".to_owned();
|
||||||
|
for segment in path.segments.iter() {
|
||||||
|
res.push_str(&format!("{}_", segment.identifier.name.as_str()));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_bin_box(
|
||||||
|
cx: &ExtCtxt,
|
||||||
|
builder: &aster::AstBuilder,
|
||||||
|
ty: &Ty,
|
||||||
|
bbox_name: &str,
|
||||||
|
push: &mut FnMut(Annotatable),
|
||||||
|
) {
|
||||||
|
let ident = builder.id(bbox_name);
|
||||||
|
let bin_box_struct = quote_item!(cx,
|
||||||
|
struct $ident ($ty);
|
||||||
|
).unwrap();
|
||||||
|
push(Annotatable::Item(bin_box_struct));
|
||||||
|
push(Annotatable::Item(quote_item!(cx,
|
||||||
|
impl From<$ty> for $ident {
|
||||||
|
fn from(val: $ty) -> $ident {
|
||||||
|
$ident(val)
|
||||||
|
}
|
||||||
|
}).unwrap()));
|
||||||
|
|
||||||
|
push(Annotatable::Item(quote_item!(cx,
|
||||||
|
impl Into<$ty> for $ident {
|
||||||
|
fn into(self) -> $ty {
|
||||||
|
let $ident(val) = self;
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}).unwrap()));
|
||||||
|
|
||||||
|
|
||||||
|
let serialize_impl = quote_item!(cx,
|
||||||
|
impl ::serde::ser::Serialize for $ident {
|
||||||
|
fn serialize<__S>(&self, _serializer: &mut __S) -> ::std::result::Result<(), __S::Error>
|
||||||
|
where __S: ::serde::ser::Serializer
|
||||||
|
{
|
||||||
|
let &$ident(val) = self;
|
||||||
|
_serializer.serialize_bytes(val.as_slice())
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let ident_expr = builder.id(::syntax::print::pprust::ty_to_string(ty));
|
||||||
|
|
||||||
|
let deserialize_impl = quote_item!(cx,
|
||||||
|
impl ::serde::de::Deserialize for $ident {
|
||||||
|
fn deserialize<__D>(deserializer: &mut __D) -> ::std::result::Result<$ident, __D::Error>
|
||||||
|
where __D: ::serde::de::Deserializer
|
||||||
|
{
|
||||||
|
struct __Visitor<__D: ::serde::de::Deserializer>(::std::marker::PhantomData<__D>);
|
||||||
|
|
||||||
|
impl <__D: ::serde::de::Deserializer> ::serde::de::Visitor for __Visitor<__D> {
|
||||||
|
type Value = $ident;
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ident, __V::Error>
|
||||||
|
where __V: ::serde::de::SeqVisitor
|
||||||
|
{
|
||||||
|
let raw_bytes: Vec<u8> = try!(visitor.visit()).unwrap_or_else(|| Vec::new());
|
||||||
|
let inner = $ident_expr ::from_bytes(&raw_bytes).unwrap();
|
||||||
|
Ok($ident (inner))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
deserializer.deserialize_bytes(__Visitor::<__D>(::std::marker::PhantomData))
|
||||||
|
}
|
||||||
|
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
push(Annotatable::Item(serialize_impl));
|
||||||
|
push(Annotatable::Item(deserialize_impl));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn match_unknown_tys(
|
||||||
|
cx: &ExtCtxt,
|
||||||
|
builder: &aster::AstBuilder,
|
||||||
|
tys: &[P<Ty>],
|
||||||
|
push: &mut FnMut(Annotatable),
|
||||||
|
) -> HashMap<String, P<Ty>>
|
||||||
|
{
|
||||||
|
let mut hash_map = HashMap::new();
|
||||||
|
let mut fringe = Vec::new();
|
||||||
|
fringe.extend(tys);
|
||||||
|
let mut stop_list = HashSet::new();
|
||||||
|
let mut index = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if fringe.len() == 0 { break; }
|
||||||
|
let drained = fringe.drain(..1).collect::<Vec<&P<Ty>>>();
|
||||||
|
let ty = drained[0];
|
||||||
|
stop_list.insert(ty);
|
||||||
|
|
||||||
|
match ty.node {
|
||||||
|
TyKind::Vec(ref nested_ty) => {
|
||||||
|
if !stop_list.contains(nested_ty) {
|
||||||
|
fringe.push(nested_ty);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TyKind::FixedLengthVec(ref nested_ty, _) => {
|
||||||
|
if !stop_list.contains(nested_ty) {
|
||||||
|
fringe.push(nested_ty);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TyKind::Path(_, ref path) => {
|
||||||
|
if path.segments.len() > 0 && path.segments[0].identifier.name.as_str() == "Option" ||
|
||||||
|
path.segments[0].identifier.name.as_str() == "Result" {
|
||||||
|
for extra_type in path.segments[0].parameters.types() {
|
||||||
|
if !stop_list.contains(extra_type) {
|
||||||
|
fringe.push(extra_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match is_new_entry(builder, path) {
|
||||||
|
Some(old_path) => {
|
||||||
|
if hash_map.get(&old_path).is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bin_box_name = format!("BinBox{}", index);
|
||||||
|
push_bin_box(cx, builder, &ty, &bin_box_name, push);
|
||||||
|
hash_map.insert(old_path, builder.ty().id(&bin_box_name));
|
||||||
|
index = index + 1;
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => { panic!("bad parameter in input args: {:?}", ty) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_map
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "ethcore-bin-serde"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Nikolay Volf"]
|
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
bincode = "*"
|
|
||||||
serde = "0.7.0"
|
|
||||||
ethcore-devtools = { path = "../../devtools" }
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
syntex = "*"
|
|
||||||
serde_codegen = "0.7.0"
|
|
@ -1,30 +0,0 @@
|
|||||||
// 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
extern crate syntex;
|
|
||||||
extern crate serde_codegen;
|
|
||||||
|
|
||||||
use std::env;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
|
||||||
let src = Path::new("src/lib.rs.in");
|
|
||||||
let dst = Path::new(&out_dir).join("lib.rs");
|
|
||||||
let mut registry = syntex::Registry::new();
|
|
||||||
serde_codegen::register(&mut registry);
|
|
||||||
registry.expand("", &src, &dst).unwrap();
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
// 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
|
|
@ -1,18 +0,0 @@
|
|||||||
// 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct BinBox<T: FromRawBytes + BytesConvertable>([u8; mem::size_of<T>()]);
|
|
@ -15,7 +15,7 @@ ethcore-devtools = { path = "../../devtools" }
|
|||||||
semver = "0.2.0"
|
semver = "0.2.0"
|
||||||
nanomsg = "0.5.0"
|
nanomsg = "0.5.0"
|
||||||
ethcore-ipc-nano = { path = "../nano" }
|
ethcore-ipc-nano = { path = "../nano" }
|
||||||
|
ethcore-util = { path = "../../util" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
syntex = "*"
|
syntex = "*"
|
||||||
|
@ -21,6 +21,7 @@ extern crate ethcore_devtools as devtools;
|
|||||||
extern crate semver;
|
extern crate semver;
|
||||||
extern crate nanomsg;
|
extern crate nanomsg;
|
||||||
extern crate ethcore_ipc_nano as nanoipc;
|
extern crate ethcore_ipc_nano as nanoipc;
|
||||||
|
extern crate ethcore_util as util;
|
||||||
|
|
||||||
pub mod service;
|
pub mod service;
|
||||||
mod examples;
|
mod examples;
|
||||||
|
@ -16,13 +16,32 @@
|
|||||||
|
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
|
use std::convert::*;
|
||||||
use ipc::IpcConfig;
|
use ipc::IpcConfig;
|
||||||
|
use util::bytes::{FromRawBytes, BytesConvertable, FromBytesError};
|
||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
pub commits: RwLock<usize>,
|
pub commits: RwLock<usize>,
|
||||||
pub rollbacks: RwLock<usize>,
|
pub rollbacks: RwLock<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CustomData {
|
||||||
|
a: usize,
|
||||||
|
b: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRawBytes for CustomData {
|
||||||
|
fn from_bytes(bytes: &[u8]) -> Result<CustomData, FromBytesError> {
|
||||||
|
Ok(CustomData { a: bytes[0] * 256 + bytes[1], b: bytes[2] * 256 + bytes[3]})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BytesConvertable for CustomData {
|
||||||
|
fn bytes(&self) -> &[u8] {
|
||||||
|
unsafe { &::std::mem::transmute::<[u8;8]>(self) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Ipc)]
|
#[derive(Ipc)]
|
||||||
impl Service {
|
impl Service {
|
||||||
fn commit(&self, f: u32) -> u32 {
|
fn commit(&self, f: u32) -> u32 {
|
||||||
@ -36,6 +55,15 @@ impl Service {
|
|||||||
*lock = *lock + a_0 as usize - b as usize;
|
*lock = *lock + a_0 as usize - b as usize;
|
||||||
(a_0 - b) as i32
|
(a_0 - b) as i32
|
||||||
}
|
}
|
||||||
|
pub fn push_custom(&self, data: CustomData) -> bool {
|
||||||
|
let clock = self.commits.write().unwrap();
|
||||||
|
let rlock = self.commits.write().unwrap();
|
||||||
|
|
||||||
|
*clock = data.a;
|
||||||
|
*rlock = data.b;
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Service {
|
impl Service {
|
||||||
|
Loading…
Reference in New Issue
Block a user