Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: mojo/public/cpp/bindings/lib/array_serialization.h

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 // TODO(vardhan): Currently, the logic for serializing a mojom type exists in
6 // two places: the C++ code generator template, and here. However, most types
7 // are serialized the same way within Arrays or outside, with the exception of
8 // |bool|. Consider defining serialization/deserialization traits for each
9 // serializable type and call those traits from here. This should help us
10 // remove most of the ArraySerializer<> specializations here.
11
12 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
13 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
14
15 #include <string.h> // For |memcpy()|.
16 #include <type_traits>
17 #include <vector>
18
19 #include "mojo/public/cpp/bindings/lib/array_internal.h"
20 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
21 #include "mojo/public/cpp/bindings/lib/iterator_util.h"
22 #include "mojo/public/cpp/bindings/lib/map_data_internal.h"
23 #include "mojo/public/cpp/bindings/lib/map_serialization_forward.h"
24 #include "mojo/public/cpp/bindings/lib/string_serialization.h"
25 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
26
27 namespace mojo {
28
29 namespace internal {
30
31 // The ArraySerializer template contains static methods for serializing |Array|s
32 // of various types. These methods include:
33 // * size_t GetSerializedSize(..)
34 // Computes the size of the serialized version of the |Array|.
35 // * void SerializeElements(..)
36 // Takes an |Iterator| and a size and serializes it.
37 // * void DeserializeElements(..)
38 // Takes a pointer to an |Array_Data| and deserializes it into a given
39 // |Array|.
40 //
41 // Note: The enable template parameter exists only to allow partial
42 // specializations to disable instantiation using logic based on E and F.
43 // By default, assuming that there are no other substitution failures, the
44 // specialization will instantiate and needs to take no action. A partial
45 // specialization of the form
46 //
47 // template<E, F> struct ArraySerialzer<E, F>
48 //
49 // may be limited to values of E and F with particular properties by supplying
50 // an expression for enable which will cause substitution failure if the
51 // properties of E and F do not satisfy the expression.
52 template <typename E,
53 typename F,
54 bool is_union =
55 IsUnionDataType<typename std::remove_pointer<F>::type>::value,
56 typename enable = void>
57 struct ArraySerializer;
58
59 // Handles serialization and deserialization of arrays of pod types.
60 template <typename E, typename F>
61 struct ArraySerializer<
62 E,
63 F,
64 false,
65 typename std::enable_if<std::is_convertible<E, F>::value ||
66 (std::is_enum<E>::value &&
67 std::is_same<F, int32_t>::value),
68 void>::type> {
69 static_assert(sizeof(E) == sizeof(F), "Incorrect array serializer");
70 static size_t GetSerializedSize(const Array<E>& input) {
71 return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E));
72 }
73
74 template <typename Iterator>
75 static ValidationError SerializeElements(
76 Iterator it,
77 size_t num_elements,
78 Buffer* buf,
79 Array_Data<F>* output,
80 const ArrayValidateParams* validate_params) {
81 MOJO_DCHECK(!validate_params->element_is_nullable)
82 << "Primitive type should be non-nullable";
83 MOJO_DCHECK(!validate_params->element_validate_params)
84 << "Primitive type should not have array validate params";
85 for (size_t i = 0; i < num_elements; ++i, ++it)
86 output->at(i) = static_cast<F>(*it);
87
88 return ValidationError::NONE;
89 }
90
91 // We can optimize serializing PODs by |memcpy|ing directly.
92 // Note that this has precedence over its templated sibling defined above.
93 static ValidationError SerializeElements(
94 typename Array<E>::Iterator it,
95 size_t num_elements,
96 Buffer* buf,
97 Array_Data<F>* output,
98 const ArrayValidateParams* validate_params) {
99 MOJO_DCHECK(!validate_params->element_is_nullable)
100 << "Primitive type should be non-nullable";
101 MOJO_DCHECK(!validate_params->element_validate_params)
102 << "Primitive type should not have array validate params";
103 if (num_elements)
104 memcpy(output->storage(), &(*it), num_elements * sizeof(E));
105
106 return ValidationError::NONE;
107 }
108
109 static void DeserializeElements(Array_Data<F>* input, Array<E>* output) {
110 std::vector<E> result(input->size());
111 if (input->size())
112 memcpy(&result[0], input->storage(), input->size() * sizeof(E));
113 output->Swap(&result);
114 }
115 };
116
117 // Serializes and deserializes arrays of bools.
118 template <>
119 struct ArraySerializer<bool, bool, false> {
120 static size_t GetSerializedSize(const Array<bool>& input) {
121 return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8);
122 }
123
124 template <typename Iterator>
125 static ValidationError SerializeElements(
126 Iterator it,
127 size_t num_elements,
128 Buffer* buf,
129 Array_Data<bool>* output,
130 const ArrayValidateParams* validate_params) {
131 MOJO_DCHECK(!validate_params->element_is_nullable)
132 << "Primitive type should be non-nullable";
133 MOJO_DCHECK(!validate_params->element_validate_params)
134 << "Primitive type should not have array validate params";
135
136 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
137 for (size_t i = 0; i < num_elements; ++i, ++it)
138 output->at(i) = *it;
139
140 return ValidationError::NONE;
141 }
142
143 static void DeserializeElements(Array_Data<bool>* input,
144 Array<bool>* output) {
145 auto result = Array<bool>::New(input->size());
146 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
147 for (size_t i = 0; i < input->size(); ++i)
148 result.at(i) = input->at(i);
149 output->Swap(&result);
150 }
151 };
152
153 // Serializes and deserializes arrays of handles.
154 template <typename H>
155 struct ArraySerializer<ScopedHandleBase<H>, H, false> {
156 static size_t GetSerializedSize(const Array<ScopedHandleBase<H>>& input) {
157 return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H));
158 }
159
160 template <typename Iterator>
161 static ValidationError SerializeElements(
162 Iterator it,
163 size_t num_elements,
164 Buffer* buf,
165 Array_Data<H>* output,
166 const ArrayValidateParams* validate_params) {
167 MOJO_DCHECK(!validate_params->element_validate_params)
168 << "Handle type should not have array validate params";
169
170 for (size_t i = 0; i < num_elements; ++i, ++it) {
171 // Transfer ownership of the handle.
172 output->at(i) = it->release();
173 if (!validate_params->element_is_nullable && !output->at(i).is_valid()) {
174 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
175 ValidationError::UNEXPECTED_INVALID_HANDLE,
176 MakeMessageWithArrayIndex(
177 "invalid handle in array expecting valid handles", num_elements,
178 i));
179 return ValidationError::UNEXPECTED_INVALID_HANDLE;
180 }
181 }
182
183 return ValidationError::NONE;
184 }
185
186 static void DeserializeElements(Array_Data<H>* input,
187 Array<ScopedHandleBase<H>>* output) {
188 auto result = Array<ScopedHandleBase<H>>::New(input->size());
189 for (size_t i = 0; i < input->size(); ++i)
190 result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i)));
191 output->Swap(&result);
192 }
193 };
194
195 // Serializes and deserializes arrays of interface requests.
196 template <typename I>
197 struct ArraySerializer<InterfaceRequest<I>, MessagePipeHandle, false> {
198 static size_t GetSerializedSize(const Array<InterfaceRequest<I>>& input) {
199 return sizeof(Array_Data<MessagePipeHandle>) +
200 Align(input.size() * sizeof(MessagePipeHandle));
201 }
202
203 template <typename Iterator>
204 static ValidationError SerializeElements(
205 Iterator it,
206 size_t num_elements,
207 Buffer* buf,
208 Array_Data<MessagePipeHandle>* output,
209 const ArrayValidateParams* validate_params) {
210 MOJO_DCHECK(!validate_params->element_validate_params)
211 << "Handle type should not have array validate params";
212
213 for (size_t i = 0; i < num_elements; ++i, ++it) {
214 // Transfer ownership of the MessagePipeHandle.
215 output->at(i) = it->PassMessagePipe().release();
216 if (!validate_params->element_is_nullable && !output->at(i).is_valid()) {
217 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
218 ValidationError::UNEXPECTED_INVALID_HANDLE,
219 MakeMessageWithArrayIndex(
220 "invalid message pipe handle in array expecting valid handles",
221 num_elements, i));
222 return ValidationError::UNEXPECTED_INVALID_HANDLE;
223 }
224 }
225
226 return ValidationError::NONE;
227 }
228
229 static void DeserializeElements(Array_Data<MessagePipeHandle>* input,
230 Array<InterfaceRequest<I>>* output) {
231 auto result = Array<InterfaceRequest<I>>::New(input->size());
232 for (size_t i = 0; i < input->size(); ++i)
233 result.at(i) =
234 InterfaceRequest<I>(MakeScopedHandle(FetchAndReset(&input->at(i))))
235 .Pass();
236 output->Swap(&result);
237 }
238 };
239
240 // Serializes and deserializes arrays of interfaces (interface handles).
241 template <typename Interface>
242 struct ArraySerializer<InterfaceHandle<Interface>, Interface_Data, false> {
243 static size_t GetSerializedSize(
244 const Array<InterfaceHandle<Interface>>& input) {
245 return sizeof(Array_Data<Interface_Data>) +
246 Align(input.size() * sizeof(Interface_Data));
247 }
248
249 template <typename Iterator>
250 static ValidationError SerializeElements(
251 Iterator it,
252 size_t num_elements,
253 Buffer* buf,
254 Array_Data<Interface_Data>* output,
255 const ArrayValidateParams* validate_params) {
256 MOJO_DCHECK(!validate_params->element_validate_params)
257 << "Interface type should not have array validate params";
258
259 for (size_t i = 0; i < num_elements; ++i, ++it) {
260 // Transfer ownership of the handle.
261 internal::InterfaceHandleToData(it->Pass(), &output->at(i));
262 if (!validate_params->element_is_nullable &&
263 !output->at(i).handle.is_valid()) {
264 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
265 ValidationError::UNEXPECTED_INVALID_HANDLE,
266 MakeMessageWithArrayIndex(
267 "invalid handle in array expecting valid handles", num_elements,
268 i));
269 return ValidationError::UNEXPECTED_INVALID_HANDLE;
270 }
271 }
272
273 return ValidationError::NONE;
274 }
275
276 static void DeserializeElements(Array_Data<Interface_Data>* input,
277 Array<InterfaceHandle<Interface>>* output) {
278 auto result = Array<InterfaceHandle<Interface>>::New(input->size());
279 for (size_t i = 0; i < input->size(); ++i)
280 internal::InterfaceDataToHandle(&input->at(i), &result.at(i));
281 output->Swap(&result);
282 }
283 };
284
285 // This template must only apply to pointer mojo entity (structs, arrays,
286 // strings). This is done by ensuring that WrapperTraits<S>::DataType is a
287 // pointer.
288 template <typename S>
289 struct ArraySerializer<
290 S,
291 typename std::enable_if<
292 std::is_pointer<typename WrapperTraits<S>::DataType>::value,
293 typename WrapperTraits<S>::DataType>::type,
294 false> {
295 typedef
296 typename std::remove_pointer<typename WrapperTraits<S>::DataType>::type
297 S_Data;
298 static size_t GetSerializedSize(const Array<S>& input) {
299 size_t size = sizeof(Array_Data<S_Data*>) +
300 input.size() * sizeof(StructPointer<S_Data>);
301 for (size_t i = 0; i < input.size(); ++i) {
302 if (!input[i].is_null())
303 size += GetSerializedSize_(*(UnwrapConstStructPtr<S>::value(input[i])));
304 }
305 return size;
306 }
307
308 template <typename Iterator>
309 static ValidationError SerializeElements(
310 Iterator it,
311 size_t num_elements,
312 Buffer* buf,
313 Array_Data<S_Data*>* output,
314 const ArrayValidateParams* validate_params) {
315 for (size_t i = 0; i < num_elements; ++i, ++it) {
316 S_Data* element;
317 auto retval = SerializeCaller::Run(
318 &(*it), buf, &element, validate_params->element_validate_params);
319 if (retval != ValidationError::NONE)
320 return retval;
321
322 output->at(i) = element;
323 if (!validate_params->element_is_nullable && !element) {
324 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
325 ValidationError::UNEXPECTED_NULL_POINTER,
326 MakeMessageWithArrayIndex("null in array expecting valid pointers",
327 num_elements, i));
328 return ValidationError::UNEXPECTED_NULL_POINTER;
329 }
330 }
331
332 return ValidationError::NONE;
333 }
334
335 static void DeserializeElements(Array_Data<S_Data*>* input,
336 Array<S>* output) {
337 auto result = Array<S>::New(input->size());
338 for (size_t i = 0; i < input->size(); ++i) {
339 DeserializeCaller::Run(input->at(i), &result[i]);
340 }
341 output->Swap(&result);
342 }
343
344 private:
345 // SerializeCaller template is used by |ArraySerializer| to dispatch a
346 // serialize call on a non-POD type. This template is defined outside
347 // |ArraySerializer| since you cannot specialize a struct within a class
348 // definition.
349 struct SerializeCaller {
350 // This template needs to be suppressed if |T| is |String|, otherwise it
351 // takes precedence over the |String|-overloaded Run() below.
352 template <
353 typename T,
354 typename =
355 typename std::enable_if<!std::is_same<T, String>::value, T>::type>
356 static ValidationError Run(T* input,
357 Buffer* buf,
358 typename WrapperTraits<T>::DataType* output,
359 const ArrayValidateParams* validate_params) {
360 MOJO_DCHECK(!validate_params)
361 << "Struct type should not have array validate params";
362 return Serialize_(UnwrapStructPtr<T>::value(*input), buf, output);
363 }
364
365 static ValidationError Run(const String* input,
366 Buffer* buf,
367 String_Data** output,
368 const ArrayValidateParams* validate_params) {
369 MOJO_DCHECK(validate_params &&
370 !validate_params->element_validate_params &&
371 !validate_params->element_is_nullable &&
372 validate_params->expected_num_elements == 0)
373 << "String type has unexpected array validate params";
374 SerializeString_(*input, buf, output);
375 return ValidationError::NONE;
376 }
377
378 template <typename T>
379 static ValidationError Run(Array<T>* input,
380 Buffer* buf,
381 typename Array<T>::Data_** output,
382 const ArrayValidateParams* validate_params) {
383 return SerializeArray_(input, buf, output, validate_params);
384 }
385
386 template <typename Key, typename Value>
387 static ValidationError Run(Map<Key, Value>* input,
388 Buffer* buf,
389 typename Map<Key, Value>::Data_** output,
390 const ArrayValidateParams* validate_params) {
391 return SerializeMap_(input, buf, output, validate_params);
392 }
393 };
394
395 struct DeserializeCaller {
396 template <typename T>
397 static void Run(typename WrapperTraits<T>::DataType input, T* output) {
398 Deserialize_(input, output);
399 }
400
401 // Since Deserialize_ takes in a |Struct*| (not |StructPtr|), we need to
402 // initialize the |StructPtr| here before deserializing into its underlying
403 // data.
404 // TODO(vardhan): Either all containers, or just Deserialize_(), should
405 // support taking in an allocator.
406 template <typename T>
407 static void Run(typename WrapperTraits<StructPtr<T>>::DataType input,
408 StructPtr<T>* output) {
409 if (input) {
410 *output = T::New();
411 Deserialize_(input, output->get());
412 }
413 }
414
415 template <typename T>
416 static void Run(typename WrapperTraits<InlinedStructPtr<T>>::DataType input,
417 InlinedStructPtr<T>* output) {
418 if (input) {
419 *output = T::New();
420 Deserialize_(input, output->get());
421 }
422 }
423 };
424 };
425
426 // Handles serialization and deserialization of arrays of unions.
427 template <typename U, typename U_Data>
428 struct ArraySerializer<U, U_Data, true> {
429 static size_t GetSerializedSize(const Array<U>& input) {
430 size_t size = sizeof(Array_Data<U_Data>);
431 for (size_t i = 0; i < input.size(); ++i) {
432 // GetSerializedSize_ will account for both the data in the union and the
433 // space in the array used to hold the union.
434 size += GetSerializedSize_(input[i]);
435 }
436 return size;
437 }
438
439 template <typename Iterator>
440 static ValidationError SerializeElements(
441 Iterator it,
442 size_t num_elements,
443 Buffer* buf,
444 Array_Data<U_Data>* output,
445 const ArrayValidateParams* validate_params) {
446 for (size_t i = 0; i < num_elements; ++i, ++it) {
447 U_Data* result = output->storage() + i;
448 auto retval = SerializeUnion_(it->get(), buf, &result);
449 if (retval != ValidationError::NONE)
450 return retval;
451 if (!validate_params->element_is_nullable && output->at(i).is_null()) {
452 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
453
454 ValidationError::UNEXPECTED_NULL_POINTER,
455 MakeMessageWithArrayIndex("null in array expecting valid unions",
456 num_elements, i));
457 return ValidationError::UNEXPECTED_NULL_POINTER;
458 }
459 }
460
461 return ValidationError::NONE;
462 }
463
464 static void DeserializeElements(Array_Data<U_Data>* input, Array<U>* output) {
465 auto result = Array<U>::New(input->size());
466 for (size_t i = 0; i < input->size(); ++i) {
467 auto& elem = input->at(i);
468 if (!elem.is_null()) {
469 using UnwrapedUnionType = typename RemoveStructPtr<U>::type;
470 result[i] = UnwrapedUnionType::New();
471 Deserialize_(&elem, result[i].get());
472 }
473 }
474 output->Swap(&result);
475 }
476 };
477
478 } // namespace internal
479
480 template <typename E>
481 inline size_t GetSerializedSize_(const Array<E>& input) {
482 if (!input)
483 return 0;
484 using F = typename internal::WrapperTraits<E>::DataType;
485 return internal::ArraySerializer<E, F>::GetSerializedSize(input);
486 }
487
488 // SerializeArray_ will return ValidationError::NONE on success and set
489 // |output| accordingly. On failure, |input| will be partially serialized into
490 // |output| up until an error occurs (which is propagated up and returned by
491 // SerializeArray_), in which case |buf| is also partially consumed.
492 template <typename E, typename F>
493 inline internal::ValidationError SerializeArray_(
494 Array<E>* input,
495 internal::Buffer* buf,
496 internal::Array_Data<F>** output,
497 const internal::ArrayValidateParams* validate_params) {
498 MOJO_DCHECK(input);
499 if (!*input) {
500 // It is up to the caller to make sure the given |Array| is not null if it
501 // is not nullable.
502 *output = nullptr;
503 return internal::ValidationError::NONE;
504 }
505
506 if (validate_params->expected_num_elements != 0 &&
507 input->size() != validate_params->expected_num_elements) {
508 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
509 internal::ValidationError::UNEXPECTED_ARRAY_HEADER,
510 internal::MakeMessageWithExpectedArraySize(
511 "fixed-size array has wrong number of elements", input->size(),
512 validate_params->expected_num_elements));
513 return internal::ValidationError::UNEXPECTED_ARRAY_HEADER;
514 }
515
516 internal::Array_Data<F>* result =
517 internal::Array_Data<F>::New(input->size(), buf);
518 auto retval = internal::ArraySerializer<E, F>::SerializeElements(
519 input->begin(), input->size(), buf, result, validate_params);
520 if (retval != internal::ValidationError::NONE)
521 return retval;
522
523 *output = result;
524 return internal::ValidationError::NONE;
525 }
526
527 template <typename E, typename F>
528 inline void Deserialize_(internal::Array_Data<F>* input, Array<E>* output) {
529 if (input) {
530 internal::ArraySerializer<E, F>::DeserializeElements(input, output);
531 } else {
532 output->reset();
533 }
534 }
535
536 } // namespace mojo
537
538 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/lib/array_internal.cc ('k') | mojo/public/cpp/bindings/lib/bindings_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698