Home | History | Annotate | Download | only in lib
      1 // Copyright 2013 The Chromium 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
      6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include <functional>
     11 
     12 #include "base/template_util.h"
     13 #include "mojo/public/cpp/bindings/interface_id.h"
     14 #include "mojo/public/cpp/bindings/lib/template_util.h"
     15 #include "mojo/public/cpp/system/core.h"
     16 
     17 namespace mojo {
     18 
     19 template <typename T>
     20 class Array;
     21 
     22 template <typename T>
     23 class AssociatedInterfacePtrInfo;
     24 
     25 template <typename T>
     26 class AssociatedInterfaceRequest;
     27 
     28 template <typename T>
     29 class InterfacePtr;
     30 
     31 template <typename T>
     32 class InterfaceRequest;
     33 
     34 template <typename K, typename V>
     35 class Map;
     36 
     37 class String;
     38 
     39 template <typename T>
     40 class StructPtr;
     41 
     42 template <typename T>
     43 class InlinedStructPtr;
     44 
     45 namespace internal {
     46 
     47 // Please note that this is a different value than |mojo::kInvalidHandleValue|,
     48 // which is the "decoded" invalid handle.
     49 const uint32_t kEncodedInvalidHandleValue = static_cast<uint32_t>(-1);
     50 
     51 // A serialized union always takes 16 bytes:
     52 //   4-byte size + 4-byte tag + 8-byte payload.
     53 const uint32_t kUnionDataSize = 16;
     54 
     55 template <typename T>
     56 class Array_Data;
     57 
     58 template <typename K, typename V>
     59 class Map_Data;
     60 
     61 using String_Data = Array_Data<char>;
     62 
     63 size_t Align(size_t size);
     64 char* AlignPointer(char* ptr);
     65 
     66 bool IsAligned(const void* ptr);
     67 
     68 // Pointers are encoded as relative offsets. The offsets are relative to the
     69 // address of where the offset value is stored, such that the pointer may be
     70 // recovered with the expression:
     71 //
     72 //   ptr = reinterpret_cast<char*>(offset) + *offset
     73 //
     74 // A null pointer is encoded as an offset value of 0.
     75 //
     76 void EncodePointer(const void* ptr, uint64_t* offset);
     77 // Note: This function doesn't validate the encoded pointer value.
     78 inline const void* DecodePointer(const uint64_t* offset) {
     79   if (!*offset)
     80     return nullptr;
     81   return reinterpret_cast<const char*>(offset) + *offset;
     82 }
     83 
     84 #pragma pack(push, 1)
     85 
     86 struct StructHeader {
     87   uint32_t num_bytes;
     88   uint32_t version;
     89 };
     90 static_assert(sizeof(StructHeader) == 8, "Bad sizeof(StructHeader)");
     91 
     92 struct ArrayHeader {
     93   uint32_t num_bytes;
     94   uint32_t num_elements;
     95 };
     96 static_assert(sizeof(ArrayHeader) == 8, "Bad_sizeof(ArrayHeader)");
     97 
     98 template <typename T>
     99 struct Pointer {
    100   using BaseType = T;
    101 
    102   void Set(T* ptr) { EncodePointer(ptr, &offset); }
    103   const T* Get() const { return static_cast<const T*>(DecodePointer(&offset)); }
    104   T* Get() {
    105     return static_cast<T*>(const_cast<void*>(DecodePointer(&offset)));
    106   }
    107 
    108   bool is_null() const { return offset == 0; }
    109 
    110   uint64_t offset;
    111 };
    112 static_assert(sizeof(Pointer<char>) == 8, "Bad_sizeof(Pointer)");
    113 
    114 struct Handle_Data {
    115   Handle_Data() = default;
    116   explicit Handle_Data(uint32_t value) : value(value) {}
    117 
    118   bool is_valid() const { return value != kEncodedInvalidHandleValue; }
    119 
    120   uint32_t value;
    121 };
    122 static_assert(sizeof(Handle_Data) == 4, "Bad_sizeof(Handle_Data)");
    123 
    124 struct Interface_Data {
    125   Handle_Data handle;
    126   uint32_t version;
    127 };
    128 static_assert(sizeof(Interface_Data) == 8, "Bad_sizeof(Interface_Data)");
    129 
    130 struct AssociatedInterface_Data {
    131   InterfaceId interface_id;
    132   uint32_t version;
    133 };
    134 static_assert(sizeof(AssociatedInterface_Data) == 8,
    135               "Bad_sizeof(AssociatedInterface_Data)");
    136 
    137 struct AssociatedInterfaceRequest_Data {
    138   InterfaceId interface_id;
    139 };
    140 static_assert(sizeof(AssociatedInterfaceRequest_Data) == 4,
    141               "Bad_sizeof(AssociatedInterfaceRequest_Data)");
    142 
    143 #pragma pack(pop)
    144 
    145 template <typename T>
    146 T FetchAndReset(T* ptr) {
    147   T temp = *ptr;
    148   *ptr = T();
    149   return temp;
    150 }
    151 
    152 template <typename T>
    153 struct IsUnionDataType {
    154  private:
    155   template <typename U>
    156   static YesType Test(const typename U::MojomUnionDataType*);
    157 
    158   template <typename U>
    159   static NoType Test(...);
    160 
    161   EnsureTypeIsComplete<T> check_t_;
    162 
    163  public:
    164   static const bool value =
    165       sizeof(Test<T>(0)) == sizeof(YesType) && !IsConst<T>::value;
    166 };
    167 
    168 enum class MojomTypeCategory : uint32_t {
    169   ARRAY = 1 << 0,
    170   ASSOCIATED_INTERFACE = 1 << 1,
    171   ASSOCIATED_INTERFACE_REQUEST = 1 << 2,
    172   BOOLEAN = 1 << 3,
    173   ENUM = 1 << 4,
    174   HANDLE = 1 << 5,
    175   INTERFACE = 1 << 6,
    176   INTERFACE_REQUEST = 1 << 7,
    177   MAP = 1 << 8,
    178   // POD except boolean and enum.
    179   POD = 1 << 9,
    180   STRING = 1 << 10,
    181   STRUCT = 1 << 11,
    182   UNION = 1 << 12
    183 };
    184 
    185 inline constexpr MojomTypeCategory operator&(MojomTypeCategory x,
    186                                              MojomTypeCategory y) {
    187   return static_cast<MojomTypeCategory>(static_cast<uint32_t>(x) &
    188                                         static_cast<uint32_t>(y));
    189 }
    190 
    191 inline constexpr MojomTypeCategory operator|(MojomTypeCategory x,
    192                                              MojomTypeCategory y) {
    193   return static_cast<MojomTypeCategory>(static_cast<uint32_t>(x) |
    194                                         static_cast<uint32_t>(y));
    195 }
    196 
    197 template <typename T, bool is_enum = std::is_enum<T>::value>
    198 struct MojomTypeTraits {
    199   using Data = T;
    200   using DataAsArrayElement = Data;
    201 
    202   static const MojomTypeCategory category = MojomTypeCategory::POD;
    203 };
    204 
    205 template <typename T>
    206 struct MojomTypeTraits<Array<T>, false> {
    207   using Data = Array_Data<typename MojomTypeTraits<T>::DataAsArrayElement>;
    208   using DataAsArrayElement = Pointer<Data>;
    209 
    210   static const MojomTypeCategory category = MojomTypeCategory::ARRAY;
    211 };
    212 
    213 template <typename T>
    214 struct MojomTypeTraits<AssociatedInterfacePtrInfo<T>, false> {
    215   using Data = AssociatedInterface_Data;
    216   using DataAsArrayElement = Data;
    217 
    218   static const MojomTypeCategory category =
    219       MojomTypeCategory::ASSOCIATED_INTERFACE;
    220 };
    221 
    222 template <typename T>
    223 struct MojomTypeTraits<AssociatedInterfaceRequest<T>, false> {
    224   using Data = AssociatedInterfaceRequest_Data;
    225   using DataAsArrayElement = Data;
    226 
    227   static const MojomTypeCategory category =
    228       MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST;
    229 };
    230 
    231 template <>
    232 struct MojomTypeTraits<bool, false> {
    233   using Data = bool;
    234   using DataAsArrayElement = Data;
    235 
    236   static const MojomTypeCategory category = MojomTypeCategory::BOOLEAN;
    237 };
    238 
    239 template <typename T>
    240 struct MojomTypeTraits<T, true> {
    241   using Data = int32_t;
    242   using DataAsArrayElement = Data;
    243 
    244   static const MojomTypeCategory category = MojomTypeCategory::ENUM;
    245 };
    246 
    247 template <typename T>
    248 struct MojomTypeTraits<ScopedHandleBase<T>, false> {
    249   using Data = Handle_Data;
    250   using DataAsArrayElement = Data;
    251 
    252   static const MojomTypeCategory category = MojomTypeCategory::HANDLE;
    253 };
    254 
    255 template <typename T>
    256 struct MojomTypeTraits<InterfacePtr<T>, false> {
    257   using Data = Interface_Data;
    258   using DataAsArrayElement = Data;
    259 
    260   static const MojomTypeCategory category = MojomTypeCategory::INTERFACE;
    261 };
    262 
    263 template <typename T>
    264 struct MojomTypeTraits<InterfaceRequest<T>, false> {
    265   using Data = Handle_Data;
    266   using DataAsArrayElement = Data;
    267 
    268   static const MojomTypeCategory category =
    269       MojomTypeCategory::INTERFACE_REQUEST;
    270 };
    271 
    272 template <typename K, typename V>
    273 struct MojomTypeTraits<Map<K, V>, false> {
    274   using Data = Map_Data<typename MojomTypeTraits<K>::DataAsArrayElement,
    275                         typename MojomTypeTraits<V>::DataAsArrayElement>;
    276   using DataAsArrayElement = Pointer<Data>;
    277 
    278   static const MojomTypeCategory category = MojomTypeCategory::MAP;
    279 };
    280 
    281 template <>
    282 struct MojomTypeTraits<String, false> {
    283   using Data = String_Data;
    284   using DataAsArrayElement = Pointer<Data>;
    285 
    286   static const MojomTypeCategory category = MojomTypeCategory::STRING;
    287 };
    288 
    289 template <typename T>
    290 struct MojomTypeTraits<StructPtr<T>, false> {
    291   using Data = typename T::Data_;
    292   using DataAsArrayElement =
    293       typename std::conditional<IsUnionDataType<Data>::value,
    294                                 Data,
    295                                 Pointer<Data>>::type;
    296 
    297   static const MojomTypeCategory category = IsUnionDataType<Data>::value
    298                                                 ? MojomTypeCategory::UNION
    299                                                 : MojomTypeCategory::STRUCT;
    300 };
    301 
    302 template <typename T>
    303 struct MojomTypeTraits<InlinedStructPtr<T>, false> {
    304   using Data = typename T::Data_;
    305   using DataAsArrayElement =
    306       typename std::conditional<IsUnionDataType<Data>::value,
    307                                 Data,
    308                                 Pointer<Data>>::type;
    309 
    310   static const MojomTypeCategory category = IsUnionDataType<Data>::value
    311                                                 ? MojomTypeCategory::UNION
    312                                                 : MojomTypeCategory::STRUCT;
    313 };
    314 
    315 template <typename T, MojomTypeCategory categories>
    316 struct BelongsTo {
    317   static const bool value =
    318       static_cast<uint32_t>(MojomTypeTraits<T>::category & categories) != 0;
    319 };
    320 
    321 template <typename T>
    322 struct EnumHashImpl {
    323   static_assert(std::is_enum<T>::value, "Incorrect hash function.");
    324 
    325   size_t operator()(T input) const {
    326     using UnderlyingType = typename base::underlying_type<T>::type;
    327     return std::hash<UnderlyingType>()(static_cast<UnderlyingType>(input));
    328   }
    329 };
    330 
    331 }  // namespace internal
    332 }  // namespace mojo
    333 
    334 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
    335