diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index bfaa8e7e0..1af35422c 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -108,8 +108,7 @@ fn serialize_item( } fn from_bytes(buffer: &[u8]) -> Result { - //$read_expr - Err(::ipc::BinaryConvertError) + $read_expr } } ).unwrap()) @@ -164,6 +163,7 @@ fn binary_expr_struct( ty: P, fields: &[ast::StructField], value_ident: Option, + instance_ident: Option, ) -> Result { let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { let index_ident = builder.id(format!("__field{}", index)); @@ -182,6 +182,11 @@ fn binary_expr_struct( let mut write_stmts = Vec::::new(); write_stmts.push(quote_stmt!(cx, let mut offset = 0usize;).unwrap()); + + let mut map_stmts = Vec::::new(); + let field_amount = builder.id(&format!("{}",fields.len())); + map_stmts.push(quote_stmt!(cx, let mut map = vec![0usize; $field_amount];).unwrap()); + map_stmts.push(quote_stmt!(cx, let mut total = 0usize;).unwrap()); for (index, field) in fields.iter().enumerate() { let size_expr = &size_exprs[index]; write_stmts.push(quote_stmt!(cx, let next_line = offset + $size_expr; ).unwrap()); @@ -198,12 +203,26 @@ fn binary_expr_struct( } } write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap()); + + let field_index = builder.id(&format!("{}", index)); + let field_type_ident = builder.id(&::syntax::print::pprust::ty_to_string(&field.ty)); + map_stmts.push(quote_stmt!(cx, map[$field_index] = total;).unwrap()); + map_stmts.push(quote_stmt!(cx, total = total + mem::size_of::<$field_type_ident>();).unwrap()); + }; + + let read_expr = if value_ident.is_some() { + let instance_create = named_fields_sequence(cx, &ty, fields); + quote_expr!(cx, { $map_stmts; $instance_create; Ok(result) }) + } + else { + let map_variant = P(fields_sequence(cx, &ty, fields, &instance_ident.unwrap_or(builder.id("Self")))); + quote_expr!(cx, { $map_stmts; Ok($map_variant) }) }; Ok(BinaryExpressions { size: total_size_expr, write: quote_expr!(cx, { $write_stmts; Ok(()) } ), - read: quote_expr!(cx, Err(::ipc::BinaryConvertError)), + read: read_expr, }) } @@ -223,6 +242,7 @@ fn binary_expr_item_struct( ty, fields, Some(builder.id("self")), + None, ) } ast::VariantData::Struct(ref fields, _) => { @@ -232,6 +252,7 @@ fn binary_expr_item_struct( ty, fields, Some(builder.id("self")), + None, ) }, _ => { @@ -270,15 +291,17 @@ fn binary_expr_enum( .collect() ); - let (size_arms, write_arms, read_arms) = ( + let (size_arms, write_arms, mut read_arms) = ( arms.iter().map(|x| x.size.clone()).collect::>(), arms.iter().map(|x| x.write.clone()).collect::>(), arms.iter().map(|x| x.read.clone()).collect::>()); + read_arms.push(quote_arm!(cx, _ => { Err(BinaryConvertError) } )); + Ok(BinaryExpressions { size: quote_expr!(cx, 1usize + match *self { $size_arms }), write: quote_expr!(cx, match *self { $write_arms }; ), - read: quote_expr!(cx, match *self { $read_arms }), + read: quote_expr!(cx, match buffer[0] { $read_arms }), }) } @@ -288,6 +311,132 @@ struct BinaryArm { read: ast::Arm, } +fn fields_sequence( + ext_cx: &ExtCtxt, + ty: &P, + fields: &[ast::StructField], + variant_ident: &ast::Ident, +) -> ast::Expr { + use syntax::parse::token; + use syntax::ast::TokenTree::Token; + + ::quasi::parse_expr_panic(&mut ::syntax::parse::new_parser_from_tts( + ext_cx.parse_sess(), + ext_cx.cfg(), + { + let _sp = ext_cx.call_site(); + let mut tt = ::std::vec::Vec::new(); + tt.push(Token(_sp, token::Ident(variant_ident.clone(), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + + for (idx, field) in fields.iter().enumerate() { + if field.ident.is_some() { + tt.push(Token(_sp, token::Ident(field.ident.clone().unwrap(), token::Plain))); + tt.push(Token(_sp, token::Colon)); + } + + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("try!"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + tt.push(Token( + _sp, + token::Ident( + ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty)), + token::Plain))); + tt.push(Token(_sp, token::ModSep)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("from_bytes"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + + tt.push(Token(_sp, token::BinOp(token::And))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer"), token::Plain))); + + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::DotDot)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + tt.push(Token(_sp, token::Comma)); + } + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + + tt + }) + ).unwrap() +} + +fn named_fields_sequence( + ext_cx: &ExtCtxt, + ty: &P, + fields: &[ast::StructField], +) -> ast::Stmt { + use syntax::parse::token; + use syntax::ast::TokenTree::Token; + + ::quasi::parse_stmt_panic(&mut ::syntax::parse::new_parser_from_tts( + ext_cx.parse_sess(), + ext_cx.cfg(), + { + let _sp = ext_cx.call_site(); + let mut tt = ::std::vec::Vec::new(); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("let"), token::Plain))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("result"), token::Plain))); + tt.push(Token(_sp, token::Eq)); + + tt.push(Token( + _sp, + token::Ident( + ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(ty)), + token::Plain))); + + tt.push(Token(_sp, token::OpenDelim(token::Brace))); + + for (idx, field) in fields.iter().enumerate() { + tt.push(Token(_sp, token::Ident(field.ident.clone().unwrap(), token::Plain))); + tt.push(Token(_sp, token::Colon)); + + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("try!"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + tt.push(Token( + _sp, + token::Ident( + ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(&field.ty)), + token::Plain))); + tt.push(Token(_sp, token::ModSep)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("from_bytes"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Paren))); + + tt.push(Token(_sp, token::BinOp(token::And))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer"), token::Plain))); + + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::DotDot)); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map"), token::Plain))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1)), token::Plain))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + tt.push(Token(_sp, token::CloseDelim(token::Paren))); + tt.push(Token(_sp, token::Comma)); + } + + tt.push(Token(_sp, token::CloseDelim(token::Brace))); + tt + }) + ).unwrap() +} + fn binary_expr_variant( cx: &ExtCtxt, builder: &aster::AstBuilder, @@ -309,10 +458,12 @@ fn binary_expr_variant( .id(type_ident).id(variant_ident) .build(); + let variant_val = builder.id(format!("{}::{}", type_ident, variant_ident)); + Ok(BinaryArm { size: quote_arm!(cx, $pat => { 0usize } ), write: quote_arm!(cx, $pat => { buffer[0] = $variant_index_ident; Ok(()) } ), - read: quote_arm!(cx, $pat => { } ), + read: quote_arm!(cx, $variant_index_ident => { Ok($variant_val) } ), }) }, ast::VariantData::Tuple(ref fields, _) => { @@ -334,6 +485,7 @@ fn binary_expr_variant( ty, fields, None, + Some(builder.id(format!("{}::{}", type_ident, variant_ident))), )); let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); @@ -345,7 +497,7 @@ fn binary_expr_variant( let buffer = &mut buffer[1..]; $write_expr }), - read: quote_arm!(cx, $pat => { $read_expr } ), + read: quote_arm!(cx, $variant_index_ident => { $read_expr } ), }) } ast::VariantData::Struct(ref fields, _) => { @@ -368,6 +520,7 @@ fn binary_expr_variant( ty, fields, None, + Some(builder.id(format!("{}::{}", type_ident, variant_ident))), )); let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in index a4f2b7538..028fb9800 100644 --- a/ipc/tests/binary.rs.in +++ b/ipc/tests/binary.rs.in @@ -15,15 +15,12 @@ // along with Parity. If not, see . use ipc::*; +use std::mem; #[derive(Binary)] enum Root { Top, Middle(u32, u64), - Bottom { - number1: u32, - number2: u64, - }, } #[derive(Binary)]