Flutter Engine
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 
22 namespace flutter {
23 
24 // ===== standard_codec_serializer.h =====
25 
26 namespace {
27 
28 // The order/values here must match the constants in message_codecs.dart.
29 enum 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|.
48 EncodedType 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 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);
215  EncodableValue value = 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 
259 template <typename T>
260 EncodableValue 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 
274 template <typename T>
275 void 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) {
296  serializer = &StandardCodecSerializer::GetInstance();
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  auto emplace_result = sInstances->emplace(
305  serializer, std::unique_ptr<StandardMessageCodec>(
306  new StandardMessageCodec(serializer)));
307  it = emplace_result.first;
308  }
309  return *(it->second);
310 }
311 
313  const StandardCodecSerializer* serializer)
314  : serializer_(serializer) {}
315 
317 
318 std::unique_ptr<EncodableValue> StandardMessageCodec::DecodeMessageInternal(
319  const uint8_t* binary_message,
320  size_t message_size) const {
321  if (!binary_message) {
322  return std::make_unique<EncodableValue>();
323  }
324  ByteBufferStreamReader stream(binary_message, message_size);
325  return std::make_unique<EncodableValue>(serializer_->ReadValue(&stream));
326 }
327 
328 std::unique_ptr<std::vector<uint8_t>>
330  const EncodableValue& message) const {
331  auto encoded = std::make_unique<std::vector<uint8_t>>();
332  ByteBufferStreamWriter stream(encoded.get());
333  serializer_->WriteValue(message, &stream);
334  return encoded;
335 }
336 
337 // ===== standard_method_codec.h =====
338 
339 // static
341  const StandardCodecSerializer* serializer) {
342  if (!serializer) {
343  serializer = &StandardCodecSerializer::GetInstance();
344  }
345  static auto* sInstances = new std::map<const StandardCodecSerializer*,
346  std::unique_ptr<StandardMethodCodec>>;
347  auto it = sInstances->find(serializer);
348  if (it == sInstances->end()) {
349  // Uses new due to private constructor (to prevent API clients from
350  // accidentally passing temporary codec instances to channels).
351  auto emplace_result = sInstances->emplace(
352  serializer, std::unique_ptr<StandardMethodCodec>(
353  new StandardMethodCodec(serializer)));
354  it = emplace_result.first;
355  }
356  return *(it->second);
357 }
358 
360  const StandardCodecSerializer* serializer)
361  : serializer_(serializer) {}
362 
364 
365 std::unique_ptr<MethodCall<EncodableValue>>
367  size_t message_size) const {
368  ByteBufferStreamReader stream(message, message_size);
369  EncodableValue method_name_value = serializer_->ReadValue(&stream);
370  const auto* method_name = std::get_if<std::string>(&method_name_value);
371  if (!method_name) {
372  std::cerr << "Invalid method call; method name is not a string."
373  << std::endl;
374  return nullptr;
375  }
376  auto arguments =
377  std::make_unique<EncodableValue>(serializer_->ReadValue(&stream));
378  return std::make_unique<MethodCall<EncodableValue>>(*method_name,
379  std::move(arguments));
380 }
381 
382 std::unique_ptr<std::vector<uint8_t>>
385  auto encoded = std::make_unique<std::vector<uint8_t>>();
386  ByteBufferStreamWriter stream(encoded.get());
387  serializer_->WriteValue(EncodableValue(method_call.method_name()), &stream);
388  if (method_call.arguments()) {
389  serializer_->WriteValue(*method_call.arguments(), &stream);
390  } else {
391  serializer_->WriteValue(EncodableValue(), &stream);
392  }
393  return encoded;
394 }
395 
396 std::unique_ptr<std::vector<uint8_t>>
398  const EncodableValue* result) const {
399  auto encoded = std::make_unique<std::vector<uint8_t>>();
400  ByteBufferStreamWriter stream(encoded.get());
401  stream.WriteByte(0);
402  if (result) {
403  serializer_->WriteValue(*result, &stream);
404  } else {
405  serializer_->WriteValue(EncodableValue(), &stream);
406  }
407  return encoded;
408 }
409 
410 std::unique_ptr<std::vector<uint8_t>>
412  const std::string& error_code,
413  const std::string& error_message,
414  const EncodableValue* error_details) const {
415  auto encoded = std::make_unique<std::vector<uint8_t>>();
416  ByteBufferStreamWriter stream(encoded.get());
417  stream.WriteByte(1);
418  serializer_->WriteValue(EncodableValue(error_code), &stream);
419  if (error_message.empty()) {
420  serializer_->WriteValue(EncodableValue(), &stream);
421  } else {
422  serializer_->WriteValue(EncodableValue(error_message), &stream);
423  }
424  if (error_details) {
425  serializer_->WriteValue(*error_details, &stream);
426  } else {
427  serializer_->WriteValue(EncodableValue(), &stream);
428  }
429  return encoded;
430 }
431 
433  const uint8_t* response,
434  size_t response_size,
436  ByteBufferStreamReader stream(response, response_size);
437  uint8_t flag = stream.ReadByte();
438  switch (flag) {
439  case 0: {
440  EncodableValue value = serializer_->ReadValue(&stream);
441  if (value.IsNull()) {
442  result->Success();
443  } else {
444  result->Success(value);
445  }
446  return true;
447  }
448  case 1: {
449  EncodableValue code = serializer_->ReadValue(&stream);
450  EncodableValue message = serializer_->ReadValue(&stream);
451  EncodableValue details = serializer_->ReadValue(&stream);
452  const std::string& message_string =
453  message.IsNull() ? "" : std::get<std::string>(message);
454  if (details.IsNull()) {
455  result->Error(std::get<std::string>(code), message_string);
456  } else {
457  result->Error(std::get<std::string>(code), message_string, details);
458  }
459  return true;
460  }
461  default:
462  return false;
463  }
464 }
465 
466 } // namespace flutter
size_t ReadSize(ByteStreamReader *stream) const
virtual void WriteAlignment(uint8_t alignment)=0
G_BEGIN_DECLS FlMethodCall * method_call
virtual void WriteValue(const EncodableValue &value, ByteStreamWriter *stream) const
virtual void ReadAlignment(uint8_t alignment)=0
const T * arguments() const
Definition: method_call.h:34
virtual void ReadBytes(uint8_t *buffer, size_t length)=0
virtual void WriteByte(uint8_t byte)=0
std::unique_ptr< std::vector< uint8_t > > EncodeErrorEnvelopeInternal(const std::string &error_code, const std::string &error_message, const EncodableValue *error_details) const override
void Error(const std::string &error_code, const std::string &error_message, const T &error_details)
Definition: method_result.h:41
StandardMessageCodec(StandardMessageCodec const &)=delete
enum flutter::testing::@1969::KeyboardChange::Type type
GAsyncResult * result
Win32Message message
EncodableValue ReadValue(ByteStreamReader *stream) const
void WriteDouble(double value)
Definition: byte_streams.h:78
static const StandardCodecSerializer & GetInstance()
static const StandardMessageCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data observatory The hostname IP address on which the Dart Observatory should be served If not defaults to or::depending on whether ipv6 is specified disable Disable the Dart Observatory The observatory is never available in release mode Bind to the IPv6 localhost address for the Dart Observatory Ignored if observatory host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent Remove all existing persistent cache This is mainly for debugging purposes such as reproducing the shader compilation jank 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
Definition: switches.h:226
void Success(const T &result)
Definition: method_result.h:29
uint8_t value
std::unique_ptr< EncodableValue > DecodeMessageInternal(const uint8_t *binary_message, const size_t message_size) const override
virtual void WriteBytes(const uint8_t *bytes, size_t length)=0
void WriteInt32(int32_t value)
Definition: byte_streams.h:68
FlutterSemanticsFlag flag
std::unique_ptr< std::vector< uint8_t > > EncodeMessageInternal(const EncodableValue &message) const override
virtual EncodableValue ReadValueOfType(uint8_t type, ByteStreamReader *stream) const
size_t length
std::vector< EncodableValue > EncodableList
bool DecodeAndProcessResponseEnvelopeInternal(const uint8_t *response, size_t response_size, MethodResult< EncodableValue > *result) const override
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
std::unique_ptr< std::vector< uint8_t > > EncodeSuccessEnvelopeInternal(const EncodableValue *result) const override
void WriteInt64(int64_t value)
Definition: byte_streams.h:73
void WriteSize(size_t size, ByteStreamWriter *stream) const
StandardMethodCodec(StandardMethodCodec const &)=delete
std::map< EncodableValue, EncodableValue > EncodableMap
std::unique_ptr< MethodCall< EncodableValue > > DecodeMethodCallInternal(const uint8_t *message, size_t message_size) const override
const std::string & method_name() const
Definition: method_call.h:31
virtual uint8_t ReadByte()=0
std::unique_ptr< std::vector< uint8_t > > EncodeMethodCallInternal(const MethodCall< EncodableValue > &method_call) const override