1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef LIB_CONVERTER_TONIC_DART_CONVERTER_H_ |
6 | #define LIB_CONVERTER_TONIC_DART_CONVERTER_H_ |
7 | |
8 | #include <string> |
9 | #include <vector> |
10 | |
11 | #include "third_party/dart/runtime/include/dart_api.h" |
12 | #include "tonic/common/macros.h" |
13 | |
14 | namespace tonic { |
15 | |
16 | // DartConvert converts types back and forth from Sky to Dart. The template |
17 | // parameter |T| determines what kind of type conversion to perform. |
18 | template <typename T, typename Enable = void> |
19 | struct DartConverter {}; |
20 | |
21 | // This is to work around the fact that typedefs do not create new types. If you |
22 | // have a typedef, and want it to use a different converter, specialize this |
23 | // template and override the types here. |
24 | // Ex: |
25 | // typedef int ColorType; // Want to use a different converter. |
26 | // class ColorConverterType {}; // Dummy type. |
27 | // template<> struct DartConvertType<ColorConverterType> { |
28 | // using ConverterType = ColorConverterType; |
29 | // using ValueType = ColorType; |
30 | // }; |
31 | template <typename T> |
32 | struct DartConverterTypes { |
33 | using ConverterType = T; |
34 | using ValueType = T; |
35 | }; |
36 | |
37 | //////////////////////////////////////////////////////////////////////////////// |
38 | // Boolean |
39 | |
40 | template <> |
41 | struct DartConverter<bool> { |
42 | static Dart_Handle ToDart(bool val) { return Dart_NewBoolean(val); } |
43 | |
44 | static void SetReturnValue(Dart_NativeArguments args, bool val) { |
45 | Dart_SetBooleanReturnValue(args, val); |
46 | } |
47 | |
48 | static bool FromDart(Dart_Handle handle) { |
49 | bool result = 0; |
50 | Dart_BooleanValue(handle, &result); |
51 | return result; |
52 | } |
53 | |
54 | static bool FromArguments(Dart_NativeArguments args, |
55 | int index, |
56 | Dart_Handle& exception) { |
57 | bool result = false; |
58 | Dart_GetNativeBooleanArgument(args, index, &result); |
59 | return result; |
60 | } |
61 | }; |
62 | |
63 | //////////////////////////////////////////////////////////////////////////////// |
64 | // Numbers |
65 | |
66 | template <typename T> |
67 | struct DartConverterInteger { |
68 | static Dart_Handle ToDart(T val) { return Dart_NewInteger(val); } |
69 | |
70 | static void SetReturnValue(Dart_NativeArguments args, T val) { |
71 | Dart_SetIntegerReturnValue(args, val); |
72 | } |
73 | |
74 | static T FromDart(Dart_Handle handle) { |
75 | int64_t result = 0; |
76 | Dart_IntegerToInt64(handle, &result); |
77 | return static_cast<T>(result); |
78 | } |
79 | |
80 | static T FromArguments(Dart_NativeArguments args, |
81 | int index, |
82 | Dart_Handle& exception) { |
83 | int64_t result = 0; |
84 | Dart_GetNativeIntegerArgument(args, index, &result); |
85 | return static_cast<T>(result); |
86 | } |
87 | }; |
88 | |
89 | template <> |
90 | struct DartConverter<int> : public DartConverterInteger<int> {}; |
91 | |
92 | template <> |
93 | struct DartConverter<long int> : public DartConverterInteger<long int> {}; |
94 | |
95 | template <> |
96 | struct DartConverter<unsigned> : public DartConverterInteger<unsigned> {}; |
97 | |
98 | template <> |
99 | struct DartConverter<long long> : public DartConverterInteger<long long> {}; |
100 | |
101 | template <> |
102 | struct DartConverter<unsigned long> |
103 | : public DartConverterInteger<unsigned long> {}; |
104 | |
105 | template <> |
106 | struct DartConverter<unsigned long long> { |
107 | // TODO(abarth): The Dart VM API doesn't yet have an entry-point for |
108 | // an unsigned 64-bit type. We will need to add a Dart API for |
109 | // constructing an integer from uint64_t. |
110 | // |
111 | // (In the meantime, we have asserts below to check that we're never |
112 | // converting values that have the 64th bit set.) |
113 | |
114 | static Dart_Handle ToDart(unsigned long long val) { |
115 | TONIC_DCHECK(val <= 0x7fffffffffffffffLL); |
116 | return Dart_NewInteger(static_cast<int64_t>(val)); |
117 | } |
118 | |
119 | static void SetReturnValue(Dart_NativeArguments args, |
120 | unsigned long long val) { |
121 | TONIC_DCHECK(val <= 0x7fffffffffffffffLL); |
122 | Dart_SetIntegerReturnValue(args, val); |
123 | } |
124 | |
125 | static unsigned long long FromDart(Dart_Handle handle) { |
126 | int64_t result = 0; |
127 | Dart_IntegerToInt64(handle, &result); |
128 | return result; |
129 | } |
130 | |
131 | static unsigned long long FromArguments(Dart_NativeArguments args, |
132 | int index, |
133 | Dart_Handle& exception) { |
134 | int64_t result = 0; |
135 | Dart_GetNativeIntegerArgument(args, index, &result); |
136 | return result; |
137 | } |
138 | }; |
139 | |
140 | template <typename T> |
141 | struct DartConverterFloatingPoint { |
142 | static Dart_Handle ToDart(T val) { return Dart_NewDouble(val); } |
143 | |
144 | static void SetReturnValue(Dart_NativeArguments args, T val) { |
145 | Dart_SetDoubleReturnValue(args, val); |
146 | } |
147 | |
148 | static T FromDart(Dart_Handle handle) { |
149 | double result = 0; |
150 | Dart_DoubleValue(handle, &result); |
151 | return result; |
152 | } |
153 | |
154 | static T FromArguments(Dart_NativeArguments args, |
155 | int index, |
156 | Dart_Handle& exception) { |
157 | double result = 0; |
158 | Dart_GetNativeDoubleArgument(args, index, &result); |
159 | return result; |
160 | } |
161 | }; |
162 | |
163 | template <> |
164 | struct DartConverter<float> : public DartConverterFloatingPoint<float> {}; |
165 | |
166 | template <> |
167 | struct DartConverter<double> : public DartConverterFloatingPoint<double> {}; |
168 | |
169 | //////////////////////////////////////////////////////////////////////////////// |
170 | // Enum Classes |
171 | |
172 | template <typename T> |
173 | struct DartConverter<T, typename std::enable_if<std::is_enum<T>::value>::type> { |
174 | static Dart_Handle ToDart(T val) { |
175 | return Dart_NewInteger( |
176 | static_cast<typename std::underlying_type<T>::type>(val)); |
177 | } |
178 | |
179 | static void SetReturnValue(Dart_NativeArguments args, T val) { |
180 | Dart_SetIntegerReturnValue( |
181 | args, static_cast<typename std::underlying_type<T>::type>(val)); |
182 | } |
183 | |
184 | static T FromDart(Dart_Handle handle) { |
185 | int64_t result = 0; |
186 | Dart_IntegerToInt64(handle, &result); |
187 | return static_cast<T>(result); |
188 | } |
189 | |
190 | static T FromArguments(Dart_NativeArguments args, |
191 | int index, |
192 | Dart_Handle& exception) { |
193 | int64_t result = 0; |
194 | Dart_GetNativeIntegerArgument(args, index, &result); |
195 | return static_cast<T>(result); |
196 | } |
197 | }; |
198 | |
199 | //////////////////////////////////////////////////////////////////////////////// |
200 | // Strings |
201 | |
202 | template <> |
203 | struct DartConverter<std::string> { |
204 | static Dart_Handle ToDart(const std::string& val) { |
205 | return Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(val.data()), |
206 | val.length()); |
207 | } |
208 | |
209 | static void SetReturnValue(Dart_NativeArguments args, |
210 | const std::string& val) { |
211 | Dart_SetReturnValue(args, ToDart(val)); |
212 | } |
213 | |
214 | static std::string FromDart(Dart_Handle handle) { |
215 | uint8_t* data = nullptr; |
216 | intptr_t length = 0; |
217 | if (Dart_IsError(Dart_StringToUTF8(handle, &data, &length))) |
218 | return std::string(); |
219 | return std::string(reinterpret_cast<char*>(data), length); |
220 | } |
221 | |
222 | static std::string FromArguments(Dart_NativeArguments args, |
223 | int index, |
224 | Dart_Handle& exception) { |
225 | return FromDart(Dart_GetNativeArgument(args, index)); |
226 | } |
227 | }; |
228 | |
229 | template <> |
230 | struct DartConverter<std::u16string> { |
231 | static Dart_Handle ToDart(const std::u16string& val) { |
232 | return Dart_NewStringFromUTF16( |
233 | reinterpret_cast<const uint16_t*>(val.data()), val.length()); |
234 | } |
235 | |
236 | static void SetReturnValue(Dart_NativeArguments args, |
237 | const std::u16string& val) { |
238 | Dart_SetReturnValue(args, ToDart(val)); |
239 | } |
240 | |
241 | static std::u16string FromDart(Dart_Handle handle) { |
242 | intptr_t length = 0; |
243 | Dart_StringLength(handle, &length); |
244 | std::vector<uint16_t> data(length); |
245 | Dart_StringToUTF16(handle, data.data(), &length); |
246 | return std::u16string(reinterpret_cast<char16_t*>(data.data()), length); |
247 | } |
248 | |
249 | static std::u16string FromArguments(Dart_NativeArguments args, |
250 | int index, |
251 | Dart_Handle& exception) { |
252 | return FromDart(Dart_GetNativeArgument(args, index)); |
253 | } |
254 | }; |
255 | |
256 | template <> |
257 | struct DartConverter<const char*> { |
258 | static Dart_Handle ToDart(const char* val) { |
259 | return Dart_NewStringFromCString(val); |
260 | } |
261 | |
262 | static void SetReturnValue(Dart_NativeArguments args, const char* val) { |
263 | Dart_SetReturnValue(args, ToDart(val)); |
264 | } |
265 | |
266 | static const char* FromDart(Dart_Handle handle) { |
267 | const char* result = nullptr; |
268 | Dart_StringToCString(handle, &result); |
269 | return result; |
270 | } |
271 | |
272 | static const char* FromArguments(Dart_NativeArguments args, |
273 | int index, |
274 | Dart_Handle& exception) { |
275 | return FromDart(Dart_GetNativeArgument(args, index)); |
276 | } |
277 | }; |
278 | |
279 | //////////////////////////////////////////////////////////////////////////////// |
280 | // Collections |
281 | |
282 | template <typename T, typename Enable = void> |
283 | struct DartListFactory { |
284 | static Dart_Handle NewList(intptr_t length) { return Dart_NewList(length); } |
285 | }; |
286 | |
287 | template <> |
288 | struct DartListFactory<std::string> { |
289 | static Dart_Handle NewList(intptr_t length) { |
290 | return Dart_NewListOf(Dart_CoreType_String, length); |
291 | } |
292 | }; |
293 | |
294 | template <typename T> |
295 | struct DartConverter<std::vector<T>> { |
296 | using ValueType = typename DartConverterTypes<T>::ValueType; |
297 | using ConverterType = typename DartConverterTypes<T>::ConverterType; |
298 | |
299 | static Dart_Handle ToDart(const std::vector<ValueType>& val) { |
300 | Dart_Handle list = DartListFactory<ValueType>::NewList(val.size()); |
301 | if (Dart_IsError(list)) |
302 | return list; |
303 | for (size_t i = 0; i < val.size(); i++) { |
304 | Dart_Handle result = |
305 | Dart_ListSetAt(list, i, DartConverter<ConverterType>::ToDart(val[i])); |
306 | if (Dart_IsError(result)) |
307 | return result; |
308 | } |
309 | return list; |
310 | } |
311 | |
312 | static void SetReturnValue(Dart_NativeArguments args, |
313 | const std::vector<ValueType>& val) { |
314 | Dart_SetReturnValue(args, ToDart(val)); |
315 | } |
316 | |
317 | static std::vector<ValueType> FromDart(Dart_Handle handle) { |
318 | std::vector<ValueType> result; |
319 | |
320 | if (!Dart_IsList(handle)) |
321 | return result; |
322 | |
323 | intptr_t length = 0; |
324 | Dart_ListLength(handle, &length); |
325 | |
326 | if (length == 0) |
327 | return result; |
328 | |
329 | result.reserve(length); |
330 | |
331 | std::vector<Dart_Handle> items(length); |
332 | Dart_Handle items_result = |
333 | Dart_ListGetRange(handle, 0, length, items.data()); |
334 | TONIC_DCHECK(!Dart_IsError(items_result)); |
335 | |
336 | for (intptr_t i = 0; i < length; ++i) { |
337 | TONIC_DCHECK(items[i]); |
338 | result.push_back(DartConverter<ConverterType>::FromDart(items[i])); |
339 | } |
340 | return result; |
341 | } |
342 | |
343 | static std::vector<ValueType> FromArguments(Dart_NativeArguments args, |
344 | int index, |
345 | Dart_Handle& exception) { |
346 | return FromDart(Dart_GetNativeArgument(args, index)); |
347 | } |
348 | }; |
349 | |
350 | //////////////////////////////////////////////////////////////////////////////// |
351 | // Dart_Handle |
352 | |
353 | template <> |
354 | struct DartConverter<Dart_Handle> { |
355 | static Dart_Handle ToDart(Dart_Handle val) { return val; } |
356 | |
357 | static void SetReturnValue(Dart_NativeArguments args, Dart_Handle val) { |
358 | Dart_SetReturnValue(args, val); |
359 | } |
360 | |
361 | static Dart_Handle FromDart(Dart_Handle handle) { return handle; } |
362 | |
363 | static Dart_Handle FromArguments(Dart_NativeArguments args, |
364 | int index, |
365 | Dart_Handle& exception) { |
366 | return Dart_GetNativeArgument(args, index); |
367 | } |
368 | }; |
369 | |
370 | //////////////////////////////////////////////////////////////////////////////// |
371 | // Convience wrappers using type inference |
372 | |
373 | template <typename T> |
374 | Dart_Handle ToDart(const T& object) { |
375 | return DartConverter<T>::ToDart(object); |
376 | } |
377 | |
378 | //////////////////////////////////////////////////////////////////////////////// |
379 | // std::string support |
380 | |
381 | inline Dart_Handle StdStringToDart(const std::string& val) { |
382 | return DartConverter<std::string>::ToDart(val); |
383 | } |
384 | |
385 | inline std::string StdStringFromDart(Dart_Handle handle) { |
386 | return DartConverter<std::string>::FromDart(handle); |
387 | } |
388 | |
389 | // Alias Dart_NewStringFromCString for less typing. |
390 | inline Dart_Handle ToDart(const char* val) { |
391 | return Dart_NewStringFromCString(val); |
392 | } |
393 | |
394 | } // namespace tonic |
395 | |
396 | #endif // LIB_CONVERTER_TONIC_DART_CONVERTER_H_ |
397 | |