Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #118 from elmato/90-complete-abi-conversion
Browse files Browse the repository at this point in the history
complete abi conversion
  • Loading branch information
bytemaster authored Aug 1, 2017
2 parents 3722f03 + edd007e commit 9b37e1e
Show file tree
Hide file tree
Showing 3 changed files with 315 additions and 67 deletions.
254 changes: 188 additions & 66 deletions libraries/types/AbiSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,189 @@

namespace eos { namespace types {

template <typename T>
inline fc::variant variantFromStream(fc::datastream<const char*>& stream) {
T temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
}

AbiSerializer::AbiSerializer( const Abi& abi ) {
configureTypes();
setAbi(abi);
}

void AbiSerializer::configureTypes() {

native_types.emplace("UInt8", std::make_pair( []( auto& stream ) -> auto {
return variantFromStream<uint8_t>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<uint8_t>() );
}
));

native_types.emplace("UInt16", std::make_pair( []( auto& stream ) -> auto {
return variantFromStream<uint16_t>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<uint16_t>() );
}
));

native_types.emplace("UInt32", std::make_pair( []( auto& stream ) -> auto {
return variantFromStream<uint32_t>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<uint32_t>() );
}
));

native_types.emplace("UInt64", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<uint64_t>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<uint64_t>() );
}
));

native_types.emplace("UInt128", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<UInt128>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<UInt128>() );
}
));

native_types.emplace("UInt256", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<UInt256>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<UInt256>() );
}
));

native_types.emplace("Int8", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<int8_t>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<int8_t>() );
}
));

native_types.emplace("Int16", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<int16_t>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<int16_t>() );
}
));

native_types.emplace("Int32", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<int32_t>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<int32_t>() );
}
));

native_types.emplace("Int64", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<int64_t>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<int64_t>() );
}
));

// native_types.emplace("Int128", std::make_pair(
// []( auto& stream ) -> auto {
// return variantFromStream<__int128>(stream);
// },
// []( const fc::variant& var, fc::datastream<char*>& ds ){
// fc::raw::pack( ds, var.as<__int128>() );
// }
// ));

// native_types.emplace("Int256", std::make_pair(
// []( auto& stream ) -> auto {
// return variantFromStream<Int256>(stream);
// },
// []( const fc::variant& var, fc::datastream<char*>& ds ){
// fc::raw::pack( ds, var.as<Int256>() );
// }
// ));

native_types.emplace("Name", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<Name>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<Name>() );
}
));

native_types.emplace("Time", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<Time>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<Time>() );
}
));

// native_types.emplace("String", std::make_pair(
// []( auto& stream ) -> auto {
// return variantFromStream<String>(stream);
// },
// []( const fc::variant& var, fc::datastream<char*>& ds ){
// fc::raw::pack( ds, var.as<String>() );
// }
// ));

native_types.emplace("Checksum", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<Checksum>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<Checksum>() );
}
));

native_types.emplace("Signature", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<Signature>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<Signature>() );
}
));

native_types.emplace("FixedString32", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<FixedString32>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<FixedString32>() );
}
));

native_types.emplace("FixedString16", std::make_pair(
[]( auto& stream ) -> auto {
return variantFromStream<FixedString16>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds ){
fc::raw::pack( ds, var.as<FixedString16>() );
}
));
}

