Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eos reflector verifier #168

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions include/fc/io/raw.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,19 +339,20 @@ namespace fc {
};

template<typename Stream, typename Class>
struct unpack_object_visitor {
unpack_object_visitor( Class& _c, Stream& _s, uint32_t _max_depth ) : c(_c),s(_s),max_depth(_max_depth - 1)
struct unpack_object_visitor : fc::reflector_verifier_visitor<Class> {
unpack_object_visitor( Class& _c, Stream& _s, uint32_t _max_depth )
: fc::reflector_verifier_visitor<Class>(_c), s(_s), max_depth(_max_depth - 1)
{
FC_ASSERT( _max_depth > 0 );
}

template<typename T, typename C, T(C::*p)>
inline void operator()( const char* name )const
{ try {
fc::raw::unpack( s, c.*p, max_depth );
fc::raw::unpack( s, this->obj.*p, max_depth );
} FC_RETHROW_EXCEPTIONS( warn, "Error unpacking field ${field}", ("field",name) ) }

private:
Class& c;
Stream& s;
const uint32_t max_depth;
};
Expand Down
77 changes: 77 additions & 0 deletions include/fc/reflect/reflect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,21 @@ struct reflector{
* };
* @endcode
*
* If reflection requires a verification (what a constructor might normally assert) then
* derive your Visitor from reflector_verifier_visitor and implement a reflector_verify()
* on your reflected type.
*
* @code
* template<typename Class>
* struct functor : reflector_verifier_visitor<Class> {
* functor(Class& _c)
* : fc::reflector_verifier_visitor<Class>(_c) {}
*
* template<typename Member, class Class, Member (Class::*member)>
* void operator()( const char* name )const;
* };
* @endcode
*
* If T is an enum then the functor has the following form:
* @code
* struct functor {
Expand All @@ -178,6 +193,37 @@ struct reflector{

void throw_bad_enum_cast( int64_t i, const char* e );
void throw_bad_enum_cast( const char* k, const char* e );

template <typename Class>
struct reflector_verifier_visitor {
explicit reflector_verifier_visitor( Class& c )
: obj(c) {}

void reflector_verify() {
reflect_verify( obj );
}

private:

// int matches 0 if reflector_verify exists SFINAE
template<class T>
auto verify_imp(const T& t, int) -> decltype(t.reflector_verify(), void()) {
t.reflector_verify();
}

// if no reflector_verify method exists (SFINAE), 0 matches long
template<class T>
auto verify_imp(const T& t, long) -> decltype(t, void()) {}

template<typename T>
auto reflect_verify(const T& t) -> decltype(verify_imp(t, 0), void()) {
verify_imp(t, 0);
}

protected:
Class& obj;
};

} // namespace fc


Expand Down Expand Up @@ -209,6 +255,7 @@ template<typename Visitor>\
static inline void visit( const Visitor& v ) { \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
verify( v ); \
}

#endif // DOXYGEN
Expand Down Expand Up @@ -316,6 +363,16 @@ template<> struct reflector<TYPE> {\
using members = typename typelist::concat<inherited_members, native_members>::type; \
using base_classes = typename typelist::builder<>::type \
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, int) -> decltype(v.reflector_verify(), void()) { \
v.reflector_verify(); \
} \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, long) -> decltype(v, void()) {} \
template<typename Visitor> \
static auto verify(const Visitor& v) -> decltype(verify_imp(v, 0), void()) { \
verify_imp(v, 0); \
} \
enum member_count_enum { \
local_member_count = typelist::length<native_members>(), \
total_member_count = typelist::length<members>() \
Expand Down Expand Up @@ -343,6 +400,16 @@ template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct reflector<TYPE> {\
using members = typename typelist::concat<inherited_members, native_members>::type; \
using base_classes = typename typelist::builder<>::type \
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, int) -> decltype(v.reflector_verify(), void()) { \
v.reflector_verify(); \
} \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, long) -> decltype(v, void()) {} \
template<typename Visitor> \
static auto verify(const Visitor& v) -> decltype(verify_imp(v, 0), void()) { \
verify_imp(v, 0); \
} \
enum member_count_enum { \
local_member_count = typelist::length<native_members>(), \
total_member_count = typelist::length<members>() \
Expand All @@ -367,6 +434,16 @@ template<> struct reflector<TYPE> {\
using members = typename typelist::concat<inherited_members, native_members>::type; \
using base_classes = typename typelist::builder<>::type \
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, int) -> decltype(v.reflector_verify(), void()) { \
v.reflector_verify(); \
} \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, long) -> decltype(v, void()) {} \
template<typename Visitor> \
static auto verify(const Visitor& v) -> decltype(verify_imp(v, 0), void()) { \
verify_imp(v, 0); \
} \
enum member_count_enum { \
local_member_count = typelist::length<native_members>(), \
total_member_count = typelist::length<members>() \
Expand Down
7 changes: 3 additions & 4 deletions include/fc/reflect/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ namespace fc
};

template<typename T>
class from_variant_visitor
class from_variant_visitor : reflector_verifier_visitor<T>
{
public:
from_variant_visitor( const variant_object& _vo, T& v, uint32_t max_depth )
:vo(_vo),val(v),_max_depth(max_depth - 1) {
: reflector_verifier_visitor<T>(v), vo(_vo), _max_depth(max_depth - 1) {
_FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
}

Expand All @@ -55,11 +55,10 @@ namespace fc
{
auto itr = vo.find(name);
if( itr != vo.end() )
from_variant( itr->value(), val.*member, _max_depth );
from_variant( itr->value(), this->obj.*member, _max_depth );
}

const variant_object& vo;
T& val;
const uint32_t _max_depth;
};

Expand Down