#pragma once #include #include namespace fc { template void to_variant( const T& o, variant& v, uint32_t max_depth ); template void from_variant( const variant& v, T& o, uint32_t max_depth ); template class to_variant_visitor { public: to_variant_visitor( mutable_variant_object& mvo, const T& v, uint32_t max_depth ) :vo(mvo),val(v),_max_depth(max_depth - 1) { _FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" ); } template void operator()( const char* name )const { this->add(vo,name,(val.*member)); } private: template void add( mutable_variant_object& vo, const char* name, const optional& v )const { if( v.valid() ) vo(name, variant( *v, _max_depth )); } template void add( mutable_variant_object& vo, const char* name, const M& v )const { vo(name, variant( v, _max_depth )); } mutable_variant_object& vo; const T& val; const uint32_t _max_depth; }; template class from_variant_visitor { public: from_variant_visitor( const variant_object& _vo, T& v, uint32_t max_depth ) :vo(_vo),val(v),_max_depth(max_depth - 1) { _FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" ); } template void operator()( const char* name )const { auto itr = vo.find(name); if( itr != vo.end() ) from_variant( itr->value(), val.*member, _max_depth ); } const variant_object& vo; T& val; const uint32_t _max_depth; }; template struct if_enum; template struct if_enum::value>> { static inline void to_variant( const T& v, fc::variant& vo, uint32_t max_depth ) { mutable_variant_object mvo; fc::reflector::visit( to_variant_visitor( mvo, v, max_depth ) ); vo = std::move(mvo); } static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth ) { const variant_object& vo = v.get_object(); fc::reflector::visit( from_variant_visitor( vo, o, max_depth ) ); } }; template struct if_enum::value>> { static inline void to_variant( const T& o, fc::variant& v, uint32_t max_depth = 1 ) { v = fc::reflector::to_fc_string(o); } static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth = 1 ) { if( v.is_string() ) o = fc::reflector::from_string( v.get_string().c_str() ); else o = fc::reflector::from_int( v.as_int64() ); } }; namespace detail { template using void_t = void; template struct has_custom_variant_conversion : std::false_type {}; template struct has_custom_variant_conversion().fc_to_variant(std::declval(), 1)), decltype(std::declval().fc_from_variant(std::declval(), 1))>> : std::true_type {}; template::value, bool> = true> void to_variant( const T& o, variant& v, uint32_t max_depth ) { if_enum::to_variant( o, v, max_depth ); } template::value, bool> = true> void to_variant( const T& o, variant& v, uint32_t max_depth ) { o.fc_to_variant(v, max_depth); } template::value, bool> = true> void from_variant( const variant& v, T& o, uint32_t max_depth ) { if_enum::from_variant( v, o, max_depth ); } template::value, bool> = true> void from_variant( const variant& v, T& o, uint32_t max_depth ) { o.fc_from_variant(v, max_depth); } } // namespace detail template void to_variant( const T& o, variant& v, uint32_t max_depth ) { detail::to_variant(o, v, max_depth); } template void from_variant( const variant& v, T& o, uint32_t max_depth ) { detail::from_variant(v, o, max_depth); } }