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