Turi Create  4.0
variant.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_UNITY_VARIANT_HPP
7 #define TURI_UNITY_VARIANT_HPP
8 #include <string>
9 #include <map>
10 #include <vector>
11 #include <boost/variant/variant.hpp>
12 #include <boost/variant/recursive_variant.hpp>
13 #include <boost/variant/get.hpp>
14 #include <core/data/flexible_type/flexible_type.hpp>
15 #include <core/storage/sframe_data/dataframe.hpp>
16 #include <core/storage/serialization/serialization_includes.hpp>
17 #include <model_server/lib/variant.hpp>
18 
19 namespace turi {
20 class model_base;
21 struct function_closure_info;
22 class unity_sframe_base;
23 class unity_sgraph_base;
24 class unity_sarray_base;
25 
26 /**
27  * A variant object that can be communicated between Python and C++ which
28  * contains either a
29  * \li flexible_type
30  * \li std::shared_ptr<unity_sgraph>
31  * \li dataframe_t
32  * \li model
33  * \li std::shared_ptr<unity_sframe>
34  * \li std::shared_ptr<unity_sarray>
35  * \li std::map<variant>
36  * \li std::vector<variant>
37  *
38  * See the boost variant documentation for details.
39  *
40  * The variant should not be accessed directly. See \ref to_variant
41  * and \ref variant_get_value for powerful ways to extract or store values
42  * from a variant.
43  */
44 typedef typename boost::make_recursive_variant<
46  std::shared_ptr<unity_sgraph_base>,
48  std::shared_ptr<model_base>,
49  std::shared_ptr<unity_sframe_base>,
50  std::shared_ptr<unity_sarray_base>,
51  std::map<std::string, boost::recursive_variant_>,
52  std::vector<boost::recursive_variant_>,
53  boost::recursive_wrapper<function_closure_info> >::type variant_type;
54 
55 /*
56  * A map of string to variant. Also a type the variant type can store.
57  */
58 typedef std::map<std::string, variant_type> variant_map_type;
59 
60 /*
61  * A map of vector to variant. Also a type that the variant_type can store
62  */
63 typedef std::vector<variant_type> variant_vector_type;
64 
65 
66 /**
67  * Given variant.which() gets the name of the type inside it.
68  */
69 inline std::string get_variant_which_name(int i) {
70  switch(i) {
71  case 0:
72  return "flexible_type";
73  case 1:
74  return "SGraph";
75  case 2:
76  return "Dataframe";
77  case 3:
78  return "Model";
79  case 4:
80  return "SFrame";
81  case 5:
82  return "SArray";
83  case 6:
84  return "Dictionary";
85  case 7:
86  return "List";
87  case 8:
88  return "Function";
89  default:
90  return "";
91  }
92 }
93 
94 } // namespace turi
95 
96 
97 namespace turi{ namespace archive_detail {
98 
99 template <>
100 struct serialize_impl<oarchive, turi::variant_type, false> {
101  static void exec(oarchive& arc, const turi::variant_type& tval);
102 };
103 
104 template <>
105 struct deserialize_impl<iarchive, turi::variant_type, false> {
106  static void exec(iarchive& arc, turi::variant_type& tval);
107 };
108 }
109 }
110 
111 
112 
113 namespace turi {
114 // A list of accessors to help Cython access the variant
115 template <typename T>
117 void _throw_variant_error(const variant_type& v) {
118  std::string errormsg = //
119  std::string("Variant type error: Expecting ") +
120  get_variant_which_name(variant_type(T()).which()) + " but got a " +
121  get_variant_which_name(v.which());
122  log_and_throw(errormsg);
123 }
124 
125 
126 /**
127  * Gets a reference to a content of a variant.
128  * Throws if variant contains an inappropriate type.
129  */
130 template <typename T>
131 static inline T& variant_get_ref(variant_type& v) {
132  try {
133  return boost::get<T>(v);
134  } catch (...) {
135  _throw_variant_error<T>(v);
136  }
137 }
138 
139 /**
140  * Gets a const reference to the content of a variant.
141  * Throws if variant contains an inappropriate type.
142  */
143 template <typename T>
144 static inline const T& variant_get_ref(const variant_type& v) {
145  try {
146  return boost::get<T>(v);
147  } catch (...) {
148  _throw_variant_error<T>(v);
149  }
150 }
151 
152 
153 
154 
155 
156 // Convenience functions
157 template <typename T>
159 inline bool variant_is(const variant_type&) {
160  return false;
161 }
162 
163 template <>
165 inline bool variant_is<flexible_type>(const variant_type& t) {
166  return t.which() == 0;
167 }
168 
169 template <>
171 inline bool variant_is<flex_string>(const variant_type& t) {
172  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::STRING);
173 }
174 
175 template <>
177 inline bool variant_is<flex_vec>(const variant_type& t) {
178  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::VECTOR);
179 }
180 
181 template <>
183 inline bool variant_is<flex_int>(const variant_type& t) {
184  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::INTEGER);
185 }
186 
187 template <>
189 inline bool variant_is<flex_float>(const variant_type& t) {
190  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::FLOAT);
191 }
192 
193 template <>
195 inline bool variant_is<flex_list>(const variant_type& t) {
196  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::LIST);
197 }
198 
199 template <>
201 inline bool variant_is<flex_dict>(const variant_type& t) {
202  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::DICT);
203 }
204 
205 template <>
207 inline bool variant_is<flex_image>(const variant_type& t) {
208  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::IMAGE);
209 }
210 
211 template <>
213 inline bool variant_is<flex_date_time>(const variant_type& t) {
214  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::DATETIME);
215 }
216 
217 template <>
219 inline bool variant_is<flex_nd_vec>(const variant_type& t) {
220  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::ND_VECTOR);
221 }
222 
223 template <>
225 inline bool variant_is<flex_undefined>(const variant_type& t) {
226  return variant_is<flexible_type>(t) && (variant_get_ref<flexible_type>(t).get_type() == flex_type_enum::UNDEFINED);
227 }
228 
229 template <>
231 inline bool variant_is<std::shared_ptr<unity_sgraph_base> >(const variant_type& t) {
232  return t.which() == 1;
233 }
234 
235 template <>
237 inline bool variant_is<dataframe_t>(const variant_type& t) {
238  return t.which() == 2;
239 }
240 
241 template <>
243 inline bool variant_is<std::shared_ptr<model_base> >(const variant_type& t) {
244  return t.which() == 3;
245 }
246 
247 template <>
249 inline bool variant_is<std::shared_ptr<unity_sframe_base> >(const variant_type& t) {
250  return t.which() == 4;
251 }
252 
253 class gl_sframe;
254 
255 template <>
257 inline bool variant_is<gl_sframe>(const variant_type& t) {
258  return t.which() == 4;
259 }
260 
261 template <>
263 inline bool variant_is<std::shared_ptr<unity_sarray_base> >(const variant_type& t) {
264  return t.which() == 5;
265 }
266 
267 class gl_sarray;
268 
269 template <>
271 inline bool variant_is<gl_sarray>(const variant_type& t) {
272  return t.which() == 5;
273 }
274 
275 template <>
277 inline bool variant_is<variant_map_type>(const variant_type& t) {
278  return t.which() == 6;
279 }
280 
281 template <>
283 inline bool variant_is<boost::recursive_wrapper<function_closure_info> >(const variant_type& t) {
284  return t.which() == 7;
285 }
286 
287 }
288 
289 
290 #include <model_server/lib/variant_converter.hpp>
291 
292 namespace turi {
293 /**
294  * Stores an arbitrary value in a variant
295  */
296 template <typename T>
297 inline void variant_set_value(variant_type& v, const T& f) {
299 }
300 
301 
302 /**
303  * Converts an arbitrary value to a variant.
304  * T can be \b alot of possibilities. See the \ref sec_supported_type_list
305  * "supported type list" for details.
306  */
307 template <typename T>
308 inline variant_type to_variant(const T& f) {
310 }
311 } // namespace turi
312 
313 namespace turi {
314 /**
315  * Reads an arbitrary type from a variant.
316  * T can be \b alot of possibilities. See the \ref sec_supported_type_list
317  * "supported type list" for details.
318  */
319 template <typename T>
320 inline typename std::decay<T>::type variant_get_value(const variant_type& v) {
322 }
323 
324 } // namespace turi
325 #include <model_server/lib/api/function_closure_info.hpp>
326 #endif
std::decay< T >::type variant_get_value(const variant_type &v)
Definition: variant.hpp:320
static T & variant_get_ref(variant_type &v)
Definition: variant.hpp:131
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
Definition: variant.hpp:24
void variant_set_value(variant_type &v, const T &f)
Definition: variant.hpp:297
#define GL_HOT_INLINE_FLATTEN
variant_type to_variant(const T &f)
Definition: variant.hpp:308
#define GL_COLD_NOINLINE_ERROR
std::string get_variant_which_name(int i)
Definition: variant.hpp:69