• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
DecodePointer(const uint64_t * offset)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 
SetPointer102   void Set(T* ptr) { EncodePointer(ptr, &offset); }
GetPointer103   const T* Get() const { return static_cast<const T*>(DecodePointer(&offset)); }
GetPointer104   T* Get() {
105     return static_cast<T*>(const_cast<void*>(DecodePointer(&offset)));
106   }
107 
is_nullPointer108   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;
Handle_DataHandle_Data116   explicit Handle_Data(uint32_t value) : value(value) {}
117 
is_validHandle_Data118   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>
FetchAndReset(T * ptr)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