compilation fixed

This commit is contained in:
Nikolay Volf 2016-04-20 18:02:17 +03:00
parent 59e18ad659
commit 3908ddf609
6 changed files with 126 additions and 58 deletions

View File

@ -77,27 +77,28 @@ fn serialize_item(
_ => { _ => {
cx.span_err( cx.span_err(
item.span, item.span,
"`#[derive(Serialize)]` may only be applied to structs and enums"); "`#[derive(Binary)]` may only be applied to structs and enums");
return Err(Error); return Err(Error);
} }
}; };
let impl_generics = build_impl_generics(cx, builder, item, generics);
let ty = builder.ty().path() let ty = builder.ty().path()
.segment(item.ident).with_generics(impl_generics.clone()).build() .segment(item.ident).with_generics(generics.clone()).build()
.build(); .build();
let where_clause = &impl_generics.where_clause; let where_clause = &generics.where_clause;
let binary_expressions = try!(binary_expr(cx, let binary_expressions = try!(binary_expr(cx,
&builder, &builder,
&item, &item,
&impl_generics, &generics,
ty.clone())); ty.clone()));
let (size_expr, read_expr, write_expr) =
(binary_expressions.size, binary_expressions.read, binary_expressions.write);
Ok(quote_item!(cx, Ok(quote_item!(cx,
impl $impl_generics ::ipc::BinaryConvertable for $ty $where_clause { impl $generics ::ipc::BinaryConvertable for $ty $where_clause {
fn size(&self) -> usize { fn size(&self) -> usize {
$size_expr $size_expr
} }
@ -107,7 +108,7 @@ fn serialize_item(
} }
fn from_bytes(buffer: &[u8]) -> Self { fn from_bytes(buffer: &[u8]) -> Self {
$create_expr $read_expr
} }
} }
).unwrap()) ).unwrap())
@ -138,19 +139,21 @@ fn binary_expr(
item.ident, item.ident,
impl_generics, impl_generics,
ty, ty,
item.span,
enum_def, enum_def,
) )
} }
_ => { _ => {
cx.span_bug(item.span, cx.span_bug(item.span,
"expected ItemStruct or ItemEnum in #[derive(Serialize)]"); "expected ItemStruct or ItemEnum in #[derive(Binary)]");
Err(Error)
} }
} }
} }
struct BinaryExpressions { struct BinaryExpressions {
pub size: P<ast::Expr>, pub size: P<ast::Expr>,
pub write: P<ast::Stmt>, pub write: P<ast::Expr>,
pub read: P<ast::Expr>, pub read: P<ast::Expr>,
} }
@ -159,41 +162,44 @@ fn binary_expr_struct(
builder: &aster::AstBuilder, builder: &aster::AstBuilder,
ty: P<ast::Ty>, ty: P<ast::Ty>,
fields: &[ast::StructField], fields: &[ast::StructField],
value_ident: Option<P<ast::Ident>>, value_ident: Option<ast::Ident>,
) -> Result<BinaryExpressions, Error> { ) -> Result<BinaryExpressions, Error> {
let type_name = field.ty; let size_exprs: Vec<P<ast::Expr>> = fields.iter().enumerate().map(|(index, field)| {
let id = field.id;
let mut size_exprs = Vec::new();
fields.iter().enumerate(|(index, field)| {
let index_ident = builder.id(format!("{}", index)); let index_ident = builder.id(format!("{}", index));
value_ident.and_then(|value_ident| size_exprs.push(quote_expr!(cx, $value_ident . $index_ident .size()))) value_ident.and_then(|x| Some(quote_expr!(cx, $x . $index_ident .size())))
.unwrap_or_else(|| size_exprs.push(quote_expr!(cx, $index_ident .size()))); .unwrap_or_else(|| quote_expr!(cx, $index_ident .size()))
}); }).collect();
let mut total_size_expr = size_exprs[0].clone(); let mut total_size_expr = size_exprs[0].clone();
for index in 1..size_expr.len() { for index in 1..size_exprs.len() {
let next_expr = size_exprs[i].clone(); let next_expr = size_exprs[index].clone();
total_size_expr = quote_expr!(cx, $total_size_expr + $next_expr); total_size_expr = quote_expr!(cx, $total_size_expr + $next_expr);
} }
let mut write_stmts = Vec::new(); let mut write_stmts = Vec::<ast::Stmt>::new();
write_stmts.push(quote_stmt!(cx, let mut offset = 0usize;)); write_stmts.push(quote_stmt!(cx, let mut offset = 0usize;).unwrap());
fields.iter().enumerate(|(index, field)| { for (index, field) in fields.iter().enumerate() {
let index_ident = builder.id(format!("{}", index)); let index_ident = builder.id(format!("{}", index));
let size_expr = size_exprs[index]; let size_expr = &size_exprs[index];
write_stmts.push(quote_stmt!(cx, let next_line = offset + $size_expr; )); write_stmts.push(quote_stmt!(cx, let next_line = offset + $size_expr; ).unwrap());
value_ident.and_then(|x| match value_ident {
write_stmts.push(quote_stmt!(cx, $x . $index_ident .write(&mut buffer[offset..next_line]);)) Some(x) => {
).unwrap_or_else(|| write_stmts.push(quote_stmt!(cx, $index_ident .write(&mut buffer[offset..next_line]);))); write_stmts.push(
write_stmts.push(quote_stmt!(cx, offset = next_line; )); quote_stmt!(cx, $x . $index_ident .write(&mut buffer[offset..next_line]);).unwrap())
}); },
None => {
write_stmts.push(
quote_stmt!(cx, $index_ident .write(&mut buffer[offset..next_line]);).unwrap())
}
}
write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap());
};
Ok(BinaryExpressions { Ok(BinaryExpressions {
size: total_size_expr, size: total_size_expr,
write: quote_stmt!(cx, { $write_stmts } ), write: quote_expr!(cx, { write_stmts; Ok(()) } ),
read: quote_expr!(cx, $ty { }), read: quote_expr!(cx, $ty { }),
}); })
} }
fn binary_expr_item_struct( fn binary_expr_item_struct(
@ -211,6 +217,7 @@ fn binary_expr_item_struct(
&builder, &builder,
ty, ty,
fields, fields,
Some(builder.id("self")),
) )
} }
ast::VariantData::Struct(ref fields, _) => { ast::VariantData::Struct(ref fields, _) => {
@ -219,8 +226,13 @@ fn binary_expr_item_struct(
&builder, &builder,
ty, ty,
fields, fields,
Some(builder.id("self")),
) )
} },
_ => {
cx.span_bug(span, "#[derive(Binary)] Unsupported struct content, expected tuple/struct");
Err(Error)
},
} }
} }
@ -230,6 +242,7 @@ fn binary_expr_enum(
type_ident: Ident, type_ident: Ident,
impl_generics: &ast::Generics, impl_generics: &ast::Generics,
ty: P<ast::Ty>, ty: P<ast::Ty>,
span: Span,
enum_def: &ast::EnumDef, enum_def: &ast::EnumDef,
) -> Result<BinaryExpressions, Error> { ) -> Result<BinaryExpressions, Error> {
let arms: Vec<_> = try!( let arms: Vec<_> = try!(
@ -242,6 +255,7 @@ fn binary_expr_enum(
type_ident, type_ident,
impl_generics, impl_generics,
ty.clone(), ty.clone(),
span,
variant, variant,
variant_index, variant_index,
) )
@ -250,22 +264,21 @@ fn binary_expr_enum(
); );
let (size_arms, write_arms, read_arms) = ( let (size_arms, write_arms, read_arms) = (
arms.iter().map(|x| x.size).collect::<Vec<P<ast::Arm>>>(), arms.iter().map(|x| x.size.clone()).collect::<Vec<ast::Arm>>(),
arms.iter().map(|x| x.write).collect::<Vec<P<ast::Arm>>>(), arms.iter().map(|x| x.write.clone()).collect::<Vec<ast::Arm>>(),
arms.iter().map(|x| x.read).collect::<Vec<P<ast::Arm>>>()); arms.iter().map(|x| x.read.clone()).collect::<Vec<ast::Arm>>());
Ok(BinaryExpressions { Ok(BinaryExpressions {
size: quote_expr!(cx, match *self { $size_arms }), size: quote_expr!(cx, match *self { $size_arms }),
write: quote_stmt!(cx, match *self { $write_arms }; ), write: quote_expr!(cx, match *self { $write_arms }; ),
read: quote_expr!(cx, match *self { $read_arms }), read: quote_expr!(cx, match *self { $read_arms }),
}); })
} }
struct BinaryArm { struct BinaryArm {
size: P<ast::Arm>, size: ast::Arm,
write: P<ast::Arm>, write: ast::Arm,
read: P<ast::Arm>, read: ast::Arm,
} }
fn binary_expr_variant( fn binary_expr_variant(
@ -274,10 +287,11 @@ fn binary_expr_variant(
type_ident: Ident, type_ident: Ident,
generics: &ast::Generics, generics: &ast::Generics,
ty: P<ast::Ty>, ty: P<ast::Ty>,
span: Span,
variant: &ast::Variant, variant: &ast::Variant,
variant_index: usize, variant_index: usize,
) -> Result<BinaryArm, Error> { ) -> Result<BinaryArm, Error> {
let type_name = ty.name; let type_name = ::syntax::print::pprust::ty_to_string(&ty);
let variant_ident = variant.node.name; let variant_ident = variant.node.name;
@ -303,12 +317,12 @@ fn binary_expr_variant(
None, None,
)); ));
let (size_expr, write, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read);
Ok(BinaryArm { Ok(BinaryArm {
size: P(quote_arm!(cx, $pat => { $size_expr } )), size: quote_arm!(cx, $pat => { $size_expr } ),
write: P(quote_arm!(cx, $pat => { $write } )), write: quote_arm!(cx, $pat => { $write_expr } ),
read: P(quote_arm!(cx, $pat => { $read_expr } )), read: quote_arm!(cx, $pat => { $read_expr } ),
}) })
} }
ast::VariantData::Struct(ref fields, _) => { ast::VariantData::Struct(ref fields, _) => {
@ -321,7 +335,7 @@ fn binary_expr_variant(
.with_pats( .with_pats(
field_names.iter() field_names.iter()
.zip(fields.iter()) .zip(fields.iter())
.map(|(id, field)|(name, builder.pat().ref_id(id)))) .map(|(id, field)|(field.ident.unwrap(), builder.pat().ref_id(id))))
.build(); .build();
@ -333,12 +347,16 @@ fn binary_expr_variant(
None, None,
)); ));
let (size_expr, write, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read);
Ok(BinaryArm { Ok(BinaryArm {
size: P(quote_arm!(cx, $pat => { $size_expr } )), size: quote_arm!(cx, $pat => { $size_expr } ),
write: P(quote_arm!(cx, $pat => { $write } )), write: quote_arm!(cx, $pat => { $write_expr } ),
read: P(quote_arm!(cx, $pat => { $read_expr } )), read: quote_arm!(cx, $pat => { $read_expr } ),
}) })
} },
_ => {
cx.span_bug(span, "#[derive(Binary)] Unsupported struct content, expected tuple/struct");
Err(Error)
},
} }
} }