void AbiSerializer::setAbi( const Abi& abi ) {
typedefs.clear();
structs.clear();
Expand Down Expand Up @@ -37,16 +216,14 @@ namespace eos { namespace types {
}

bool AbiSerializer::isType( const TypeName& type )const {
static const std::set<TypeName> native = {"Name", "UInt8", "UInt32", "UInt64", "UInt128", "Time", "String"};
if( native.find(type) != native.end() ) return true;
if( native_types.find(type) != native_types.end() ) return true;
if( typedefs.find(type) != typedefs.end() ) return isType( typedefs.find(type)->second );
if( structs.find(type) != structs.end() ) return true;
return false;
}

const Struct& AbiSerializer::getStruct( const TypeName& type )const {
if( typedefs.find(type) != typedefs.end() ) return getStruct( typedefs.find(type)->second );
auto itr = structs.find(type);
auto itr = structs.find( resolveType(type) );
FC_ASSERT( itr != structs.end(), "Unknown struct ${type}", ("type",type) );
return itr->second;
}
Expand Down Expand Up @@ -82,7 +259,6 @@ namespace eos { namespace types {
const auto& st = getStruct( type );
if( st.base != TypeName() ) {
binaryToVariant( resolveType(st.base), stream, obj );
return;
}
for( const auto& field : st.fields ) {
obj( field.name, binaryToVariant( resolveType(field.type), stream ) );
Expand All @@ -92,41 +268,11 @@ namespace eos { namespace types {
fc::variant AbiSerializer::binaryToVariant(const TypeName& type, fc::datastream<const char*>& stream )const
{
TypeName rtype = resolveType( type );
if( rtype == "Name" ) {
Name temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
}
else if( rtype == "UInt8" ) {
unsigned char temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
}
else if( rtype == "UInt32" ) {
uint32_t temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
}
else if( rtype == "UInt64" ) {
uint64_t temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
}
else if( rtype == "UInt128" ) {
UInt128 temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
}
else if( rtype == "Time" ) {
Time temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
}
else if( rtype == "String" ) {
String temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
auto native_type = native_types.find(rtype);
if( native_type != native_types.end() ) {
return native_type->second.first(stream);
}

fc::mutable_variant_object mvo;
binaryToVariant( rtype, stream, mvo );
return fc::variant( std::move(mvo) );
Expand All @@ -141,33 +287,9 @@ namespace eos { namespace types {
{
auto rtype = resolveType(type);

if( rtype == "Name" ) {
fc::raw::pack( ds, var.as<Name>() );
return;
}
else if( rtype == "UInt8" ) {
fc::raw::pack( ds, var.as<unsigned char>() );
return;
}
else if( rtype == "UInt32" ) {
fc::raw::pack( ds, var.as<uint32_t>() );
return;
}
else if( rtype == "UInt64" ) {
fc::raw::pack( ds, var.as<uint64_t>() );
return;
}
else if( rtype == "UInt128" ) {
fc::raw::pack( ds, var.as<UInt128>() );
return;
}
else if( rtype == "Time" ) {
fc::raw::pack( ds, var.as<uint32_t>() );
return;
}
else if( rtype == "String" ) {
fc::raw::pack( ds, var.as<String>() );
return;
auto native_type = native_types.find(rtype);
if( native_type != native_types.end() ) {
native_type->second.second(var, ds);
} else {
const auto& st = getStruct( rtype );
const auto& vo = var.get_object();
Expand Down
10 changes: 9 additions & 1 deletion libraries/types/include/eos/types/AbiSerializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ namespace eos { namespace types {

using std::map;
using std::string;
using std::function;
using std::pair;

/**
* Describes the binary representation message and table contents so that it can
* be converted to and from JSON.
*/
struct AbiSerializer {
AbiSerializer(){}
AbiSerializer(){ configureTypes(); }
AbiSerializer( const Abi& abi );
void setAbi( const Abi& abi );

Expand All @@ -20,6 +22,12 @@ struct AbiSerializer {
map<Name,TypeName> actions;
map<Name,TypeName> tables;

typedef std::function<fc::variant(fc::datastream<const char*>&)> pack_function;
typedef std::function<void(const fc::variant&, fc::datastream<char*>&)> unpack_function;

map<TypeName, pair<pack_function, unpack_function>> native_types;
void configureTypes();

void validate()const;

TypeName resolveType( const TypeName& t )const;
Expand Down
Loading

0 comments on commit 9b37e1e

Please sign in to comment.