Flutter Engine
 
Loading...
Searching...
No Matches
standard_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// This file contains what would normally be standard_codec_serializer.cc,
6// standard_message_codec.cc, and standard_method_codec.cc. They are grouped
7// together to simplify use of the client wrapper, since the common case is
8// that any client that needs one of these files needs all three.
9
10#include <cassert>
11#include <cstring>
12#include <iostream>
13#include <map>
14#include <string>
15#include <vector>
16
17#include "byte_buffer_streams.h"
21
22namespace flutter {
23
24// ===== standard_codec_serializer.h =====
25
26namespace {
27
28// The order/values here must match the constants in message_codecs.dart.
29enum class EncodedType {
30 kNull = 0,
31 kTrue,
32 kFalse,
33 kInt32,
34 kInt64,
35 kLargeInt, // No longer used. If encountered, treat as kString.
36 kFloat64,
37 kString,
38 kUInt8List,
39 kInt32List,
40 kInt64List,
41 kFloat64List,
42 kList,
43 kMap,
44 kFloat32List,
45};
46
47// Returns the encoded type that should be written when serializing |value|.
48EncodedType EncodedTypeForValue(const EncodableValue& value) {
49 switch (value.index()) {
50 case 0:
51 return EncodedType::kNull;
52 case 1:
53 return std::get<bool>(value) ? EncodedType::kTrue : EncodedType::kFalse;
54 case 2:
55 return EncodedType::kInt32;
56 case 3:
57 return EncodedType::kInt64;
58 case 4:
59 return EncodedType::kFloat64;
60 case 5:
61 return EncodedType::kString;
62 case 6:
63 return EncodedType::kUInt8List;
64 case 7:
65 return EncodedType::kInt32List;
66 case 8:
67 return EncodedType::kInt64List;
68 case 9:
69 return EncodedType::kFloat64List;
70 case 10:
71 return EncodedType::kList;
72 case 11:
73 return EncodedType::kMap;
74 case 13:
75 return EncodedType::kFloat32List;
76 }
77 assert(false);
78 return EncodedType::kNull;
79}
80
81} // namespace
82
84
86
88 static StandardCodecSerializer sInstance;
89 return sInstance;
90};
91
93 ByteStreamReader* stream) const {
94 uint8_t type = stream->ReadByte();
95 return ReadValueOfType(type, stream);
96}
97
99 ByteStreamWriter* stream) const {
100 stream->WriteByte(static_cast<uint8_t>(EncodedTypeForValue(value)));
101 // TODO(cbracken): Consider replacing this with std::visit.
102 switch (value.index()) {
103 case 0:
104 case 1:
105 // Null and bool are encoded directly in the type.
106 break;
107 case 2:
108 stream->WriteInt32(std::get<int32_t>(value));
109 break;
110 case 3:
111 stream->WriteInt64(std::get<int64_t>(value));
112 break;
113 case 4:
114 stream->WriteAlignment(8);
115 stream->WriteDouble(std::get<double>(value));
116 break;
117 case 5: {
118 const auto& string_value = std::get<std::string>(value);
119 size_t size = string_value.size();
120 WriteSize(size, stream);
121 if (size > 0) {
122 stream->WriteBytes(
123 reinterpret_cast<const uint8_t*>(string_value.data()), size);
124 }
125 break;
126 }
127 case 6:
128 WriteVector(std::get<std::vector<uint8_t>>(value), stream);
129 break;
130 case 7:
131 WriteVector(std::get<std::vector<int32_t>>(value), stream);
132 break;
133 case 8:
134 WriteVector(std::get<std::vector<int64_t>>(value), stream);
135 break;
136 case 9:
137 WriteVector(std::get<std::vector<double>>(value), stream);
138 break;
139 case 10: {
140 const auto& list = std::get<EncodableList>(value);
141 WriteSize(list.size(), stream);
142 for (const auto& item : list) {
143 WriteValue(item, stream);
144 }
145 break;
146 }
147 case 11: {
148 const auto& map = std::get<EncodableMap>(value);
149 WriteSize(map.size(), stream);
150 for (const auto& pair : map) {
151 WriteValue(pair.first, stream);
152 WriteValue(pair.second, stream);
153 }
154 break;
155 }
156 case 12:
157 std::cerr
158 << "Unhandled custom type in StandardCodecSerializer::WriteValue. "
159 << "Custom types require codec extensions." << std::endl;
160 break;
161 case 13: {
162 WriteVector(std::get<std::vector<float>>(value), stream);
163 break;
164 }
165 }
166}
167
169 uint8_t type,
170 ByteStreamReader* stream) const {
171 switch (static_cast<EncodedType>(type)) {
172 case EncodedType::kNull:
173 return EncodableValue();
174 case EncodedType::kTrue:
175 return EncodableValue(true);
176 case EncodedType::kFalse:
177 return EncodableValue(false);
178 case EncodedType::kInt32:
179 return EncodableValue(stream->ReadInt32());
180 case EncodedType::kInt64:
181 return EncodableValue(stream->ReadInt64());
182 case EncodedType::kFloat64:
183 stream->ReadAlignment(8);
184 return EncodableValue(stream->ReadDouble());
185 case EncodedType::kLargeInt:
186 case EncodedType::kString: {
187 size_t size = ReadSize(stream);
188 std::string string_value;
189 string_value.resize(size);
190 stream->ReadBytes(reinterpret_cast<uint8_t*>(&string_value[0]), size);
191 return EncodableValue(string_value);
192 }
193 case EncodedType::kUInt8List:
194 return ReadVector<uint8_t>(stream);
195 case EncodedType::kInt32List:
196 return ReadVector<int32_t>(stream);
197 case EncodedType::kInt64List:
198 return ReadVector<int64_t>(stream);
199 case EncodedType::kFloat64List:
200 return ReadVector<double>(stream);
201 case EncodedType::kList: {
202 size_t length = ReadSize(stream);
203 EncodableList list_value;
204 list_value.reserve(length);
205 for (size_t i = 0; i < length; ++i) {
206 list_value.push_back(ReadValue(stream));
207 }
208 return EncodableValue(list_value);
209 }
210 case EncodedType::kMap: {
211 size_t length = ReadSize(stream);
212 EncodableMap map_value;
213 for (size_t i = 0; i < length; ++i) {
214 EncodableValue key = ReadValue(stream);
216 map_value.emplace(std::move(key), std::move(value));
217 }
218 return EncodableValue(map_value);
219 }
220 case EncodedType::kFloat32List: {
221 return ReadVector<float>(stream);
222 }
223 }
224 std::cerr << "Unknown type in StandardCodecSerializer::ReadValueOfType: "
225 << static_cast<int>(type) << std::endl;
226 return EncodableValue();
227}
228
230 uint8_t byte = stream->ReadByte();
231 if (byte < 254) {
232 return byte;
233 } else if (byte == 254) {
234 uint16_t value = 0;
235 stream->ReadBytes(reinterpret_cast<uint8_t*>(&value), 2);
236 return value;
237 } else {
238 uint32_t value = 0;
239 stream->ReadBytes(reinterpret_cast<uint8_t*>(&value), 4);
240 return value;
241 }
242}
243
245 ByteStreamWriter* stream) const {
246 if (size < 254) {
247 stream->WriteByte(static_cast<uint8_t>(size));
248 } else if (size <= 0xffff) {
249 stream->WriteByte(254);
250 uint16_t value = static_cast<uint16_t>(size);
251 stream->WriteBytes(reinterpret_cast<uint8_t*>(&value), 2);
252 } else {
253 stream->WriteByte(255);
254 uint32_t value = static_cast<uint32_t>(size);
255 stream->WriteBytes(reinterpret_cast<uint8_t*>(&value), 4);
256 }
257}
258
259template <typename T>
260EncodableValue StandardCodecSerializer::ReadVector(
261 ByteStreamReader* stream) const {
262 size_t count = ReadSize(stream);
263 std::vector<T> vector;
264 vector.resize(count);
265 uint8_t type_size = static_cast<uint8_t>(sizeof(T));
266 if (type_size > 1) {
267 stream->ReadAlignment(type_size);
268 }
269 stream->ReadBytes(reinterpret_cast<uint8_t*>(vector.data()),
270 count * type_size);
271 return EncodableValue(vector);
272}
273
274template <typename T>
275void StandardCodecSerializer::WriteVector(const std::vector<T> vector,
276 ByteStreamWriter* stream) const {
277 size_t count = vector.size();
278 WriteSize(count, stream);
279 if (count == 0) {
280 return;
281 }
282 uint8_t type_size = static_cast<uint8_t>(sizeof(T));
283 if (type_size > 1) {
284 stream->WriteAlignment(type_size);
285 }
286 stream->WriteBytes(reinterpret_cast<const uint8_t*>(vector.data()),
287 count * type_size);
288}
289
290// ===== standard_message_codec.h =====
291
292// static
294 const StandardCodecSerializer* serializer) {
295 if (!serializer) {
297 }
298 static auto* sInstances = new std::map<const StandardCodecSerializer*,
299 std::unique_ptr<StandardMessageCodec>>;
300 auto it = sInstances->find(serializer);
301 if (it == sInstances->end()) {
302 // Uses new due to private constructor (to prevent API clients from
303 // accidentally passing temporary codec instances to channels).
304 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
305 auto emplace_result = sInstances->emplace(
306 serializer, std::unique_ptr<StandardMessageCodec>(
307 new StandardMessageCodec(serializer)));
308 it = emplace_result.first;
309 }
310 return *(it->second);
311}
312
314 const StandardCodecSerializer* serializer)
315 : serializer_(serializer) {}
316
318
319std::unique_ptr<EncodableValue> StandardMessageCodec::DecodeMessageInternal(
320 const uint8_t* binary_message,
321 size_t message_size) const {
322 if (!binary_message) {
323 return std::make_unique<EncodableValue>();
324 }
325 ByteBufferStreamReader stream(binary_message, message_size);
326 return std::make_unique<EncodableValue>(serializer_->ReadValue(&stream));
327}
328
329std::unique_ptr<std::vector<uint8_t>>
331 const EncodableValue& message) const {
332 auto encoded = std::make_unique<std::vector<uint8_t>>();
333 ByteBufferStreamWriter stream(encoded.get());
334 serializer_->WriteValue(message, &stream);
335 return encoded;
336}
337
338// ===== standard_method_codec.h =====
339
340// static
342 const StandardCodecSerializer* serializer) {
343 if (!serializer) {
345 }
346 static auto* sInstances = new std::map<const StandardCodecSerializer*,
347 std::unique_ptr<StandardMethodCodec>>;
348 auto it = sInstances->find(serializer);
349 if (it == sInstances->end()) {
350 // Uses new due to private constructor (to prevent API clients from
351 // accidentally passing temporary codec instances to channels).
352 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
353 auto emplace_result = sInstances->emplace(
354 serializer, std::unique_ptr<StandardMethodCodec>(
355 new StandardMethodCodec(serializer)));
356 it = emplace_result.first;
357 }
358 return *(it->second);
359}
360
362 const StandardCodecSerializer* serializer)
363 : serializer_(serializer) {}
364
366
367std::unique_ptr<MethodCall<EncodableValue>>
369 size_t message_size) const {
370 ByteBufferStreamReader stream(message, message_size);
371 EncodableValue method_name_value = serializer_->ReadValue(&stream);
372 const auto* method_name = std::get_if<std::string>(&method_name_value);
373 if (!method_name) {
374 std::cerr << "Invalid method call; method name is not a string."
375 << std::endl;
376 return nullptr;
377 }
378 auto arguments =
379 std::make_unique<EncodableValue>(serializer_->ReadValue(&stream));
380 return std::make_unique<MethodCall<EncodableValue>>(*method_name,
381 std::move(arguments));
382}
383
384std::unique_ptr<std::vector<uint8_t>>
387 auto encoded = std::make_unique<std::vector<uint8_t>>();
388 ByteBufferStreamWriter stream(encoded.get());
389 serializer_->WriteValue(EncodableValue(method_call.method_name()), &stream);
390 if (method_call.arguments()) {
391 serializer_->WriteValue(*method_call.arguments(), &stream);
392 } else {
393 serializer_->WriteValue(EncodableValue(), &stream);
394 }
395 return encoded;
396}
397
398std::unique_ptr<std::vector<uint8_t>>
400 const EncodableValue* result) const {
401 auto encoded = std::make_unique<std::vector<uint8_t>>();
402 ByteBufferStreamWriter stream(encoded.get());
403 stream.WriteByte(0);
404 if (result) {
405 serializer_->WriteValue(*result, &stream);
406 } else {
407 serializer_->WriteValue(EncodableValue(), &stream);
408 }
409 return encoded;
410}
411
412std::unique_ptr<std::vector<uint8_t>>
414 const std::string& error_code,
415 const std::string& error_message,
416 const EncodableValue* error_details) const {
417 auto encoded = std::make_unique<std::vector<uint8_t>>();
418 ByteBufferStreamWriter stream(encoded.get());
419 stream.WriteByte(1);
420 serializer_->WriteValue(EncodableValue(error_code), &stream);
421 if (error_message.empty()) {
422 serializer_->WriteValue(EncodableValue(), &stream);
423 } else {
424 serializer_->WriteValue(EncodableValue(error_message), &stream);
425 }
426 if (error_details) {
427 serializer_->WriteValue(*error_details, &stream);
428 } else {
429 serializer_->WriteValue(EncodableValue(), &stream);
430 }
431 return encoded;
432}
433
435 const uint8_t* response,
436 size_t response_size,
437 MethodResult<EncodableValue>* result) const {
438 ByteBufferStreamReader stream(response, response_size);
439 uint8_t flag = stream.ReadByte();
440 switch (flag) {
441 case 0: {
442 EncodableValue value = serializer_->ReadValue(&stream);
443 if (value.IsNull()) {
444 result->Success();
445 } else {
446 result->Success(value);
447 }
448 return true;
449 }
450 case 1: {
451 EncodableValue code = serializer_->ReadValue(&stream);
452 EncodableValue message = serializer_->ReadValue(&stream);
453 EncodableValue details = serializer_->ReadValue(&stream);
454 const std::string& message_string =
455 message.IsNull() ? "" : std::get<std::string>(message);
456 if (details.IsNull()) {
457 result->Error(std::get<std::string>(code), message_string);
458 } else {
459 result->Error(std::get<std::string>(code), message_string, details);
460 }
461 return true;
462 }
463 default:
464 return false;
465 }
466}
467
468} // namespace flutter
GLenum type
virtual uint8_t ReadByte()=0
virtual void ReadBytes(uint8_t *buffer, size_t length)=0
virtual void ReadAlignment(uint8_t alignment)=0
virtual void WriteByte(uint8_t byte)=0
void WriteInt64(int64_t value)
virtual void WriteBytes(const uint8_t *bytes, size_t length)=0
virtual void WriteAlignment(uint8_t alignment)=0
void WriteDouble(double value)
void WriteInt32(int32_t value)
void Error(const std::string &error_code, const std::string &error_message, const T &error_details)
void Success(const T &result)
virtual void WriteValue(const EncodableValue &value, ByteStreamWriter *stream) const
void WriteSize(size_t size, ByteStreamWriter *stream) const
static const StandardCodecSerializer & GetInstance()
EncodableValue ReadValue(ByteStreamReader *stream) const
virtual EncodableValue ReadValueOfType(uint8_t type, ByteStreamReader *stream) const
size_t ReadSize(ByteStreamReader *stream) const
static const StandardMessageCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
std::unique_ptr< EncodableValue > DecodeMessageInternal(const uint8_t *binary_message, const size_t message_size) const override
StandardMessageCodec(StandardMessageCodec const &)=delete
std::unique_ptr< std::vector< uint8_t > > EncodeMessageInternal(const EncodableValue &message) const override
std::unique_ptr< std::vector< uint8_t > > EncodeErrorEnvelopeInternal(const std::string &error_code, const std::string &error_message, const EncodableValue *error_details) const override
std::unique_ptr< std::vector< uint8_t > > EncodeMethodCallInternal(const MethodCall< EncodableValue > &method_call) const override
StandardMethodCodec(StandardMethodCodec const &)=delete
std::unique_ptr< std::vector< uint8_t > > EncodeSuccessEnvelopeInternal(const EncodableValue *result) const override
std::unique_ptr< MethodCall< EncodableValue > > DecodeMethodCallInternal(const uint8_t *message, size_t message_size) const override
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
bool DecodeAndProcessResponseEnvelopeInternal(const uint8_t *response, size_t response_size, MethodResult< EncodableValue > *result) const override
int32_t value
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
G_BEGIN_DECLS GBytes * message
size_t length
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
std::vector< EncodableValue > EncodableList
std::map< EncodableValue, EncodableValue > EncodableMap
@ kNull
Definition paint.cc:61