• 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 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 
Align(size_t size)61 inline size_t Align(size_t size) {
62   return (size + 7) & ~0x7;
63 }
64 
IsAligned(const void * ptr)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 //
EncodePointer(const void * ptr,uint64_t * offset)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.
DecodePointer(const uint64_t * offset)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 
SetPointer115   void Set(T* ptr) { EncodePointer(ptr, &offset); }
GetPointer116   const T* Get() const { return static_cast<const T*>(DecodePointer(&offset)); }
GetPointer117   T* Get() {
118     return static_cast<T*>(const_cast<void*>(DecodePointer(&offset)));
119   }
120 
is_nullPointer121   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;
Handle_DataHandle_Data131   explicit Handle_Data(uint32_t value) : value(value) {}
132 
is_validHandle_Data133   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;
AssociatedEndpointHandle_DataAssociatedEndpointHandle_Data147   explicit AssociatedEndpointHandle_Data(uint32_t value) : value(value) {}
148 
is_validAssociatedEndpointHandle_Data149   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>
FetchAndReset(T * ptr)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