Skip to content

Commit

Permalink
Made changes necessary to serialize/deserialize ABI (for EOSIO/eos#354):
Browse files Browse the repository at this point in the history
* Modularized `intialize_types` to allow more than one subset of the types available to the program to be initialized into their own ABI.
  This was needed to bootstrap serializing the ABI itself, but also will be helpful in later unit tests.
* Changed deserializer for custom builtins to use conversion constructor (and copy/move assignment operator) rather than the custom
  assignment operator I was initially using to allow the same code to work with enumerations as well.
* Added support to reflect pairs/tuples which are just treated as structs (using mangled C++ type name)
  with anonymous fields (in ABI the fields are named f0, f1, ... ).
* With the above changes, I had the necessary tools to reflect `ABI`.
  Now the `ABI` struct is reflected with the same type system which it can describe, and so a serialized version of a contracts ABI can
  be included in a transaction (as a possible alternative to using `fc::pack` and `fc::unpack`).
  I also demonstrated constructing the `types_manager` from a serialized ABI by modifying the `reflection_test1` example.
  • Loading branch information
arhag committed Sep 20, 2017
1 parent 8f2ff41 commit 8a095d0
Show file tree
Hide file tree
Showing 13 changed files with 429 additions and 184 deletions.
75 changes: 9 additions & 66 deletions libraries/types/include/eos/types/abi.hpp
Original file line number Diff line number Diff line change
@@ -1,68 +1,11 @@
#pragma once

#include <eos/types/type_id.hpp>
#include <string>
#include <vector>
#include <utility>

namespace eos { namespace types {

using std::string;
using std::vector;
using std::pair;

struct ABI
{
enum type_specification : uint8_t
{
struct_type,
array_type,
vector_type,
optional_type,
variant_type
};

struct type_definition
{
uint32_t first;
int32_t second;
type_specification ts;
};

struct struct_t
{
string name;
vector<pair<string, type_id>> fields;
vector<int16_t> sort_order;
};

struct table_index
{
type_id key_type;
bool unique;
bool ascending;
vector<uint16_t> mapping;
};

struct table
{
type_id::index_t object_index;
vector<table_index> indices;
};


vector<type_definition> types;
vector<struct_t> structs;
vector<type_id> variant_cases;
vector<table> tables;
};

} }

/*
EOS_TYPES_REFLECT_STRUCT( type_definition, (first)(second)(ts) );
EOS_TYPES_REFLECT_STRUCT( struct_t, (name)(fields)(sort_order) );
EOS_TYPES_REFLECT_STRUCT( table_index, (key_type)(unique)(ascending)(mapping) );
EOS_TYPES_REFLECT_STRUCT( table, (name)(object_index)(indices) );
EOS_TYPES_REFLECT_STRUCT( ABI, (types)(structs)(variant_cases)(tables) );
*/
#include <eos/types/abi_definition.hpp>
#include <eos/types/reflect.hpp>

EOS_TYPES_REFLECT_BUILTIN( eos::types::ABI::type_specification, builtin_uint8 )
EOS_TYPES_REFLECT_STRUCT( eos::types::ABI::type_definition, (first)(second)(ts) )
EOS_TYPES_REFLECT_STRUCT( eos::types::ABI::struct_t, (name)(fields)(sort_order) )
EOS_TYPES_REFLECT_STRUCT( eos::types::ABI::table_index, (key_type)(unique)(ascending)(mapping) )
EOS_TYPES_REFLECT_STRUCT( eos::types::ABI::table, (object_index)(indices) )
EOS_TYPES_REFLECT_STRUCT( eos::types::ABI, (types)(structs)(variant_cases)(tables) )
2 changes: 1 addition & 1 deletion libraries/types/include/eos/types/abi_constructor.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <eos/types/abi.hpp>
#include <eos/types/abi_definition.hpp>

#include <set>
#include <map>
Expand Down
63 changes: 63 additions & 0 deletions libraries/types/include/eos/types/abi_definition.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include <eos/types/type_id.hpp>

#include <string>
#include <vector>
#include <utility>

namespace eos { namespace types {

using std::string;
using std::vector;
using std::pair;

struct ABI
{
enum type_specification : uint8_t
{
struct_type,
array_type,
vector_type,
optional_type,
variant_type
};

struct type_definition
{
uint32_t first;
int32_t second;
type_specification ts;
};

struct struct_t
{
string name;
vector<pair<string, type_id>> fields;
vector<int16_t> sort_order;
};

struct table_index
{
type_id key_type;
bool unique;
bool ascending;
vector<uint16_t> mapping;
};

struct table
{
type_id::index_t object_index;
vector<table_index> indices;
};


vector<type_definition> types;
vector<struct_t> structs;
vector<type_id> variant_cases;
vector<table> tables;
};

} }


25 changes: 19 additions & 6 deletions libraries/types/include/eos/types/deserialize_visitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace eos { namespace types {

#define EOS_TYPES_CUSTOM_BUILTIN_PRIMITIVE( builtin_name, primitive_type ) \
EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( builtin_name ) \
b = r.get<primitive_type>(offset); \
b = static_cast<B>(r.get<primitive_type>(offset)); \
EOS_TYPES_CUSTOM_BUILTIN_MATCH_END

EOS_TYPES_CUSTOM_BUILTIN_PRIMITIVE( int8, int8_t )
Expand Down Expand Up @@ -98,9 +98,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END
eos::types::reflector<Base>::visit(b, vis);
}

template<typename Member, class Class, Member (Class::*member)>
typename std::enable_if<eos::types::reflector<Class>::is_struct::value>::type
operator()(Class& c, const char* name, uint32_t member_index)const
deserialize_visitor make_visitor_for_product_type_member( uint32_t member_index )const
{
auto f = tm.get_member(tid.get_type_index(), member_index);
auto member_tid = f.get_type_id();
Expand All @@ -114,11 +112,26 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END
{
member_offset += f.get_offset();
}

deserialize_visitor vis(tm, r, member_tid, member_offset);

return {tm, r, member_tid, member_offset};
}

template<typename Member, class Class, Member (Class::*member)>
typename std::enable_if<eos::types::reflector<Class>::is_struct::value>::type
operator()(Class& c, const char* name, uint32_t member_index)const
{
auto vis = make_visitor_for_product_type_member(member_index);
eos::types::reflector<Member>::visit(c.*member, vis);
}

template<typename Member, class Class, size_t Index> // Meant for tuples/pairs
typename std::enable_if<eos::types::reflector<Class>::is_struct::value>::type
operator()(Class& c)const
{
auto vis = make_visitor_for_product_type_member(static_cast<uint32_t>(Index));
eos::types::reflector<Member>::visit(std::get<Index>(c), vis);
}

template<class Container>
typename std::enable_if<eos::types::reflector<Container>::is_array::value>::type
operator()(Container& c)const
Expand Down
Loading

0 comments on commit 8a095d0

Please sign in to comment.