Flutter Engine
encodable_value.h
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 #ifndef FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
6 #define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
7 
8 #include <any>
9 #include <cassert>
10 #include <cstdint>
11 #include <map>
12 #include <string>
13 #include <utility>
14 #include <variant>
15 #include <vector>
16 
17 // Unless overridden, attempt to detect the RTTI state from the compiler.
18 #ifndef FLUTTER_ENABLE_RTTI
19 #if defined(_MSC_VER)
20 #ifdef _CPPRTTI
21 #define FLUTTER_ENABLE_RTTI 1
22 #endif
23 #elif defined(__clang__)
24 #if __has_feature(cxx_rtti)
25 #define FLUTTER_ENABLE_RTTI 1
26 #endif
27 #elif defined(__GNUC__)
28 #ifdef __GXX_RTTI
29 #define FLUTTER_ENABLE_RTTI 1
30 #endif
31 #endif
32 #endif // #ifndef FLUTTER_ENABLE_RTTI
33 
34 namespace flutter {
35 
36 static_assert(sizeof(double) == 8, "EncodableValue requires a 64-bit double");
37 
38 // A container for arbitrary types in EncodableValue.
39 //
40 // This is used in conjunction with StandardCodecExtension to allow using other
41 // types with a StandardMethodCodec/StandardMessageCodec. It is implicitly
42 // convertible to EncodableValue, so constructing an EncodableValue from a
43 // custom type can generally be written as:
44 // CustomEncodableValue(MyType(...))
45 // rather than:
46 // EncodableValue(CustomEncodableValue(MyType(...)))
47 //
48 // For extracting received custom types, it is implicitly convertible to
49 // std::any. For example:
50 // const MyType& my_type_value =
51 // std::any_cast<MyType>(std::get<CustomEncodableValue>(value));
52 //
53 // If RTTI is enabled, different extension types can be checked with type():
54 // if (custom_value->type() == typeid(SomeData)) { ... }
55 // Clients that wish to disable RTTI would need to decide on another approach
56 // for distinguishing types (e.g., in StandardCodecExtension::WriteValueOfType)
57 // if multiple custom types are needed. For instance, wrapping all of the
58 // extension types in an EncodableValue-style variant, and only ever storing
59 // that variant in CustomEncodableValue.
61  public:
62  explicit CustomEncodableValue(const std::any& value) : value_(value) {}
63  ~CustomEncodableValue() = default;
64 
65  // Allow implicit conversion to std::any to allow direct use of any_cast.
66  operator std::any&() { return value_; }
67  operator const std::any&() const { return value_; }
68 
69 #if defined(FLUTTER_ENABLE_RTTI) && FLUTTER_ENABLE_RTTI
70  // Passthrough to std::any's type().
71  const std::type_info& type() const noexcept { return value_.type(); }
72 #endif
73 
74  // This operator exists only to provide a stable ordering for use as a
75  // std::map key, to satisfy the compiler requirements for EncodableValue.
76  // It does not attempt to provide useful ordering semantics, and using a
77  // custom value as a map key is not recommended.
78  bool operator<(const CustomEncodableValue& other) const {
79  return this < &other;
80  }
81  bool operator==(const CustomEncodableValue& other) const {
82  return this == &other;
83  }
84 
85  private:
86  std::any value_;
87 };
88 
89 class EncodableValue;
90 
91 // Convenience type aliases.
92 using EncodableList = std::vector<EncodableValue>;
93 using EncodableMap = std::map<EncodableValue, EncodableValue>;
94 
95 namespace internal {
96 // The base class for EncodableValue. Do not use this directly; it exists only
97 // for EncodableValue to inherit from.
98 //
99 // Do not change the order or indexes of the items here; see the comment on
100 // EncodableValue
101 using EncodableValueVariant = std::variant<std::monostate,
102  bool,
103  int32_t,
104  int64_t,
105  double,
106  std::string,
107  std::vector<uint8_t>,
108  std::vector<int32_t>,
109  std::vector<int64_t>,
110  std::vector<double>,
112  EncodableMap,
114  std::vector<float>>;
115 } // namespace internal
116 
117 // An object that can contain any value or collection type supported by
118 // Flutter's standard method codec.
119 //
120 // For details, see:
121 // https://api.flutter.dev/flutter/services/StandardMessageCodec-class.html
122 //
123 // As an example, the following Dart structure:
124 // {
125 // 'flag': true,
126 // 'name': 'Thing',
127 // 'values': [1, 2.0, 4],
128 // }
129 // would correspond to:
130 // EncodableValue(EncodableMap{
131 // {EncodableValue("flag"), EncodableValue(true)},
132 // {EncodableValue("name"), EncodableValue("Thing")},
133 // {EncodableValue("values"), EncodableValue(EncodableList{
134 // EncodableValue(1),
135 // EncodableValue(2.0),
136 // EncodableValue(4),
137 // })},
138 // })
139 //
140 // The primary API surface for this object is std::variant. For instance,
141 // getting a string value from an EncodableValue, with type checking:
142 // if (std::holds_alternative<std::string>(value)) {
143 // std::string some_string = std::get<std::string>(value);
144 // }
145 //
146 // The order/indexes of the variant types is part of the API surface, and is
147 // guaranteed not to change.
148 //
149 // The variant types are mapped with Dart types in following ways:
150 // std::monostate -> null
151 // bool -> bool
152 // int32_t -> int
153 // int64_t -> int
154 // double -> double
155 // std::string -> String
156 // std::vector<uint8_t> -> Uint8List
157 // std::vector<int32_t> -> Int32List
158 // std::vector<int64_t> -> Int64List
159 // std::vector<float> -> Float32List
160 // std::vector<double> -> Float64List
161 // EncodableList -> List
162 // EncodableMap -> Map
164  public:
165  // Rely on std::variant for most of the constructors/operators.
167  using super::super;
168  using super::operator=;
169 
170  explicit EncodableValue() = default;
171 
172  // Avoid the C++17 pitfall of conversion from char* to bool. Should not be
173  // needed for C++20.
174  explicit EncodableValue(const char* string) : super(std::string(string)) {}
175  EncodableValue& operator=(const char* other) {
176  *this = std::string(other);
177  return *this;
178  }
179 
180  // Allow implicit conversion from CustomEncodableValue; the only reason to
181  // make a CustomEncodableValue (which can only be constructed explicitly) is
182  // to use it with EncodableValue, so the risk of unintended conversions is
183  // minimal, and it avoids the need for the verbose:
184  // EncodableValue(CustomEncodableValue(...)).
186 
187  // Override the conversion constructors from std::variant to make them
188  // explicit, to avoid implicit conversion.
189  //
190  // While implicit conversion can be convenient in some cases, it can have very
191  // surprising effects. E.g., calling a function that takes an EncodableValue
192  // but accidentally passing an EncodableValue* would, instead of failing to
193  // compile, go through a pointer->bool->EncodableValue(bool) chain and
194  // silently call the function with a temp-constructed EncodableValue(true).
195  template <class T>
196  constexpr explicit EncodableValue(T&& t) noexcept : super(t) {}
197 
198  // Returns true if the value is null. Convenience wrapper since unlike the
199  // other types, std::monostate uses aren't self-documenting.
200  bool IsNull() const { return std::holds_alternative<std::monostate>(*this); }
201 
202  // Convenience method to simplify handling objects received from Flutter
203  // where the values may be larger than 32-bit, since they have the same type
204  // on the Dart side, but will be either 32-bit or 64-bit here depending on
205  // the value.
206  //
207  // Calling this method if the value doesn't contain either an int32_t or an
208  // int64_t will throw an exception.
209  int64_t LongValue() const {
210  if (std::holds_alternative<int32_t>(*this)) {
211  return std::get<int32_t>(*this);
212  }
213  return std::get<int64_t>(*this);
214  }
215 };
216 
217 } // namespace flutter
218 
219 #endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
KeyCallType type
internal::EncodableValueVariant super
EncodableValue(const char *string)
Definition: ref_ptr.h:252
bool operator==(const CustomEncodableValue &other) const
CustomEncodableValue(const std::any &value)
constexpr EncodableValue(T &&t) noexcept
uint8_t value
int64_t LongValue() const
EncodableValue(const CustomEncodableValue &v)
std::vector< EncodableValue > EncodableList
std::map< EncodableValue, EncodableValue > EncodableMap
std::variant< std::monostate, bool, int32_t, int64_t, double, std::string, std::vector< uint8_t >, std::vector< int32_t >, std::vector< int64_t >, std::vector< double >, EncodableList, EncodableMap, CustomEncodableValue, std::vector< float > > EncodableValueVariant
bool operator<(const CustomEncodableValue &other) const
EncodableValue & operator=(const char *other)