6 #ifndef TURI_TOOLKIT_FUNCTION_WRAPPER_IMPL_HPP 7 #define TURI_TOOLKIT_FUNCTION_WRAPPER_IMPL_HPP 9 #include <boost/mpl/vector.hpp> 10 #include <boost/mpl/size.hpp> 11 #include <boost/mpl/contains.hpp> 12 #include <boost/mpl/assert.hpp> 13 #include <boost/mpl/int.hpp> 14 #include <boost/mpl/placeholders.hpp> 15 #include <boost/mpl/range_c.hpp> 16 #include <boost/mpl/transform.hpp> 17 #include <boost/fusion/mpl.hpp> 18 #include <boost/fusion/mpl/at.hpp> 19 #include <boost/fusion/include/vector.hpp> 20 #include <boost/fusion/include/as_vector.hpp> 21 #include <boost/fusion/algorithm/iteration/for_each.hpp> 22 #include <boost/fusion/functional/invocation/invoke.hpp> 23 #include <boost/type_traits.hpp> 24 #include <boost/type_traits/function_traits.hpp> 25 #include <model_server/lib/toolkit_function_invocation.hpp> 26 #include <model_server/lib/toolkit_function_specification.hpp> 27 #include <model_server/lib/toolkit_util.hpp> 29 namespace toolkit_function_wrapper_impl {
48 template <
typename Fn>
50 template <
typename R,
typename... T>
51 static boost::mpl::vector<T...> function_args_to_mpl_vector_helper(R (*)(T...)) {
52 return boost::mpl::vector<T...>();
55 typedef decltype(function_args_to_mpl_vector_helper(reinterpret_cast<Fn>(NULL))) type;
111 template <
typename T>
114 static constexpr
bool is_void =
false;
115 template <
typename F>
128 static constexpr
bool is_void =
true;
129 template <
typename F>
143 template<
typename Sig>
147 struct result<make_pointer_to(T&)>
153 T* operator()(T& t)
const 163 template <
typename T>
165 return variant_get_value<T>(var);
175 inline variant_map_type read_arg<variant_map_type>(
const variant_type& var) {
176 if (var.which() == 0) {
177 const flexible_type& ft = variant_get_ref<flexible_type>(var);
182 variant_map_type ret;
190 return variant_get_value<variant_map_type>(var);
214 template <
typename InArgType>
217 std::vector<std::string> inargnames;
218 variant_map_type* params;
221 void operator()(boost::mpl::integral_c<int, n> t)
const {
223 typedef typename std::decay<decltype(boost::fusion::at_c<n>(*inargs))>::type element_type;
224 if (n < inargnames.size()) {
225 variant_map_type::const_iterator kv = params->find(inargnames[n]);
226 if (kv == params->end()) {
227 std_log_and_throw(std::invalid_argument,
228 "Missing toolkit function parameter: " + inargnames[n]);
231 boost::fusion::at_c<n>(*inargs) = read_arg<element_type>(kv->second);
253 template <
typename InArgType>
256 const std::vector<variant_type>* params;
259 void operator()(boost::mpl::integral_c<int, n> t)
const {
261 typedef typename std::decay<decltype(boost::fusion::at_c<n>(*inargs))>::type element_type;
262 if (n < params->size()) {
263 boost::fusion::at_c<n>(*inargs) = variant_get_value<element_type>((*params)[n]);
277 typedef typename boost::mpl::range_c<int, 0, N>::type type;
288 template <
size_t Start,
size_t End>
290 typedef typename boost::mpl::range_c<int, Start, End>::type type;
311 template <
size_t NumInArgs,
typename Function>
312 std::function<variant_type(variant_map_type)>
313 generate_function_wrapper(Function fn, std::vector<std::string> inargnames) {
315 using boost::mpl::erase;
316 using boost::mpl::size;
317 using boost::mpl::int_;
318 using boost::mpl::_1;
323 typedef boost::function_traits<typename std::remove_pointer<Function>::type > fntraits;
327 typedef typename boost::mpl::transform<fn_args_type_original, std::decay<_1>>::type fn_args_type;
329 static_assert(size<fn_args_type>::value == NumInArgs,
330 "Invalid number arguments. #input != #function arguments.");
331 typedef fn_args_type in_arg_types;
337 typename boost::fusion::result_of::as_vector<in_arg_types>::type in_args;
347 in_arg_filler.params = &args;
348 in_arg_filler.inargnames = inargnames;
349 in_arg_filler.inargs = &in_args;
351 boost::fusion::for_each(in_arg_range, in_arg_filler);
356 return boost::fusion::invoke(fn, in_args);
382 template <
size_t NumInArgs,
typename Function>
383 std::function<variant_type(const std::vector<variant_type>&)>
384 generate_native_function_wrapper(Function fn) {
386 using boost::mpl::erase;
387 using boost::mpl::size;
388 using boost::mpl::int_;
389 using boost::mpl::_1;
394 typedef boost::function_traits<typename std::remove_pointer<Function>::type > fntraits;
398 typedef typename boost::mpl::transform<fn_args_type_original, std::decay<_1>>::type fn_args_type;
400 static_assert(size<fn_args_type>::value == NumInArgs,
401 "Invalid number arguments. #input != #function arguments.");
402 typedef fn_args_type in_arg_types;
405 [fn](
const std::vector<variant_type>& args)->
variant_type {
406 if (args.size() != fntraits::arity) {
407 throw std::string(
"Insufficient arguments");
410 typename boost::fusion::result_of::as_vector<in_arg_types>::type in_args;
420 in_arg_filler.params = &args;
421 in_arg_filler.inargs = &in_args;
423 boost::fusion::for_each(in_arg_range, in_arg_filler);
428 return boost::fusion::invoke(fn, in_args);
456 template <
size_t NumInArgs,
typename T,
typename Ret,
typename... Args>
457 std::function<variant_type(T*, variant_map_type)>
458 generate_member_function_wrapper(Ret (T::* fn)(Args...),
459 std::vector<std::string> inargnames) {
461 using boost::mpl::erase;
462 using boost::mpl::size;
463 using boost::mpl::int_;
464 using boost::mpl::_1;
469 auto member_fn = std::mem_fn(fn);
471 typedef typename boost::mpl::vector<T*, Args...>::type fn_args_type_original;
473 typedef typename boost::mpl::transform<fn_args_type_original, std::decay<_1>>::type fn_args_type;
475 static_assert(size<fn_args_type>::value == NumInArgs + 1,
476 "Invalid number arguments. #input != #function arguments.");
477 typedef fn_args_type in_arg_types;
479 inargnames.insert(inargnames.begin(),
"");
482 [member_fn, inargnames](T* t, variant_map_type args)->
variant_type {
485 typename boost::fusion::result_of::as_vector<in_arg_types>::type in_args;
494 boost::fusion::at_c<0>(in_args) = t;
496 in_arg_filler.params = &args;
497 in_arg_filler.inargnames = inargnames;
498 in_arg_filler.inargs = &in_args;
500 boost::fusion::for_each(in_arg_range, in_arg_filler);
505 return boost::fusion::invoke(member_fn, in_args);
535 template <
size_t NumInArgs,
typename T,
typename Ret,
typename... Args>
536 std::function<variant_type(T*, variant_map_type)>
537 generate_const_member_function_wrapper(Ret (T::* fn)(Args...)
const,
538 std::vector<std::string> inargnames) {
540 using boost::mpl::erase;
541 using boost::mpl::size;
542 using boost::mpl::int_;
543 using boost::mpl::_1;
548 auto member_fn = std::mem_fn(fn);
550 typedef typename boost::mpl::vector<T*, Args...>::type fn_args_type_original;
552 typedef typename boost::mpl::transform<fn_args_type_original, std::decay<_1>>::type fn_args_type;
554 static_assert(size<fn_args_type>::value == NumInArgs + 1,
555 "Invalid number arguments. #input != #function arguments.");
556 typedef fn_args_type in_arg_types;
558 inargnames.insert(inargnames.begin(),
"");
561 [member_fn, inargnames](T* t, variant_map_type args)->
variant_type {
564 typename boost::fusion::result_of::as_vector<in_arg_types>::type in_args;
573 boost::fusion::at_c<0>(in_args) = t;
575 in_arg_filler.params = &args;
576 in_arg_filler.inargnames = inargnames;
577 in_arg_filler.inargs = &in_args;
579 boost::fusion::for_each(in_arg_range, in_arg_filler);
584 return boost::fusion::invoke(member_fn, in_args);
680 template <
size_t NumInArgs,
typename Function>
682 std::vector<std::string> inargnames) {
685 auto fnwrapper = generate_function_wrapper<NumInArgs, Function>(fn, inargnames);
686 auto native_fn_wrapper = generate_native_function_wrapper<NumInArgs, Function>(fn);
693 ret.
params[
"return_value"] = val;
696 }
catch (std::string err) {
699 }
catch (
const char* err) {
702 }
catch (std::exception& e) {
706 ret.
message =
"Unknown Exception";
714 auto last_colon = fnname.find_last_of(
":");
715 if (last_colon == std::string::npos) spec.
name = fnname;
716 else spec.
name = fnname.substr(last_colon + 1);
723 spec.
description[
"_raw_fn_pointer_"] =
reinterpret_cast<size_t>(fn);
738 template <
typename Function,
typename... Args>
742 typedef boost::function_traits<typename std::remove_pointer<Function>::type> fntraits;
743 static_assert(fntraits::arity ==
sizeof...(Args),
744 "Incorrect number input parameter names specified.");
745 return make_spec<
sizeof...(Args)>(fn, fnname, {args...});
boost::make_recursive_variant< flexible_type, std::shared_ptr< unity_sgraph_base >, dataframe_t, std::shared_ptr< model_base >, std::shared_ptr< unity_sframe_base >, std::shared_ptr< unity_sarray_base >, std::map< std::string, boost::recursive_variant_ >, std::vector< boost::recursive_variant_ >, boost::recursive_wrapper< function_closure_info > >::type variant_type
flex_type_enum get_type() const
variant_type to_variant(const T &f)
std::vector< std::pair< flexible_type, flexible_type > > flex_dict
static flexible_type FLEX_UNDEFINED