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