• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
6 #define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
7 
8 #include <assert.h>
9 #include <cstdint>
10 #include <map>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 namespace flutter {
16 
17 static_assert(sizeof(double) == 8, "EncodableValue requires a 64-bit double");
18 
19 class EncodableValue;
20 // Convenience type aliases for list and map EncodableValue types.
21 using EncodableList = std::vector<EncodableValue>;
22 using EncodableMap = std::map<EncodableValue, EncodableValue>;
23 
24 // An object that can contain any value or collection type supported by
25 // Flutter's standard method codec.
26 //
27 // For details, see:
28 // https://api.flutter.dev/flutter/services/StandardMessageCodec-class.html
29 //
30 // As an example, the following Dart structure:
31 //   {
32 //     'flag': true,
33 //     'name': 'Thing',
34 //     'values': [1, 2.0, 4],
35 //   }
36 // would correspond to:
37 //   EncodableValue(EncodableMap{
38 //       {EncodableValue("flag"), EncodableValue(true)},
39 //       {EncodableValue("name"), EncodableValue("Thing")},
40 //       {EncodableValue("values"), EncodableValue(EncodableList{
41 //                                      EncodableValue(1),
42 //                                      EncodableValue(2.0),
43 //                                      EncodableValue(4),
44 //                                  })},
45 //   })
46 class EncodableValue {
47  public:
48   // Possible types for an EncodableValue to reperesent.
49   enum class Type {
50     kNull,        // A null value.
51     kBool,        // A boolean value.
52     kInt,         // A 32-bit integer.
53     kLong,        // A 64-bit integer.
54     kDouble,      // A 64-bit floating point number.
55     kString,      // A string.
56     kByteList,    // A list of bytes.
57     kIntList,     // A list of 32-bit integers.
58     kLongList,    // A list of 64-bit integers.
59     kDoubleList,  // A list of 64-bit floating point numbers.
60     kList,        // A list of EncodableValues.
61     kMap,         // A mapping from EncodableValues to EncodableValues.
62   };
63 
64   // Creates an instance representing a null value.
EncodableValue()65   EncodableValue() {}
66 
67   // Creates an instance representing a bool value.
EncodableValue(bool value)68   explicit EncodableValue(bool value) : bool_(value), type_(Type::kBool) {}
69 
70   // Creates an instance representing a 32-bit integer value.
EncodableValue(int32_t value)71   explicit EncodableValue(int32_t value) : int_(value), type_(Type::kInt) {}
72 
73   // Creates an instance representing a 64-bit integer value.
EncodableValue(int64_t value)74   explicit EncodableValue(int64_t value) : long_(value), type_(Type::kLong) {}
75 
76   // Creates an instance representing a 64-bit floating point value.
EncodableValue(double value)77   explicit EncodableValue(double value)
78       : double_(value), type_(Type::kDouble) {}
79 
80   // Creates an instance representing a string value.
EncodableValue(const char * value)81   explicit EncodableValue(const char* value)
82       : string_(new std::string(value)), type_(Type::kString) {}
83 
84   // Creates an instance representing a string value.
EncodableValue(const std::string & value)85   explicit EncodableValue(const std::string& value)
86       : string_(new std::string(value)), type_(Type::kString) {}
87 
88   // Creates an instance representing a list of bytes.
EncodableValue(std::vector<uint8_t> list)89   explicit EncodableValue(std::vector<uint8_t> list)
90       : byte_list_(new std::vector<uint8_t>(std::move(list))),
91         type_(Type::kByteList) {}
92 
93   // Creates an instance representing a list of 32-bit integers.
EncodableValue(std::vector<int32_t> list)94   explicit EncodableValue(std::vector<int32_t> list)
95       : int_list_(new std::vector<int32_t>(std::move(list))),
96         type_(Type::kIntList) {}
97 
98   // Creates an instance representing a list of 64-bit integers.
EncodableValue(std::vector<int64_t> list)99   explicit EncodableValue(std::vector<int64_t> list)
100       : long_list_(new std::vector<int64_t>(std::move(list))),
101         type_(Type::kLongList) {}
102 
103   // Creates an instance representing a list of 64-bit floating point values.
EncodableValue(std::vector<double> list)104   explicit EncodableValue(std::vector<double> list)
105       : double_list_(new std::vector<double>(std::move(list))),
106         type_(Type::kDoubleList) {}
107 
108   // Creates an instance representing a list of EncodableValues.
EncodableValue(EncodableList list)109   explicit EncodableValue(EncodableList list)
110       : list_(new EncodableList(std::move(list))), type_(Type::kList) {}
111 
112   // Creates an instance representing a map from EncodableValues to
113   // EncodableValues.
EncodableValue(EncodableMap map)114   explicit EncodableValue(EncodableMap map)
115       : map_(new EncodableMap(std::move(map))), type_(Type::kMap) {}
116 
117   // Convience constructor for creating default value of the given type.
118   //
119   // Collections types will be empty, numeric types will be 0, strings will be
120   // empty, and booleans will be false. For non-collection types, prefer using
121   // the value-based constructor with an explicit value for clarity.
EncodableValue(Type type)122   explicit EncodableValue(Type type) : type_(type) {
123     switch (type_) {
124       case Type::kNull:
125         break;
126       case Type::kBool:
127         bool_ = false;
128         break;
129       case Type::kInt:
130         int_ = 0;
131         break;
132       case Type::kLong:
133         long_ = 0;
134         break;
135       case Type::kDouble:
136         double_ = 0.0;
137         break;
138       case Type::kString:
139         string_ = new std::string();
140         break;
141       case Type::kByteList:
142         byte_list_ = new std::vector<uint8_t>();
143         break;
144       case Type::kIntList:
145         int_list_ = new std::vector<int32_t>();
146         break;
147       case Type::kLongList:
148         long_list_ = new std::vector<int64_t>();
149         break;
150       case Type::kDoubleList:
151         double_list_ = new std::vector<double>();
152         break;
153       case Type::kList:
154         list_ = new std::vector<EncodableValue>();
155         break;
156       case Type::kMap:
157         map_ = new std::map<EncodableValue, EncodableValue>();
158         break;
159     }
160   }
161 
~EncodableValue()162   ~EncodableValue() { DestroyValue(); }
163 
EncodableValue(const EncodableValue & other)164   EncodableValue(const EncodableValue& other) {
165     DestroyValue();
166 
167     type_ = other.type_;
168     switch (type_) {
169       case Type::kNull:
170         break;
171       case Type::kBool:
172         bool_ = other.bool_;
173         break;
174       case Type::kInt:
175         int_ = other.int_;
176         break;
177       case Type::kLong:
178         long_ = other.long_;
179         break;
180       case Type::kDouble:
181         double_ = other.double_;
182         break;
183       case Type::kString:
184         string_ = new std::string(*other.string_);
185         break;
186       case Type::kByteList:
187         byte_list_ = new std::vector<uint8_t>(*other.byte_list_);
188         break;
189       case Type::kIntList:
190         int_list_ = new std::vector<int32_t>(*other.int_list_);
191         break;
192       case Type::kLongList:
193         long_list_ = new std::vector<int64_t>(*other.long_list_);
194         break;
195       case Type::kDoubleList:
196         double_list_ = new std::vector<double>(*other.double_list_);
197         break;
198       case Type::kList:
199         list_ = new std::vector<EncodableValue>(*other.list_);
200         break;
201       case Type::kMap:
202         map_ = new std::map<EncodableValue, EncodableValue>(*other.map_);
203         break;
204     }
205   }
206 
EncodableValue(EncodableValue && other)207   EncodableValue(EncodableValue&& other) { *this = std::move(other); }
208 
209   EncodableValue& operator=(const EncodableValue& other) {
210     if (&other == this) {
211       return *this;
212     }
213     using std::swap;
214     EncodableValue temp(other);
215     swap(*this, temp);
216     return *this;
217   }
218 
219   EncodableValue& operator=(EncodableValue&& other) {
220     if (&other == this) {
221       return *this;
222     }
223     DestroyValue();
224 
225     type_ = other.type_;
226     switch (type_) {
227       case Type::kNull:
228         break;
229       case Type::kBool:
230         bool_ = other.bool_;
231         break;
232       case Type::kInt:
233         int_ = other.int_;
234         break;
235       case Type::kLong:
236         long_ = other.long_;
237         break;
238       case Type::kDouble:
239         double_ = other.double_;
240         break;
241       case Type::kString:
242         string_ = other.string_;
243         break;
244       case Type::kByteList:
245         byte_list_ = other.byte_list_;
246         break;
247       case Type::kIntList:
248         int_list_ = other.int_list_;
249         break;
250       case Type::kLongList:
251         long_list_ = other.long_list_;
252         break;
253       case Type::kDoubleList:
254         double_list_ = other.double_list_;
255         break;
256       case Type::kList:
257         list_ = other.list_;
258         break;
259       case Type::kMap:
260         map_ = other.map_;
261         break;
262     }
263     // Ensure that destruction doesn't run on the source of the move.
264     other.type_ = Type::kNull;
265     return *this;
266   }
267 
268   // Allow assigning any value type that can be used for a constructor.
269   template <typename T>
270   EncodableValue& operator=(const T& value) {
271     *this = EncodableValue(value);
272     return *this;
273   }
274 
275   // This operator exists only to provide a stable ordering for use as a
276   // std::map key. It does not attempt to provide useful ordering semantics.
277   // Notably:
278   // - Numeric values are not guaranteed any ordering across numeric types.
279   //   E.g., 1 as a Long may sort after 100 as an Int.
280   // - Collection types use pointer equality, rather than value. This means that
281   //   multiple collections with the same values will end up as separate keys
282   //   in a map (consistent with default Dart Map behavior).
283   bool operator<(const EncodableValue& other) const {
284     if (type_ != other.type_) {
285       return type_ < other.type_;
286     }
287     switch (type_) {
288       case Type::kNull:
289         return false;
290       case Type::kBool:
291         return bool_ < other.bool_;
292       case Type::kInt:
293         return int_ < other.int_;
294       case Type::kLong:
295         return long_ < other.long_;
296       case Type::kDouble:
297         return double_ < other.double_;
298       case Type::kString:
299         return *string_ < *other.string_;
300       case Type::kByteList:
301       case Type::kIntList:
302       case Type::kLongList:
303       case Type::kDoubleList:
304       case Type::kList:
305       case Type::kMap:
306         return this < &other;
307     }
308     assert(false);
309     return false;
310   }
311 
312   // Returns the bool value this object represents.
313   //
314   // It is a programming error to call this unless IsBool() is true.
BoolValue()315   bool BoolValue() const {
316     assert(IsBool());
317     return bool_;
318   }
319 
320   // Returns the 32-bit integer value this object represents.
321   //
322   // It is a programming error to call this unless IsInt() is true.
IntValue()323   int32_t IntValue() const {
324     assert(IsInt());
325     return int_;
326   }
327 
328   // Returns the 64-bit integer value this object represents.
329   //
330   // It is a programming error to call this unless IsLong() or IsInt() is true.
331   //
332   // Note that calling this function on an Int value is the only case where
333   // a *Value() function can be called without the corresponding Is*() being
334   // true. This is to simplify handling objects received from Flutter where the
335   // values may be larger than 32-bit, since they have the same type on the Dart
336   // side, but will be either 32-bit or 64-bit here depending on the value.
LongValue()337   int64_t LongValue() const {
338     assert(IsLong() || IsInt());
339     if (IsLong()) {
340       return long_;
341     }
342     return int_;
343   }
344 
345   // Returns the double value this object represents.
346   //
347   // It is a programming error to call this unless IsDouble() is true.
DoubleValue()348   double DoubleValue() const {
349     assert(IsDouble());
350     return double_;
351   }
352 
353   // Returns the string value this object represents.
354   //
355   // It is a programming error to call this unless IsString() is true.
StringValue()356   const std::string& StringValue() const {
357     assert(IsString());
358     return *string_;
359   }
360 
361   // Returns the byte list this object represents.
362   //
363   // It is a programming error to call this unless IsByteList() is true.
ByteListValue()364   const std::vector<uint8_t>& ByteListValue() const {
365     assert(IsByteList());
366     return *byte_list_;
367   }
368 
369   // Returns the byte list this object represents.
370   //
371   // It is a programming error to call this unless IsByteList() is true.
ByteListValue()372   std::vector<uint8_t>& ByteListValue() {
373     assert(IsByteList());
374     return *byte_list_;
375   }
376 
377   // Returns the 32-bit integer list this object represents.
378   //
379   // It is a programming error to call this unless IsIntList() is true.
IntListValue()380   const std::vector<int32_t>& IntListValue() const {
381     assert(IsIntList());
382     return *int_list_;
383   }
384 
385   // Returns the 32-bit integer list this object represents.
386   //
387   // It is a programming error to call this unless IsIntList() is true.
IntListValue()388   std::vector<int32_t>& IntListValue() {
389     assert(IsIntList());
390     return *int_list_;
391   }
392 
393   // Returns the 64-bit integer list this object represents.
394   //
395   // It is a programming error to call this unless IsLongList() is true.
LongListValue()396   const std::vector<int64_t>& LongListValue() const {
397     assert(IsLongList());
398     return *long_list_;
399   }
400 
401   // Returns the 64-bit integer list this object represents.
402   //
403   // It is a programming error to call this unless IsLongList() is true.
LongListValue()404   std::vector<int64_t>& LongListValue() {
405     assert(IsLongList());
406     return *long_list_;
407   }
408 
409   // Returns the double list this object represents.
410   //
411   // It is a programming error to call this unless IsDoubleList() is true.
DoubleListValue()412   const std::vector<double>& DoubleListValue() const {
413     assert(IsDoubleList());
414     return *double_list_;
415   }
416 
417   // Returns the double list this object represents.
418   //
419   // It is a programming error to call this unless IsDoubleList() is true.
DoubleListValue()420   std::vector<double>& DoubleListValue() {
421     assert(IsDoubleList());
422     return *double_list_;
423   }
424 
425   // Returns the list of EncodableValues this object represents.
426   //
427   // It is a programming error to call this unless IsList() is true.
ListValue()428   const EncodableList& ListValue() const {
429     assert(IsList());
430     return *list_;
431   }
432 
433   // Returns the list of EncodableValues this object represents.
434   //
435   // It is a programming error to call this unless IsList() is true.
ListValue()436   EncodableList& ListValue() {
437     assert(IsList());
438     return *list_;
439   }
440 
441   // Returns the map of EncodableValue : EncodableValue pairs this object
442   // represent.
443   //
444   // It is a programming error to call this unless IsMap() is true.
MapValue()445   const EncodableMap& MapValue() const {
446     assert(IsMap());
447     return *map_;
448   }
449 
450   // Returns the map of EncodableValue : EncodableValue pairs this object
451   // represent.
452   //
453   // It is a programming error to call this unless IsMap() is true.
MapValue()454   EncodableMap& MapValue() {
455     assert(IsMap());
456     return *map_;
457   }
458 
459   // Returns true if this represents a null value.
IsNull()460   bool IsNull() const { return type_ == Type::kNull; }
461 
462   // Returns true if this represents a bool value.
IsBool()463   bool IsBool() const { return type_ == Type::kBool; }
464 
465   // Returns true if this represents a 32-bit integer value.
IsInt()466   bool IsInt() const { return type_ == Type::kInt; }
467 
468   // Returns true if this represents a 64-bit integer value.
IsLong()469   bool IsLong() const { return type_ == Type::kLong; }
470 
471   // Returns true if this represents a double value.
IsDouble()472   bool IsDouble() const { return type_ == Type::kDouble; }
473 
474   // Returns true if this represents a string value.
IsString()475   bool IsString() const { return type_ == Type::kString; }
476 
477   // Returns true if this represents a list of bytes.
IsByteList()478   bool IsByteList() const { return type_ == Type::kByteList; }
479 
480   // Returns true if this represents a list of 32-bit integers.
IsIntList()481   bool IsIntList() const { return type_ == Type::kIntList; }
482 
483   // Returns true if this represents a list of 64-bit integers.
IsLongList()484   bool IsLongList() const { return type_ == Type::kLongList; }
485 
486   // Returns true if this represents a list of doubles.
IsDoubleList()487   bool IsDoubleList() const { return type_ == Type::kDoubleList; }
488 
489   // Returns true if this represents a list of EncodableValues.
IsList()490   bool IsList() const { return type_ == Type::kList; }
491 
492   // Returns true if this represents a map of EncodableValue : EncodableValue
493   // pairs.
IsMap()494   bool IsMap() const { return type_ == Type::kMap; }
495 
496   // Returns the type this value represents.
497   //
498   // This is primarily intended for use with switch(); for individual checks,
499   // prefer an Is*() call.
type()500   Type type() const { return type_; }
501 
502  private:
503   // Performs any cleanup necessary for the active union value. This must be
504   // called before assigning a new value, and on object destruction.
505   //
506   // After calling this, type_ will alway be kNull.
DestroyValue()507   void DestroyValue() {
508     switch (type_) {
509       case Type::kNull:
510       case Type::kBool:
511       case Type::kInt:
512       case Type::kLong:
513       case Type::kDouble:
514         break;
515       case Type::kString:
516         delete string_;
517         break;
518       case Type::kByteList:
519         delete byte_list_;
520         break;
521       case Type::kIntList:
522         delete int_list_;
523         break;
524       case Type::kLongList:
525         delete long_list_;
526         break;
527       case Type::kDoubleList:
528         delete double_list_;
529         break;
530       case Type::kList:
531         delete list_;
532         break;
533       case Type::kMap:
534         delete map_;
535         break;
536     }
537 
538     type_ = Type::kNull;
539   }
540 
541   // The anonymous union that stores the represented value. Accessing any of
542   // these entries other than the one that corresponds to the current value of
543   // |type_| has undefined behavior.
544   //
545   // Pointers are used for the non-POD types to avoid making the overall size
546   // of the union unnecessarily large.
547   //
548   // TODO: Replace this with std::variant once c++17 is available.
549   union {
550     bool bool_;
551     int32_t int_;
552     int64_t long_;
553     double double_;
554     std::string* string_;
555     std::vector<uint8_t>* byte_list_;
556     std::vector<int32_t>* int_list_;
557     std::vector<int64_t>* long_list_;
558     std::vector<double>* double_list_;
559     std::vector<EncodableValue>* list_;
560     std::map<EncodableValue, EncodableValue>* map_;
561   };
562 
563   // The currently active union entry.
564   Type type_ = Type::kNull;
565 };
566 
567 }  // namespace flutter
568 
569 #endif  // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
570