6 #ifndef TURI_UNITY_LIB_VARIANT_DETAIL_HPP 7 #define TURI_UNITY_LIB_VARIANT_DETAIL_HPP 10 #include <unordered_map> 12 #include <type_traits> 13 #include <boost/mpl/contains.hpp> 14 #include <boost/mpl/range_c.hpp> 15 #include <boost/mpl/vector.hpp> 16 #include <boost/mpl/bool.hpp> 17 #include <boost/mpl/count.hpp> 18 #include <boost/mpl/transform.hpp> 19 #include <boost/fusion/algorithm/iteration/for_each.hpp> 20 #include <model_server/lib/variant.hpp> 21 #include <model_server/lib/unity_global_singleton.hpp> 22 #include <core/data/flexible_type/flexible_type_converter.hpp> 23 #include <model_server/lib/api/function_closure_info.hpp> 27 class unity_sarray_base;
28 class unity_sframe_base;
29 class unity_sgraph_base;
39 extern int64_t USE_GL_DATATYPE;
74 struct is_toolkit_builtin {
75 static constexpr
bool value =
76 std::is_same<typename std::decay<T>::type,
gl_sarray>::value ||
77 std::is_same<typename std::decay<T>::type,
gl_sframe>::value ||
78 std::is_same<typename std::decay<T>::type,
gl_sarray>::value ||
79 std::is_same<typename std::decay<T>::type,
gl_sgraph>::value;
89 template <
typename... Args>
150 template <
typename T,
class Enable =
void>
152 static constexpr
bool value =
false;
161 template <
typename T>
163 typename
std::enable_if<is_flexible_type_convertible<T>::value>::type> {
164 static constexpr
bool value =
true;
169 f = variant_get_ref<flexible_type>(val);
171 std::string errormsg =
172 std::string(
"Expecting a flexible_type. Got a ") +
174 std_log_and_throw(std::invalid_argument, errormsg);
194 template <
typename T>
196 typename
std::enable_if<(is_variant_member<T>::value &&
197 !std::is_same<T, flexible_type>::value) ||
198 std::is_same<T, variant_type>::value>::type> {
199 static constexpr
bool value =
true;
201 return variant_get_ref<T>(val);
213 static constexpr
bool value =
true;
229 static constexpr
bool value =
true;
230 std::shared_ptr<unity_sarray>
get(
const variant_type& val);
241 static constexpr
bool value =
true;
242 std::shared_ptr<unity_sframe>
get(
const variant_type& val);
243 variant_type
set(std::shared_ptr<unity_sframe> val);
253 static constexpr
bool value =
true;
254 std::shared_ptr<unity_sgraph>
get(
const variant_type& val);
255 variant_type
set(std::shared_ptr<unity_sgraph> val);
265 template <
typename T>
267 typename std::enable_if<is_model_descendent<T>::value &&
268 !std::is_same<T, model_base>::value &&
269 !is_toolkit_builtin<T>::value>::type> {
270 static constexpr
bool value =
true;
271 std::shared_ptr<T>
get(
const variant_type& val) {
272 return std::dynamic_pointer_cast<T>(variant_get_ref<std::shared_ptr<model_base>>(val));
274 variant_type
set(
const std::shared_ptr<T>& val) {
275 return variant_type(std::static_pointer_cast<model_base>(val));
286 template <
typename T>
288 typename
std::enable_if<is_model_descendent<T>::value &&
289 !std::is_same<T, model_base>::value &&
290 !is_toolkit_builtin<T>::value>::type> {
291 static constexpr
bool value =
true;
292 T
get(
const variant_type& val) {
293 return *std::dynamic_pointer_cast<T>(variant_get_ref<std::shared_ptr<model_base>>(val));
295 variant_type
set(
const T& val) {
296 return variant_type(std::static_pointer_cast<model_base>(std::make_shared<T>(val)));
307 template <
typename T>
309 typename std::enable_if<!is_flexible_type_convertible<std::vector<T>>::value &&
310 is_variant_convertible<T>::value &&
311 !is_variant_member<std::vector<T>>::value>::type> {
312 static constexpr
bool value =
true;
313 std::vector<T>
get(
const variant_type& val_) {
314 const variant_vector_type& val = variant_get_ref<variant_vector_type>(val_);
315 std::vector<T> ret(val.size());
316 for (
size_t i = 0;i < val.size(); ++i) {
321 variant_type
set(
const std::vector<T>& val) {
322 variant_vector_type ret(val.size());
323 for (
size_t i = 0;i < val.size(); ++i) {
336 template <
typename T>
338 typename std::enable_if<!is_flexible_type_convertible<T>::value &&
339 is_variant_convertible<T>::value &&
340 !is_variant_member<std::map<std::string, T>>::value>::type> {
341 static constexpr
bool value =
true;
342 std::map<std::string, T>
get(
const variant_type& val_) {
343 const variant_map_type& val = variant_get_ref<variant_map_type>(val_);
344 std::map<std::string, T> ret;
345 for (
const auto& elem: val) {
350 variant_type
set(
const std::map<std::string, T>& val) {
351 variant_map_type ret;
352 for (
const auto& elem: val) {
364 template <
typename T>
366 typename std::enable_if<!is_flexible_type_convertible<T>::value &&
367 is_variant_convertible<T>::value>::type> {
368 static constexpr
bool value =
true;
369 std::unordered_map<std::string, T>
get(
const variant_type& val_) {
370 const variant_map_type& val = variant_get_ref<variant_map_type>(val_);
371 std::unordered_map<std::string, T> ret;
372 for (
const auto& elem: val) {
377 variant_type
set(
const std::unordered_map<std::string, T>& val) {
378 variant_map_type ret;
379 for (
const auto& elem: val) {
390 template <
typename S,
typename T>
392 typename std::enable_if<!is_flexible_type_convertible<T>::value &&
393 is_variant_convertible<T>::value>::type> {
394 static constexpr
bool value =
true;
395 std::pair<S, T>
get(
const variant_type& val) {
396 std::vector<variant_type> ret =
398 if (ret.size() != 2) {
399 std_log_and_throw(std::invalid_argument,
400 "Expecting an array of length 2");
405 variant_type
set(
const std::pair<S, T>& val) {
406 variant_vector_type ret;
414 #ifndef DISABLE_SDK_TYPES 420 static constexpr
bool value =
true;
427 static constexpr
bool value =
true;
428 gl_sframe
get(
const variant_type& val);
429 variant_type
set(gl_sframe val);
434 static constexpr
bool value =
true;
435 gl_sgraph
get(
const variant_type& val);
436 variant_type
set(gl_sgraph val);
441 static constexpr
bool value =
true;
442 gl_gframe
get(
const variant_type& val);
443 variant_type
set(gl_gframe val);
447 namespace variant_converter_impl {
449 template <
typename TupleType>
451 const std::vector<variant_type>* input;
452 mutable TupleType* tuple;
454 void operator()(boost::mpl::integral_c<int, n> t)
const {
455 typedef typename std::decay<decltype(std::get<n>(*tuple))>::type TargetType;
461 template <
typename TupleType>
463 const TupleType* input;
464 mutable std::vector<variant_type>* output;
466 void operator()(boost::mpl::integral_c<int, n> t)
const {
467 typedef typename std::decay<decltype(std::get<n>(*input))>::type TargetType;
478 std::function<variant_type(const std::vector<variant_type>&)>
486 template <
typename... Args>
488 typename std::enable_if<!all_flexible_type_convertible<Args...>::value &&
489 all_variant_convertible<Args...>::value>::type> {
490 static constexpr
bool value =
true;
491 std::tuple<Args...>
get(
const variant_type& val) {
492 std::vector<variant_type> cv =
494 if (cv.size() !=
sizeof...(Args)) {
495 std::string error_msg =
496 "Expecting an array of length " + std::to_string(
sizeof...(Args));
497 std_log_and_throw(std::invalid_argument, error_msg);
500 typename boost::mpl::range_c<int, 0,
sizeof...(Args)>::type tuple_range;
501 variant_converter_impl::fill_tuple<std::tuple<Args...>> filler;
502 std::tuple<Args...> output;
504 filler.tuple = &output;
505 boost::fusion::for_each(tuple_range, filler);
508 variant_type
set(
const std::tuple<Args...> & val) {
509 typename boost::mpl::range_c<int, 0,
sizeof...(Args)>::type tuple_range;
510 variant_converter_impl::fill_variant<std::tuple<Args...>> filler;
511 std::vector<variant_type> output;
513 filler.output = &output;
514 output.resize(
sizeof...(Args));
515 boost::fusion::for_each(tuple_range, filler);
524 template <
typename S,
typename... Args>
526 typename std::enable_if<is_variant_convertible<S>::value &&
527 all_variant_convertible<Args...>::value>::type> {
528 static constexpr
bool value =
true;
529 std::function<S(Args...)>
get(
const variant_type& val) {
531 closure = variant_get_ref<function_closure_info>(val);
532 auto native_execute_function =
533 variant_converter_impl::get_toolkit_function_from_closure(closure);
536 return [=](Args... args)->S {
537 std::tuple<Args...> val{args...};
538 typename boost::mpl::range_c<int, 0,
sizeof...(Args)>::type tuple_range;
539 variant_converter_impl::fill_variant<std::tuple<Args...>> filler;
541 filler.output->resize(
sizeof...(Args));
542 boost::fusion::for_each(tuple_range, filler);
546 variant_type
set(
const std::function<S(Args...)>& val) {
547 std_log_and_throw(std::invalid_argument,
548 "Cannot convert function to variant");
549 ASSERT_UNREACHABLE();
559 template <
typename T>
562 typedef boost::mpl::bool_<value> type;
570 template <
typename... Args>
572 typedef boost::mpl::vector<Args...> type_sequence;
575 typedef typename boost::mpl::transform<type_sequence,
579 typedef typename boost::mpl::count<transformed_sequence, boost::mpl::bool_<true>>::type num_good;
582 static constexpr
bool value = (num_good::value ==
sizeof...(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
boost::mpl::contains< variant_type::types, T > is_variant_member
std::is_convertible< T *, model_base * > is_model_descendent
std::string get_variant_which_name(int i)