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 FLUTTER_FML_DART_DART_CONVERTER_H_ |
6 | #define FLUTTER_FML_DART_DART_CONVERTER_H_ |
7 | |
8 | #include <memory> |
9 | #include <vector> |
10 | |
11 | #include "flutter/fml/mapping.h" |
12 | #include "third_party/dart/runtime/include/dart_api.h" |
13 | #include "third_party/tonic/converter/dart_converter.h" |
14 | |
15 | namespace tonic { |
16 | |
17 | using DartConverterMapping = std::unique_ptr<fml::Mapping>; |
18 | |
19 | template <> |
20 | struct DartConverter<DartConverterMapping> { |
21 | static Dart_Handle ToDart(const DartConverterMapping& val) { |
22 | if (!val) { |
23 | return Dart_Null(); |
24 | } |
25 | |
26 | auto dart_list_handle = Dart_NewListOf(Dart_CoreType_Int, val->GetSize()); |
27 | |
28 | if (Dart_IsError(dart_list_handle)) { |
29 | FML_LOG(ERROR) << "Error while attempting to allocate a list: " |
30 | << Dart_GetError(dart_list_handle); |
31 | return dart_list_handle; |
32 | } |
33 | |
34 | if (val->GetSize() == 0) { |
35 | // Nothing to copy. Just return the zero sized list. |
36 | return dart_list_handle; |
37 | } |
38 | |
39 | auto result = Dart_ListSetAsBytes(dart_list_handle, // list |
40 | 0, // offset |
41 | val->GetMapping(), // native array, |
42 | val->GetSize() // length |
43 | ); |
44 | |
45 | if (Dart_IsError(result)) { |
46 | FML_LOG(ERROR) << "Error while attempting to create a Dart list: " |
47 | << Dart_GetError(result); |
48 | return result; |
49 | } |
50 | |
51 | return dart_list_handle; |
52 | } |
53 | |
54 | static void SetReturnValue(Dart_NativeArguments args, |
55 | const DartConverterMapping& val) { |
56 | Dart_SetReturnValue(args, ToDart(val)); |
57 | } |
58 | |
59 | static DartConverterMapping FromDart(Dart_Handle dart_list) { |
60 | if (Dart_IsNull(dart_list)) { |
61 | return nullptr; |
62 | } |
63 | |
64 | if (Dart_IsError(dart_list)) { |
65 | FML_LOG(ERROR) << "Cannot convert an error handle to a list: " |
66 | << Dart_GetError(dart_list); |
67 | return nullptr; |
68 | } |
69 | |
70 | if (!Dart_IsList(dart_list)) { |
71 | FML_LOG(ERROR) << "Dart handle was not a list." ; |
72 | return nullptr; |
73 | } |
74 | |
75 | intptr_t length = 0; |
76 | auto handle = Dart_ListLength(dart_list, &length); |
77 | |
78 | if (Dart_IsError(handle)) { |
79 | FML_LOG(ERROR) << "Could not get the length of the Dart list: " |
80 | << Dart_GetError(handle); |
81 | return nullptr; |
82 | } |
83 | |
84 | if (length == 0) { |
85 | // Return a valid zero sized mapping. |
86 | return std::make_unique<fml::NonOwnedMapping>(nullptr, 0); |
87 | } |
88 | |
89 | auto mapping_buffer = ::malloc(length); |
90 | |
91 | if (!mapping_buffer) { |
92 | FML_LOG(ERROR) |
93 | << "Out of memory while attempting to allocate a mapping of size: " |
94 | << length; |
95 | return nullptr; |
96 | } |
97 | |
98 | auto mapping = std::make_unique<fml::NonOwnedMapping>( |
99 | static_cast<const uint8_t*>(mapping_buffer), length, |
100 | [](const uint8_t* data, size_t size) { |
101 | ::free(const_cast<uint8_t*>(data)); |
102 | }); |
103 | |
104 | handle = Dart_ListGetAsBytes( |
105 | dart_list, // list |
106 | 0, // offset |
107 | static_cast<uint8_t*>(mapping_buffer), // native array |
108 | length // length |
109 | ); |
110 | |
111 | if (Dart_IsError(handle)) { |
112 | FML_LOG(ERROR) << "Could not copy Dart list to native buffer: " |
113 | << Dart_GetError(handle); |
114 | return nullptr; |
115 | } |
116 | |
117 | return mapping; |
118 | } |
119 | }; |
120 | |
121 | } // namespace tonic |
122 | |
123 | #endif // FLUTTER_FML_DART_DART_CONVERTER_H_ |
124 | |