View File

@ -16,10 +16,12 @@
//! Binary representation of types //! Binary representation of types
pub trait BinaryConvertable { pub struct BinaryConvertError;
fn size(&self) -> usize;
fn to_bytes(buffer: &mut [u8]); pub trait BinaryConvertable : Sized {
fn size(&self) -> Result<usize, BinaryConvertError>;
fn from_bytes(buffer: &[u8]) -> Self; fn to_bytes(buffer: &mut [u8]) -> Result<(), BinaryConvertError>;
fn from_bytes(buffer: &[u8]) -> Result<Self, BinaryConvertError>;
} }

17
ipc/tests/binary.rs Normal file
View File

@ -0,0 +1,17 @@
// 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"), "/binary.rs"));

21
ipc/tests/binary.rs.in Normal file
View File

@ -0,0 +1,21 @@
// 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(Binary)]
enum Root {
Top,
Middle(String)
}

View File

@ -60,4 +60,13 @@ pub fn main() {
registry.expand("", &src, &dst).unwrap(); registry.expand("", &src, &dst).unwrap();
} }
// ipc pass
{
let src = Path::new("binary.rs.in");
let dst = Path::new(&out_dir).join("binary.rs");
let mut registry = syntex::Registry::new();
codegen::register(&mut registry);
registry.expand("", &src, &dst).unwrap();
}
} }

View File

@ -29,3 +29,4 @@ pub mod service;
mod examples; mod examples;
mod over_nano; mod over_nano;
mod nested; mod nested;
mod binary;