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