| Flutter Linux Embedder |

fl_json_message_codec.cc
Go to the documentation of this file.
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 #include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
6
7 #include <gmodule.h>
8
9 #include <cstring>
10
11 #include "rapidjson/reader.h"
12 #include "rapidjson/writer.h"
13
14 G_DEFINE_QUARK(fl_json_message_codec_error_quark, fl_json_message_codec_error)
15
16 struct _FlJsonMessageCodec {
17 FlMessageCodec parent_instance;
18 };
19
20 G_DEFINE_TYPE(FlJsonMessageCodec,
21 fl_json_message_codec,
22 fl_message_codec_get_type())
23
24 // Recursively writes #FlValue objects using rapidjson.
25 static gboolean write_value(rapidjson::Writer<rapidjson::StringBuffer>& writer,
26 FlValue* value,
27 GError** error) {
28 if (value == nullptr) {
29 writer.Null();
30 return TRUE;
31 }
32
33 switch (fl_value_get_type(value)) {
34 case FL_VALUE_TYPE_NULL:
35 writer.Null();
36 break;
37 case FL_VALUE_TYPE_BOOL:
38 writer.Bool(fl_value_get_bool(value));
39 break;
40 case FL_VALUE_TYPE_INT:
41 writer.Int64(fl_value_get_int(value));
42 break;
43 case FL_VALUE_TYPE_FLOAT:
44 writer.Double(fl_value_get_float(value));
45 break;
46 case FL_VALUE_TYPE_STRING:
47 writer.String(fl_value_get_string(value));
48 break;
49 case FL_VALUE_TYPE_UINT8_LIST: {
50 writer.StartArray();
51 const uint8_t* data = fl_value_get_uint8_list(value);
52 for (size_t i = 0; i < fl_value_get_length(value); i++) {
53 writer.Int(data[i]);
54 }
55 writer.EndArray();
56 break;
57 }
58 case FL_VALUE_TYPE_INT32_LIST: {
59 writer.StartArray();
60 const int32_t* data = fl_value_get_int32_list(value);
61 for (size_t i = 0; i < fl_value_get_length(value); i++) {
62 writer.Int(data[i]);
63 }
64 writer.EndArray();
65 break;
66 }
67 case FL_VALUE_TYPE_INT64_LIST: {
68 writer.StartArray();
69 const int64_t* data = fl_value_get_int64_list(value);
70 for (size_t i = 0; i < fl_value_get_length(value); i++) {
71 writer.Int64(data[i]);
72 }
73 writer.EndArray();
74 break;
75 }
76 case FL_VALUE_TYPE_FLOAT_LIST: {
77 writer.StartArray();
78 const double* data = fl_value_get_float_list(value);
79 for (size_t i = 0; i < fl_value_get_length(value); i++) {
80 writer.Double(data[i]);
81 }
82 writer.EndArray();
83 break;
84 }
85 case FL_VALUE_TYPE_LIST: {
86 writer.StartArray();
87 for (size_t i = 0; i < fl_value_get_length(value); i++) {
88 if (!write_value(writer, fl_value_get_list_value(value, i), error)) {
89 return FALSE;
90 }
91 }
92 writer.EndArray();
93 break;
94 }
95 case FL_VALUE_TYPE_MAP: {
96 writer.StartObject();
97 for (size_t i = 0; i < fl_value_get_length(value); i++) {
98 FlValue* key = fl_value_get_map_key(value, i);
99 if (fl_value_get_type(key) != FL_VALUE_TYPE_STRING) {
100 g_set_error(error, FL_JSON_MESSAGE_CODEC_ERROR,
101 FL_JSON_MESSAGE_CODEC_ERROR_INVALID_OBJECT_KEY_TYPE,
102 "Invalid object key type");
103 return FALSE;
104 }
105 writer.Key(fl_value_get_string(key));
106 if (!write_value(writer, fl_value_get_map_value(value, i), error)) {
107 return FALSE;
108 }
109 }
110 writer.EndObject();
111 break;
112 }
113 default:
114 g_set_error(error, FL_MESSAGE_CODEC_ERROR,
115 FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE,
116 "Unexpected FlValue type %d", fl_value_get_type(value));
117 return FALSE;
118 }
119
120 return TRUE;
121 }
122
123 // Handler to parse JSON using rapidjson in SAX mode.
124 struct FlValueHandler {
125 GPtrArray* stack;
126 FlValue* key;
127 GError* error;
128
129 FlValueHandler() {
130 stack = g_ptr_array_new_with_free_func(
131 reinterpret_cast<GDestroyNotify>(fl_value_unref));
132 key = nullptr;
133 error = nullptr;
134 }
135
136 ~FlValueHandler() {
137 g_ptr_array_unref(stack);
138 if (key != nullptr) {
139 fl_value_unref(key);
140 }
141 if (error != nullptr) {
142 g_error_free(error);
143 }
144 }
145
146 // Gets the current head of the stack.
147 FlValue* get_head() {
148 if (stack->len == 0) {
149 return nullptr;
150 }
151 return static_cast<FlValue*>(g_ptr_array_index(stack, stack->len - 1));
152 }
153
154 // Pushes a value onto the stack.
155 void push(FlValue* value) { g_ptr_array_add(stack, fl_value_ref(value)); }
156
157 // Pops the stack.
158 void pop() { g_ptr_array_remove_index(stack, stack->len - 1); }
159
160 // Adds a new value to the stack.
161 bool add(FlValue* value) {
162 g_autoptr(FlValue) owned_value = value;
163 FlValue* head = get_head();
164 if (head == nullptr) {
165 push(owned_value);
166 } else if (fl_value_get_type(head) == FL_VALUE_TYPE_LIST) {
167 fl_value_append(head, owned_value);
168 } else if (fl_value_get_type(head) == FL_VALUE_TYPE_MAP) {
169 fl_value_set_take(head, key, fl_value_ref(owned_value));
170 key = nullptr;
171 } else {
172 g_set_error(&error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
173 "Can't add value to non container");
174 return false;
175 }
176
177 if (fl_value_get_type(owned_value) == FL_VALUE_TYPE_LIST ||
178 fl_value_get_type(owned_value) == FL_VALUE_TYPE_MAP) {
179 push(value);
180 }
181
182 return true;
183 }
184
185 // The following implements the rapidjson SAX API.
186
187 bool Null() { return add(fl_value_new_null()); }
188
189 bool Bool(bool b) { return add(fl_value_new_bool(b)); }
190
191 bool Int(int i) { return add(fl_value_new_int(i)); }
192
193 bool Uint(unsigned i) { return add(fl_value_new_int(i)); }
194
195 bool Int64(int64_t i) { return add(fl_value_new_int(i)); }
196
197 bool Uint64(uint64_t i) {
198 // For some reason (bug in rapidjson?) this is not returned in Int64.
199 if (i == G_MAXINT64) {
200 return add(fl_value_new_int(i));
201 } else {
202 return add(fl_value_new_float(i));
203 }
204 }
205
206 bool Double(double d) { return add(fl_value_new_float(d)); }
207
208 bool RawNumber(const char* str, rapidjson::SizeType length, bool copy) {
209 g_set_error(&error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
210 "RawNumber not supported");
211 return false;
212 }
213
214 bool String(const char* str, rapidjson::SizeType length, bool copy) {
215 FlValue* v = fl_value_new_string_sized(str, length);
216 return add(v);
217 }
218
219 bool StartObject() { return add(fl_value_new_map()); }
220
221 bool Key(const char* str, rapidjson::SizeType length, bool copy) {
222 if (key != nullptr) {
223 fl_value_unref(key);
224 }
225 key = fl_value_new_string_sized(str, length);
226 return true;
227 }
228
229 bool EndObject(rapidjson::SizeType memberCount) {
230 pop();
231 return true;
232 }
233
234 bool StartArray() { return add(fl_value_new_list()); }
235
236 bool EndArray(rapidjson::SizeType elementCount) {
237 pop();
238 return true;
239 }
240 };
241
242 // Implements FlMessageCodec:encode_message.
243 static GBytes* fl_json_message_codec_encode_message(FlMessageCodec* codec,
244 FlValue* message,
245 GError** error) {
246 rapidjson::StringBuffer buffer;
247 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
248
249 if (!write_value(writer, message, error)) {
250 return nullptr;
251 }
252
253 const gchar* text = buffer.GetString();
254 return g_bytes_new(text, strlen(text));
255 }
256
257 // Implements FlMessageCodec:decode_message.
258 static FlValue* fl_json_message_codec_decode_message(FlMessageCodec* codec,
259 GBytes* message,
260 GError** error) {
261 gsize data_length;
262 const gchar* data =
263 static_cast<const char*>(g_bytes_get_data(message, &data_length));
264 if (!g_utf8_validate(data, data_length, nullptr)) {
265 g_set_error(error, FL_JSON_MESSAGE_CODEC_ERROR,
266 FL_JSON_MESSAGE_CODEC_ERROR_INVALID_UTF8,
267 "Message is not valid UTF8");
268 return nullptr;
269 }
270
271 FlValueHandler handler;
272 rapidjson::Reader reader;
273 rapidjson::MemoryStream ss(data, data_length);
274 if (!reader.Parse(ss, handler)) {
275 if (handler.error != nullptr) {
276 g_propagate_error(error, handler.error);
277 handler.error = nullptr;
278 } else {
279 g_set_error(error, FL_JSON_MESSAGE_CODEC_ERROR,
280 FL_JSON_MESSAGE_CODEC_ERROR_INVALID_JSON,
281 "Message is not valid JSON");
282 }
283 return nullptr;
284 }
285
286 FlValue* value = handler.get_head();
287 if (value == nullptr) {
288 g_set_error(error, FL_JSON_MESSAGE_CODEC_ERROR,
289 FL_JSON_MESSAGE_CODEC_ERROR_INVALID_JSON,
290 "Message is not valid JSON");
291 return nullptr;
292 }
293
294 return fl_value_ref(value);
295 }
296
297 static void fl_json_message_codec_class_init(FlJsonMessageCodecClass* klass) {
298 FL_MESSAGE_CODEC_CLASS(klass)->encode_message =
299 fl_json_message_codec_encode_message;
300 FL_MESSAGE_CODEC_CLASS(klass)->decode_message =
301 fl_json_message_codec_decode_message;
302 }
303
304 static void fl_json_message_codec_init(FlJsonMessageCodec* self) {}
305
306 G_MODULE_EXPORT FlJsonMessageCodec* fl_json_message_codec_new() {
307 return static_cast<FlJsonMessageCodec*>(
308 g_object_new(fl_json_message_codec_get_type(), nullptr));
309 }
310
311 G_MODULE_EXPORT gchar* fl_json_message_codec_encode(FlJsonMessageCodec* codec,
312 FlValue* value,
313 GError** error) {
314 g_return_val_if_fail(FL_IS_JSON_CODEC(codec), nullptr);
315
316 rapidjson::StringBuffer buffer;
317 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
318
319 if (!write_value(writer, value, error)) {
320 return nullptr;
321 }
322
323 return g_strdup(buffer.GetString());
324 }
325
326 G_MODULE_EXPORT FlValue* fl_json_message_codec_decode(FlJsonMessageCodec* codec,
327 const gchar* text,
328 GError** error) {
329 g_return_val_if_fail(FL_IS_JSON_CODEC(codec), nullptr);
330
331 g_autoptr(GBytes) data = g_bytes_new_static(text, strlen(text));
332 g_autoptr(FlValue) value = fl_json_message_codec_decode_message(
333 FL_MESSAGE_CODEC(codec), data, error);
334 if (value == nullptr) {
335 return nullptr;
336 }
337
338 return fl_value_ref(value);
339 }
FL_JSON_MESSAGE_CODEC_ERROR_INVALID_UTF8
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_UTF8
Definition: fl_json_message_codec.h:31
fl_value_get_int32_list
const G_MODULE_EXPORT int32_t * fl_value_get_int32_list(FlValue *self)
Definition: fl_value.cc:696
FL_VALUE_TYPE_UINT8_LIST
@ FL_VALUE_TYPE_UINT8_LIST
Definition: fl_value.h:70
fl_value_new_string_sized
G_MODULE_EXPORT FlValue * fl_value_new_string_sized(const gchar *value, size_t value_length)
Definition: fl_value.cc:283
FL_VALUE_TYPE_MAP
@ FL_VALUE_TYPE_MAP
Definition: fl_value.h:75
FlValueHandler::FlValueHandler
FlValueHandler()
Definition: fl_json_message_codec.cc:129
FlValueHandler::key
FlValue * key
Definition: fl_json_message_codec.cc:126
FL_JSON_MESSAGE_CODEC_ERROR_INVALID_OBJECT_KEY_TYPE
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_OBJECT_KEY_TYPE
Definition: fl_json_message_codec.h:33
FlValueHandler::String
bool String(const char *str, rapidjson::SizeType length, bool copy)
Definition: fl_json_message_codec.cc:214
FlValueHandler::StartObject
bool StartObject()
Definition: fl_json_message_codec.cc:219
fl_value_new_list
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition: fl_value.cc:349
FlValueHandler::Uint64
bool Uint64(uint64_t i)
Definition: fl_json_message_codec.cc:197
i
int i
Definition: fl_socket_accessible.cc:18
fl_value_get_float_list
const G_MODULE_EXPORT double * fl_value_get_float_list(FlValue *self)
Definition: fl_value.cc:717
fl_value_new_bool
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:255
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
fl_json_message_codec_new
G_MODULE_EXPORT FlJsonMessageCodec * fl_json_message_codec_new()
Definition: fl_json_message_codec.cc:306
fl_json_message_codec.h
FlValueHandler::Bool
bool Bool(bool b)
Definition: fl_json_message_codec.cc:189
FlValueHandler::~FlValueHandler
~FlValueHandler()
Definition: fl_json_message_codec.cc:136
fl_value_set_take
G_MODULE_EXPORT void fl_value_set_take(FlValue *self, FlValue *key, FlValue *value)
Definition: fl_value.cc:618
fl_value_new_null
G_MODULE_EXPORT FlValue * fl_value_new_null()
Definition: fl_value.cc:251
FL_VALUE_TYPE_LIST
@ FL_VALUE_TYPE_LIST
Definition: fl_value.h:74
FlValueHandler::get_head
FlValue * get_head()
Definition: fl_json_message_codec.cc:147
_FlJsonMessageCodec
Definition: fl_json_message_codec.cc:16
fl_value_get_bool
G_MODULE_EXPORT bool fl_value_get_bool(FlValue *self)
Definition: fl_value.cc:661
fl_value_get_uint8_list
const G_MODULE_EXPORT uint8_t * fl_value_get_uint8_list(FlValue *self)
Definition: fl_value.cc:689
fl_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
fl_value_get_string
const G_MODULE_EXPORT gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:682
FlValueHandler::EndArray
bool EndArray(rapidjson::SizeType elementCount)
Definition: fl_json_message_codec.cc:236
FlValueHandler::Key
bool Key(const char *str, rapidjson::SizeType length, bool copy)
Definition: fl_json_message_codec.cc:221
G_DEFINE_TYPE
G_DEFINE_TYPE(FlJsonMessageCodec, fl_json_message_codec, fl_message_codec_get_type()) static gboolean write_value(rapidjson
Definition: fl_json_message_codec.cc:20
FL_VALUE_TYPE_NULL
@ FL_VALUE_TYPE_NULL
Definition: fl_value.h:65
_FlJsonMessageCodec::parent_instance
FlMessageCodec parent_instance
Definition: fl_json_message_codec.cc:17
FlValueHandler::Uint
bool Uint(unsigned i)
Definition: fl_json_message_codec.cc:193
fl_value_get_int
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition: fl_value.cc:668
fl_value_unref
G_MODULE_EXPORT void fl_value_unref(FlValue *self)
Definition: fl_value.cc:400
FlValueHandler::add
bool add(FlValue *value)
Definition: fl_json_message_codec.cc:161
fl_value_ref
G_MODULE_EXPORT FlValue * fl_value_ref(FlValue *self)
Definition: fl_value.cc:394
G_DEFINE_QUARK
G_DEFINE_QUARK(fl_binary_messenger_codec_error_quark, fl_binary_messenger_codec_error) G_DECLARE_FINAL_TYPE(FlBinaryMessengerImpl
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
fl_value_get_type
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
fl_value_get_list_value
G_MODULE_EXPORT FlValue * fl_value_get_list_value(FlValue *self, size_t index)
Definition: fl_value.cc:776
fl_json_message_codec_class_init
static void fl_json_message_codec_class_init(FlJsonMessageCodecClass *klass)
Definition: fl_json_message_codec.cc:297
FlValueHandler::pop
void pop()
Definition: fl_json_message_codec.cc:158
fl_json_message_codec_encode
G_MODULE_EXPORT gchar * fl_json_message_codec_encode(FlJsonMessageCodec *codec, FlValue *value, GError **error)
Definition: fl_json_message_codec.cc:311
FL_VALUE_TYPE_STRING
@ FL_VALUE_TYPE_STRING
Definition: fl_value.h:69
FlValueHandler::EndObject
bool EndObject(rapidjson::SizeType memberCount)
Definition: fl_json_message_codec.cc:229
FlValueHandler::RawNumber
bool RawNumber(const char *str, rapidjson::SizeType length, bool copy)
Definition: fl_json_message_codec.cc:208
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_json_message_codec_encode_message
static GBytes * fl_json_message_codec_encode_message(FlMessageCodec *codec, FlValue *message, GError **error)
Definition: fl_json_message_codec.cc:243
fl_json_message_codec_error_quark
G_MODULE_EXPORT GQuark fl_json_message_codec_error_quark(void) G_GNUC_CONST
FL_MESSAGE_CODEC_ERROR_FAILED
@ FL_MESSAGE_CODEC_ERROR_FAILED
Definition: fl_message_codec.h:34
fl_value_get_float
G_MODULE_EXPORT double fl_value_get_float(FlValue *self)
Definition: fl_value.cc:675
fl_value_get_length
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition: fl_value.cc:724
FL_VALUE_TYPE_INT64_LIST
@ FL_VALUE_TYPE_INT64_LIST
Definition: fl_value.h:72
FlValueHandler::push
void push(FlValue *value)
Definition: fl_json_message_codec.cc:155
FL_VALUE_TYPE_INT
@ FL_VALUE_TYPE_INT
Definition: fl_value.h:67
FlValueHandler::Int64
bool Int64(int64_t i)
Definition: fl_json_message_codec.cc:195
FlValueHandler::Double
bool Double(double d)
Definition: fl_json_message_codec.cc:206
fl_json_message_codec_decode_message
static FlValue * fl_json_message_codec_decode_message(FlMessageCodec *codec, GBytes *message, GError **error)
Definition: fl_json_message_codec.cc:258
FlValueHandler::Null
bool Null()
Definition: fl_json_message_codec.cc:187
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
FlValueHandler
Definition: fl_json_message_codec.cc:124
FL_VALUE_TYPE_FLOAT_LIST
@ FL_VALUE_TYPE_FLOAT_LIST
Definition: fl_value.h:73
FL_JSON_MESSAGE_CODEC_ERROR
#define FL_JSON_MESSAGE_CODEC_ERROR
Definition: fl_json_message_codec.h:27
fl_json_message_codec_decode
G_MODULE_EXPORT FlValue * fl_json_message_codec_decode(FlJsonMessageCodec *codec, const gchar *text, GError **error)
Definition: fl_json_message_codec.cc:326
fl_value_append
G_MODULE_EXPORT void fl_value_append(FlValue *self, FlValue *value)
Definition: fl_value.cc:592
buffer
static const uint8_t buffer[]
Definition: fl_pixel_buffer_texture_test.cc:44
FL_VALUE_TYPE_FLOAT
@ FL_VALUE_TYPE_FLOAT
Definition: fl_value.h:68
FL_VALUE_TYPE_INT32_LIST
@ FL_VALUE_TYPE_INT32_LIST
Definition: fl_value.h:71
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE
@ FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE
Definition: fl_message_codec.h:37
FlValueHandler::error
GError * error
Definition: fl_json_message_codec.cc:127
fl_value_new_float
G_MODULE_EXPORT FlValue * fl_value_new_float(double value)
Definition: fl_value.cc:269
FlValueHandler::Int
bool Int(int i)
Definition: fl_json_message_codec.cc:191
FL_JSON_MESSAGE_CODEC_ERROR_INVALID_JSON
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_JSON
Definition: fl_json_message_codec.h:32
fl_value_get_map_key
G_MODULE_EXPORT FlValue * fl_value_get_map_key(FlValue *self, size_t index)
Definition: fl_value.cc:784
fl_value_get_int64_list
const G_MODULE_EXPORT int64_t * fl_value_get_int64_list(FlValue *self)
Definition: fl_value.cc:703
FL_VALUE_TYPE_BOOL
@ FL_VALUE_TYPE_BOOL
Definition: fl_value.h:66
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
length
size_t length
Definition: fl_standard_message_codec_test.cc:1113
fl_json_message_codec_init
static void fl_json_message_codec_init(FlJsonMessageCodec *self)
Definition: fl_json_message_codec.cc:304
fl_value_get_map_value
G_MODULE_EXPORT FlValue * fl_value_get_map_value(FlValue *self, size_t index)
Definition: fl_value.cc:792
FlValueHandler::StartArray
bool StartArray()
Definition: fl_json_message_codec.cc:234
FlValueHandler::stack
GPtrArray * stack
Definition: fl_json_message_codec.cc:125
FL_MESSAGE_CODEC_ERROR
#define FL_MESSAGE_CODEC_ERROR
Definition: fl_message_codec.h:30