OLD | NEW |
| (Empty) |
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 <type_traits> | |
9 | |
10 #include "mojo/public/cpp/bindings/lib/template_util.h" | |
11 #include "mojo/public/cpp/bindings/struct_ptr.h" | |
12 #include "mojo/public/cpp/system/handle.h" | |
13 #include "mojo/public/cpp/system/message_pipe.h" | |
14 | |
15 namespace mojo { | |
16 class String; | |
17 | |
18 template <typename T> | |
19 class Array; | |
20 | |
21 template <typename Interface> | |
22 class InterfaceHandle; | |
23 | |
24 template <typename Interface> | |
25 class InterfaceRequest; | |
26 | |
27 template <typename K, typename V> | |
28 class Map; | |
29 | |
30 namespace internal { | |
31 template <typename T> | |
32 class Array_Data; | |
33 | |
34 #pragma pack(push, 1) | |
35 | |
36 struct StructHeader { | |
37 uint32_t num_bytes; | |
38 uint32_t version; | |
39 }; | |
40 static_assert(sizeof(StructHeader) == 8, "Bad sizeof(StructHeader)"); | |
41 | |
42 struct ArrayHeader { | |
43 uint32_t num_bytes; | |
44 uint32_t num_elements; | |
45 }; | |
46 static_assert(sizeof(ArrayHeader) == 8, "Bad_sizeof(ArrayHeader)"); | |
47 | |
48 template <typename T> | |
49 union StructPointer { | |
50 uint64_t offset; | |
51 T* ptr; | |
52 }; | |
53 static_assert(sizeof(StructPointer<char>) == 8, "Bad_sizeof(StructPointer)"); | |
54 | |
55 template <typename T> | |
56 union ArrayPointer { | |
57 uint64_t offset; | |
58 Array_Data<T>* ptr; | |
59 }; | |
60 static_assert(sizeof(ArrayPointer<char>) == 8, "Bad_sizeof(ArrayPointer)"); | |
61 | |
62 union StringPointer { | |
63 uint64_t offset; | |
64 Array_Data<char>* ptr; | |
65 }; | |
66 static_assert(sizeof(StringPointer) == 8, "Bad_sizeof(StringPointer)"); | |
67 | |
68 struct Interface_Data { | |
69 MessagePipeHandle handle; | |
70 uint32_t version; | |
71 }; | |
72 static_assert(sizeof(Interface_Data) == 8, "Bad_sizeof(Interface_Data)"); | |
73 | |
74 template <typename T> | |
75 union UnionPointer { | |
76 uint64_t offset; | |
77 T* ptr; | |
78 }; | |
79 static_assert(sizeof(UnionPointer<char>) == 8, "Bad_sizeof(UnionPointer)"); | |
80 | |
81 #pragma pack(pop) | |
82 | |
83 template <typename T> | |
84 void ResetIfNonNull(T* ptr) { | |
85 if (ptr) | |
86 *ptr = T(); | |
87 } | |
88 | |
89 template <typename T> | |
90 T FetchAndReset(T* ptr) { | |
91 T temp = *ptr; | |
92 *ptr = T(); | |
93 return temp; | |
94 } | |
95 | |
96 template <typename H> | |
97 struct IsHandle { | |
98 enum { value = std::is_base_of<Handle, H>::value }; | |
99 }; | |
100 | |
101 // TODO(vardhan): Replace RemoveStructPtr<> and UnwrapStructPtr<> with | |
102 // specializations of std::pointer_traits<> on [Inlined]StructPtr<>. | |
103 template <typename T> | |
104 struct RemoveStructPtr { | |
105 typedef T type; | |
106 }; | |
107 | |
108 template <typename T> | |
109 struct RemoveStructPtr<StructPtr<T>> { | |
110 typedef T type; | |
111 }; | |
112 | |
113 template <typename T> | |
114 struct RemoveStructPtr<InlinedStructPtr<T>> { | |
115 typedef T type; | |
116 }; | |
117 | |
118 template <typename T> | |
119 struct UnwrapStructPtr { | |
120 static T* value(T& x) { return &x; } | |
121 }; | |
122 | |
123 template <typename T> | |
124 struct UnwrapStructPtr<StructPtr<T>> { | |
125 static T* value(StructPtr<T>& x) { return x.get(); } | |
126 }; | |
127 | |
128 template <typename T> | |
129 struct UnwrapStructPtr<InlinedStructPtr<T>> { | |
130 static T* value(InlinedStructPtr<T>& x) { return x.get(); } | |
131 }; | |
132 | |
133 template <typename T> | |
134 struct UnwrapConstStructPtr { | |
135 static const T* value(const T& x) { return &x; } | |
136 }; | |
137 | |
138 template <typename T> | |
139 struct UnwrapConstStructPtr<StructPtr<T>> { | |
140 static const T* value(const StructPtr<T>& x) { return x.get(); } | |
141 }; | |
142 | |
143 template <typename T> | |
144 struct UnwrapConstStructPtr<InlinedStructPtr<T>> { | |
145 static const T* value(const InlinedStructPtr<T>& x) { return x.get(); } | |
146 }; | |
147 | |
148 template <typename T> | |
149 struct IsStructPtr { | |
150 static bool const value = IsSpecializationOf<StructPtr, T>::value || | |
151 IsSpecializationOf<InlinedStructPtr, T>::value; | |
152 }; | |
153 | |
154 template <typename T> | |
155 struct IsUnionWrapperType { | |
156 template <typename U> | |
157 static YesType Test(const typename U::Data_::MojomUnionDataType*); | |
158 | |
159 template <typename U> | |
160 static NoType Test(...); | |
161 | |
162 static const bool value = | |
163 sizeof(Test<T>(0)) == sizeof(YesType) && !std::is_const<T>::value; | |
164 }; | |
165 | |
166 template <typename T> | |
167 struct IsUnionDataType { | |
168 template <typename U> | |
169 static YesType Test(const typename U::MojomUnionDataType*); | |
170 | |
171 template <typename U> | |
172 static NoType Test(...); | |
173 | |
174 static const bool value = | |
175 sizeof(Test<T>(0)) == sizeof(YesType) && !std::is_const<T>::value; | |
176 }; | |
177 | |
178 // To introduce a new mojom type, you must define (partial or full) template | |
179 // specializations for the following traits templates, which operate on the C++ | |
180 // wrapper types representing a mojom type: | |
181 // - WrapperTraits: provides a |DataType| typedef which points to the | |
182 // serialized data type. | |
183 // - ValueTraits: provides an |Equals()| method for comparing the two wrapper | |
184 // values of the same type. | |
185 // | |
186 // Currently, full specializations of WrapperTraits are generated for mojo | |
187 // structs in their generated `.mojom.h`. In contrast, WrapperTraits for Unions | |
188 // don't need to be auto-generated because their underlying DataType can be | |
189 // accessed without dependency issues -- a catch-all WrapperTraits for unions is | |
190 // instead defined here. | |
191 // TODO(vardhan): Merge ValueTraits and WrapperTraits into one? | |
192 // TODO(vardhan): Write a doc about all the Traits templates you need to touch | |
193 // when introducing a new mojom type. | |
194 // TODO(vardhan): Instead of providing |move_only| & |is_union| template | |
195 // parameters, provide a default "typename Enable = void" template parameter, | |
196 // and have specializations define their own Enable expressions (similar to how | |
197 // ValueTraits is). | |
198 template <typename T, | |
199 bool move_only = IsMoveOnlyType<T>::value, | |
200 bool is_union = | |
201 IsUnionWrapperType<typename RemoveStructPtr<T>::type>::value> | |
202 struct WrapperTraits; | |
203 | |
204 // Catch-all for all mojom types not specialized below. | |
205 template <typename T> | |
206 struct WrapperTraits<T, false, false> { | |
207 using DataType = T; | |
208 }; | |
209 template <typename H> | |
210 struct WrapperTraits<ScopedHandleBase<H>, true, false> { | |
211 using DataType = H; | |
212 }; | |
213 template <typename I> | |
214 struct WrapperTraits<InterfaceRequest<I>, true, false> { | |
215 using DataType = MessagePipeHandle; | |
216 }; | |
217 template <typename Interface> | |
218 struct WrapperTraits<InterfaceHandle<Interface>, true, false> { | |
219 using DataType = Interface_Data; | |
220 }; | |
221 // Unions. | |
222 template <typename U> | |
223 struct WrapperTraits<StructPtr<U>, true, true> { | |
224 using DataType = typename U::Data_; | |
225 }; | |
226 template <typename U> | |
227 struct WrapperTraits<InlinedStructPtr<U>, true, true> { | |
228 using DataType = typename U::Data_; | |
229 }; | |
230 // Catch-all for other pointer types: arrays, maps. | |
231 template <typename S> | |
232 struct WrapperTraits<S, true, false> { | |
233 using DataType = typename S::Data_*; | |
234 }; | |
235 | |
236 template <typename T, typename Enable = void> | |
237 struct ValueTraits { | |
238 static bool Equals(const T& a, const T& b) { return a == b; } | |
239 }; | |
240 | |
241 template <typename T> | |
242 struct ValueTraits<T, | |
243 typename std::enable_if< | |
244 IsSpecializationOf<Array, T>::value || | |
245 IsSpecializationOf<Map, T>::value || | |
246 IsSpecializationOf<StructPtr, T>::value || | |
247 IsSpecializationOf<InlinedStructPtr, T>::value>::type> { | |
248 static bool Equals(const T& a, const T& b) { return a.Equals(b); } | |
249 }; | |
250 | |
251 template <typename T> | |
252 struct ValueTraits<ScopedHandleBase<T>> { | |
253 static bool Equals(const ScopedHandleBase<T>& a, | |
254 const ScopedHandleBase<T>& b) { | |
255 return (&a == &b) || (!a.is_valid() && !b.is_valid()); | |
256 } | |
257 }; | |
258 | |
259 // |InterfaceHandle|s hold message pipes uniquely, so they can only be equal if | |
260 // they're the same object or are both "invalid". | |
261 template <typename I> | |
262 struct ValueTraits<InterfaceHandle<I>> { | |
263 static bool Equals(const InterfaceHandle<I>& a, const InterfaceHandle<I>& b) { | |
264 return (&a == &b) || (!a.is_valid() && !b.is_valid()); | |
265 } | |
266 }; | |
267 | |
268 // |InterfaceRequest|s hold message pipes uniquely, so they can only be equal if | |
269 // they're the same object or are both "invalid". | |
270 template <typename I> | |
271 struct ValueTraits<InterfaceRequest<I>> { | |
272 static bool Equals(const InterfaceRequest<I>& a, | |
273 const InterfaceRequest<I>& b) { | |
274 return (&a == &b) || (!a.is_pending() && !b.is_pending()); | |
275 } | |
276 }; | |
277 | |
278 } // namespace internal | |
279 } // namespace mojo | |
280 | |
281 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_ | |
OLD | NEW |