OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ |
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <string.h> // For |memcpy()|. | 9 #include <string.h> // For |memcpy()|. |
10 | 10 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 ? ArraySerializerType::POINTER | 49 ? ArraySerializerType::POINTER |
50 : (IsHandle<DataElement>::value | 50 : (IsHandle<DataElement>::value |
51 ? ArraySerializerType::HANDLE | 51 ? ArraySerializerType::HANDLE |
52 : (std::is_same<Element, bool>::value | 52 : (std::is_same<Element, bool>::value |
53 ? ArraySerializerType::BOOLEAN | 53 ? ArraySerializerType::BOOLEAN |
54 : (std::is_enum<Element>::value | 54 : (std::is_enum<Element>::value |
55 ? ArraySerializerType::ENUM | 55 ? ArraySerializerType::ENUM |
56 : ArraySerializerType::POD)))); | 56 : ArraySerializerType::POD)))); |
57 }; | 57 }; |
58 | 58 |
59 template < | |
60 typename Traits, | |
61 typename MaybeConstUserType, | |
62 typename IteratorType, | |
63 typename std::enable_if< | |
64 HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> | |
65 static decltype(Traits::GetValue(std::declval<IteratorType&>())) GetNextHelper( | |
66 MaybeConstUserType& input, | |
67 IteratorType& iter) { | |
68 auto& value = Traits::GetValue(iter); | |
yzshen1
2016/06/10 16:21:32
Please update the comments in array_traits.h
Fady Samuel
2016/06/10 19:05:33
Done.
| |
69 Traits::AdvanceIterator(iter); | |
70 return value; | |
71 } | |
72 | |
73 template < | |
74 typename Traits, | |
75 typename MaybeConstUserType, | |
76 typename IteratorType, | |
77 typename std::enable_if< | |
78 !HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> | |
79 static decltype(Traits::GetAt(std::declval<MaybeConstUserType&>(), 0)) | |
80 GetNextHelper(MaybeConstUserType& input, size_t& index) { | |
81 DCHECK_LT(index, Traits::GetSize(input)); | |
82 return Traits::GetAt(input, index++); | |
83 } | |
84 | |
59 // Used as the UserTypeReader template parameter of ArraySerializer. | 85 // Used as the UserTypeReader template parameter of ArraySerializer. |
60 template <typename MaybeConstUserType> | 86 template <typename MaybeConstUserType> |
61 class ArrayReader { | 87 class ArrayReader { |
yzshen1
2016/06/10 16:21:32
Maybe we should change this to ArrayIterator and l
Fady Samuel
2016/06/10 19:05:33
Done. I'm not sure how to get rid of GetNextHelper
| |
62 public: | 88 public: |
63 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 89 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
64 using Traits = ArrayTraits<UserType>; | 90 using Traits = ArrayTraits<UserType>; |
91 using IteratorType = decltype( | |
92 CallGetBeginIfExists<Traits>(std::declval<MaybeConstUserType&>())); | |
65 | 93 |
66 explicit ArrayReader(MaybeConstUserType& input) : input_(input) {} | 94 explicit ArrayReader(MaybeConstUserType& input) |
95 : input_(input), iter_(CallGetBeginIfExists<Traits>(input)) {} | |
67 ~ArrayReader() {} | 96 ~ArrayReader() {} |
68 | 97 |
69 size_t GetSize() const { return Traits::GetSize(input_); } | 98 size_t GetSize() const { return Traits::GetSize(input_); } |
70 | 99 |
71 using GetNextResult = | 100 decltype(GetNextHelper<Traits, MaybeConstUserType, IteratorType>( |
72 decltype(Traits::GetAt(std::declval<MaybeConstUserType&>(), 0)); | 101 std::declval<MaybeConstUserType&>(), |
73 GetNextResult GetNext() { | 102 std::declval<IteratorType&>())) |
74 DCHECK_LT(index_, Traits::GetSize(input_)); | 103 GetNext() { |
75 return Traits::GetAt(input_, index_++); | 104 return GetNextHelper<Traits, MaybeConstUserType, IteratorType>(input_, |
105 iter_); | |
76 } | 106 } |
77 | 107 |
78 using GetDataIfExistsResult = decltype( | 108 using GetDataIfExistsResult = decltype( |
79 CallGetDataIfExists<Traits>(std::declval<MaybeConstUserType&>())); | 109 CallGetDataIfExists<Traits>(std::declval<MaybeConstUserType&>())); |
80 GetDataIfExistsResult GetDataIfExists() { | 110 GetDataIfExistsResult GetDataIfExists() { |
81 return CallGetDataIfExists<Traits>(input_); | 111 return CallGetDataIfExists<Traits>(input_); |
82 } | 112 } |
83 | 113 |
84 private: | 114 private: |
85 MaybeConstUserType& input_; | 115 MaybeConstUserType& input_; |
86 size_t index_ = 0; | 116 IteratorType iter_; |
87 }; | 117 }; |
88 | 118 |
89 // ArraySerializer is also used to serialize map keys and values. Therefore, it | 119 // ArraySerializer is also used to serialize map keys and values. Therefore, it |
90 // has a UserTypeReader parameter which is an adaptor for reading to hide the | 120 // has a UserTypeReader parameter which is an adaptor for reading to hide the |
91 // difference between ArrayTraits and MapTraits. | 121 // difference between ArrayTraits and MapTraits. |
92 template <typename MojomType, | 122 template <typename MojomType, |
93 typename MaybeConstUserType, | 123 typename MaybeConstUserType, |
94 typename UserTypeReader, | 124 typename UserTypeReader, |
95 ArraySerializerType type = GetArraySerializerType<MojomType>::value> | 125 ArraySerializerType type = GetArraySerializerType<MojomType>::value> |
96 struct ArraySerializer; | 126 struct ArraySerializer; |
97 | 127 |
98 // Handles serialization and deserialization of arrays of pod types. | 128 // Handles serialization and deserialization of arrays of pod types. |
99 template <typename MojomType, | 129 template <typename MojomType, |
100 typename MaybeConstUserType, | 130 typename MaybeConstUserType, |
101 typename UserTypeReader> | 131 typename UserTypeReader> |
102 struct ArraySerializer<MojomType, | 132 struct ArraySerializer<MojomType, |
103 MaybeConstUserType, | 133 MaybeConstUserType, |
104 UserTypeReader, | 134 UserTypeReader, |
105 ArraySerializerType::POD> { | 135 ArraySerializerType::POD> { |
106 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 136 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
107 using Data = typename MojomType::Data_; | 137 using Data = typename MojomType::Data_; |
108 using DataElement = typename Data::Element; | 138 using DataElement = typename Data::Element; |
109 using Element = typename MojomType::Element; | 139 using Element = typename MojomType::Element; |
110 using Traits = ArrayTraits<UserType>; | 140 using Traits = ArrayTraits<UserType>; |
141 using IteratorType = | |
142 decltype(CallGetBeginIfExists<Traits>(std::declval<UserType&>())); | |
111 | 143 |
112 static_assert(std::is_same<Element, DataElement>::value, | 144 static_assert(std::is_same<Element, DataElement>::value, |
113 "Incorrect array serializer"); | 145 "Incorrect array serializer"); |
114 static_assert(std::is_same<Element, typename Traits::Element>::value, | 146 static_assert(std::is_same<Element, typename Traits::Element>::value, |
115 "Incorrect array serializer"); | 147 "Incorrect array serializer"); |
116 | 148 |
117 static size_t GetSerializedSize(UserTypeReader* input, | 149 static size_t GetSerializedSize(UserTypeReader* input, |
118 SerializationContext* context) { | 150 SerializationContext* context) { |
119 return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement)); | 151 return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement)); |
120 } | 152 } |
(...skipping 24 matching lines...) Expand all Loading... | |
145 static bool DeserializeElements(Data* input, | 177 static bool DeserializeElements(Data* input, |
146 UserType* output, | 178 UserType* output, |
147 SerializationContext* context) { | 179 SerializationContext* context) { |
148 if (!Traits::Resize(*output, input->size())) | 180 if (!Traits::Resize(*output, input->size())) |
149 return false; | 181 return false; |
150 if (input->size()) { | 182 if (input->size()) { |
151 auto data = CallGetDataIfExists<Traits>(*output); | 183 auto data = CallGetDataIfExists<Traits>(*output); |
152 if (data) { | 184 if (data) { |
153 memcpy(data, input->storage(), input->size() * sizeof(DataElement)); | 185 memcpy(data, input->storage(), input->size() * sizeof(DataElement)); |
154 } else { | 186 } else { |
155 for (size_t i = 0; i < input->size(); ++i) | 187 IteratorType iter = CallGetBeginIfExists<Traits>(*output); |
156 Traits::GetAt(*output, i) = input->at(i); | 188 for (size_t i = 0; i < input->size(); ++i) { |
189 GetNextHelper<Traits, MaybeConstUserType, IteratorType>( | |
190 *output, iter) = input->at(i); | |
191 } | |
157 } | 192 } |
158 } | 193 } |
159 return true; | 194 return true; |
160 } | 195 } |
161 }; | 196 }; |
162 | 197 |
163 // Handles serialization and deserialization of arrays of enum types. | 198 // Handles serialization and deserialization of arrays of enum types. |
164 template <typename MojomType, | 199 template <typename MojomType, |
165 typename MaybeConstUserType, | 200 typename MaybeConstUserType, |
166 typename UserTypeReader> | 201 typename UserTypeReader> |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 template <typename MojomType, | 249 template <typename MojomType, |
215 typename MaybeConstUserType, | 250 typename MaybeConstUserType, |
216 typename UserTypeReader> | 251 typename UserTypeReader> |
217 struct ArraySerializer<MojomType, | 252 struct ArraySerializer<MojomType, |
218 MaybeConstUserType, | 253 MaybeConstUserType, |
219 UserTypeReader, | 254 UserTypeReader, |
220 ArraySerializerType::BOOLEAN> { | 255 ArraySerializerType::BOOLEAN> { |
221 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 256 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
222 using Traits = ArrayTraits<UserType>; | 257 using Traits = ArrayTraits<UserType>; |
223 using Data = typename MojomType::Data_; | 258 using Data = typename MojomType::Data_; |
259 using IteratorType = | |
260 decltype(CallGetBeginIfExists<Traits>(std::declval<UserType&>())); | |
224 | 261 |
225 static_assert(std::is_same<bool, typename UserType::Element>::value, | 262 static_assert(std::is_same<bool, typename UserType::Element>::value, |
226 "Incorrect array serializer"); | 263 "Incorrect array serializer"); |
227 | 264 |
228 static size_t GetSerializedSize(UserTypeReader* input, | 265 static size_t GetSerializedSize(UserTypeReader* input, |
229 SerializationContext* context) { | 266 SerializationContext* context) { |
230 return sizeof(Data) + Align((input->GetSize() + 7) / 8); | 267 return sizeof(Data) + Align((input->GetSize() + 7) / 8); |
231 } | 268 } |
232 | 269 |
233 static void SerializeElements(UserTypeReader* input, | 270 static void SerializeElements(UserTypeReader* input, |
234 Buffer* buf, | 271 Buffer* buf, |
235 Data* output, | 272 Data* output, |
236 const ContainerValidateParams* validate_params, | 273 const ContainerValidateParams* validate_params, |
237 SerializationContext* context) { | 274 SerializationContext* context) { |
238 DCHECK(!validate_params->element_is_nullable) | 275 DCHECK(!validate_params->element_is_nullable) |
239 << "Primitive type should be non-nullable"; | 276 << "Primitive type should be non-nullable"; |
240 DCHECK(!validate_params->element_validate_params) | 277 DCHECK(!validate_params->element_validate_params) |
241 << "Primitive type should not have array validate params"; | 278 << "Primitive type should not have array validate params"; |
242 | 279 |
243 size_t size = input->GetSize(); | 280 size_t size = input->GetSize(); |
244 for (size_t i = 0; i < size; ++i) | 281 for (size_t i = 0; i < size; ++i) |
245 output->at(i) = input->GetNext(); | 282 output->at(i) = input->GetNext(); |
246 } | 283 } |
247 static bool DeserializeElements(Data* input, | 284 static bool DeserializeElements(Data* input, |
248 UserType* output, | 285 UserType* output, |
249 SerializationContext* context) { | 286 SerializationContext* context) { |
250 if (!Traits::Resize(*output, input->size())) | 287 if (!Traits::Resize(*output, input->size())) |
251 return false; | 288 return false; |
252 for (size_t i = 0; i < input->size(); ++i) | 289 IteratorType iter = CallGetBeginIfExists<Traits>(*output); |
253 Traits::GetAt(*output, i) = input->at(i); | 290 for (size_t i = 0; i < input->size(); ++i) { |
291 GetNextHelper<Traits, MaybeConstUserType, IteratorType>(*output, iter) = | |
292 input->at(i); | |
293 } | |
254 return true; | 294 return true; |
255 } | 295 } |
256 }; | 296 }; |
257 | 297 |
258 // Serializes and deserializes arrays of handles. | 298 // Serializes and deserializes arrays of handles. |
259 template <typename MojomType, | 299 template <typename MojomType, |
260 typename MaybeConstUserType, | 300 typename MaybeConstUserType, |
261 typename UserTypeReader> | 301 typename UserTypeReader> |
262 struct ArraySerializer<MojomType, | 302 struct ArraySerializer<MojomType, |
263 MaybeConstUserType, | 303 MaybeConstUserType, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 typename UserTypeReader> | 357 typename UserTypeReader> |
318 struct ArraySerializer<MojomType, | 358 struct ArraySerializer<MojomType, |
319 MaybeConstUserType, | 359 MaybeConstUserType, |
320 UserTypeReader, | 360 UserTypeReader, |
321 ArraySerializerType::POINTER> { | 361 ArraySerializerType::POINTER> { |
322 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 362 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
323 using Data = typename MojomType::Data_; | 363 using Data = typename MojomType::Data_; |
324 using DataElement = typename Data::Element; | 364 using DataElement = typename Data::Element; |
325 using Element = typename MojomType::Element; | 365 using Element = typename MojomType::Element; |
326 using Traits = ArrayTraits<UserType>; | 366 using Traits = ArrayTraits<UserType>; |
367 using IteratorType = | |
368 decltype(CallGetBeginIfExists<Traits>(std::declval<UserType&>())); | |
327 | 369 |
328 static size_t GetSerializedSize(UserTypeReader* input, | 370 static size_t GetSerializedSize(UserTypeReader* input, |
329 SerializationContext* context) { | 371 SerializationContext* context) { |
330 size_t element_count = input->GetSize(); | 372 size_t element_count = input->GetSize(); |
331 size_t size = | 373 size_t size = |
332 sizeof(Data) + | 374 sizeof(Data) + |
333 element_count * | 375 element_count * |
334 sizeof(Pointer<typename std::remove_pointer<DataElement>::type>); | 376 sizeof(Pointer<typename std::remove_pointer<DataElement>::type>); |
335 for (size_t i = 0; i < element_count; ++i) | 377 for (size_t i = 0; i < element_count; ++i) |
336 size += PrepareToSerialize<Element>(input->GetNext(), context); | 378 size += PrepareToSerialize<Element>(input->GetNext(), context); |
(...skipping 18 matching lines...) Expand all Loading... | |
355 MakeMessageWithArrayIndex("null in array expecting valid pointers", | 397 MakeMessageWithArrayIndex("null in array expecting valid pointers", |
356 size, i)); | 398 size, i)); |
357 } | 399 } |
358 } | 400 } |
359 static bool DeserializeElements(Data* input, | 401 static bool DeserializeElements(Data* input, |
360 UserType* output, | 402 UserType* output, |
361 SerializationContext* context) { | 403 SerializationContext* context) { |
362 bool success = true; | 404 bool success = true; |
363 if (!Traits::Resize(*output, input->size())) | 405 if (!Traits::Resize(*output, input->size())) |
364 return false; | 406 return false; |
407 IteratorType iter = CallGetBeginIfExists<Traits>(*output); | |
365 for (size_t i = 0; i < input->size(); ++i) { | 408 for (size_t i = 0; i < input->size(); ++i) { |
366 // Note that we rely on complete deserialization taking place in order to | 409 // Note that we rely on complete deserialization taking place in order to |
367 // transfer ownership of all encoded handles. Therefore we don't | 410 // transfer ownership of all encoded handles. Therefore we don't |
368 // short-circuit on failure here. | 411 // short-circuit on failure here. |
369 if (!Deserialize<Element>(input->at(i), &Traits::GetAt(*output, i), | 412 if (!Deserialize<Element>( |
370 context)) { | 413 input->at(i), |
414 &GetNextHelper<Traits, MaybeConstUserType, IteratorType>(*output, | |
415 iter), | |
416 context)) { | |
371 success = false; | 417 success = false; |
372 } | 418 } |
373 } | 419 } |
374 return success; | 420 return success; |
375 } | 421 } |
376 | 422 |
377 private: | 423 private: |
378 template <typename T, | 424 template <typename T, |
379 bool is_array_or_map = IsSpecializationOf<Array, T>::value || | 425 bool is_array_or_map = IsSpecializationOf<Array, T>::value || |
380 IsSpecializationOf<Map, T>::value> | 426 IsSpecializationOf<Map, T>::value> |
(...skipping 27 matching lines...) Expand all Loading... | |
408 typename MaybeConstUserType, | 454 typename MaybeConstUserType, |
409 typename UserTypeReader> | 455 typename UserTypeReader> |
410 struct ArraySerializer<MojomType, | 456 struct ArraySerializer<MojomType, |
411 MaybeConstUserType, | 457 MaybeConstUserType, |
412 UserTypeReader, | 458 UserTypeReader, |
413 ArraySerializerType::UNION> { | 459 ArraySerializerType::UNION> { |
414 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 460 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
415 using Data = typename MojomType::Data_; | 461 using Data = typename MojomType::Data_; |
416 using Element = typename MojomType::Element; | 462 using Element = typename MojomType::Element; |
417 using Traits = ArrayTraits<UserType>; | 463 using Traits = ArrayTraits<UserType>; |
464 using IteratorType = | |
465 decltype(CallGetBeginIfExists<Traits>(std::declval<UserType&>())); | |
418 | 466 |
419 static_assert(std::is_same<typename MojomType::Element, | 467 static_assert(std::is_same<typename MojomType::Element, |
420 typename Traits::Element>::value, | 468 typename Traits::Element>::value, |
421 "Incorrect array serializer"); | 469 "Incorrect array serializer"); |
422 | 470 |
423 static size_t GetSerializedSize(UserTypeReader* input, | 471 static size_t GetSerializedSize(UserTypeReader* input, |
424 SerializationContext* context) { | 472 SerializationContext* context) { |
425 size_t element_count = input->GetSize(); | 473 size_t element_count = input->GetSize(); |
426 size_t size = sizeof(Data); | 474 size_t size = sizeof(Data); |
427 for (size_t i = 0; i < element_count; ++i) { | 475 for (size_t i = 0; i < element_count; ++i) { |
(...skipping 20 matching lines...) Expand all Loading... | |
448 size, i)); | 496 size, i)); |
449 } | 497 } |
450 } | 498 } |
451 | 499 |
452 static bool DeserializeElements(Data* input, | 500 static bool DeserializeElements(Data* input, |
453 UserType* output, | 501 UserType* output, |
454 SerializationContext* context) { | 502 SerializationContext* context) { |
455 bool success = true; | 503 bool success = true; |
456 if (!Traits::Resize(*output, input->size())) | 504 if (!Traits::Resize(*output, input->size())) |
457 return false; | 505 return false; |
506 IteratorType iter = CallGetBeginIfExists<Traits>(*output); | |
458 for (size_t i = 0; i < input->size(); ++i) { | 507 for (size_t i = 0; i < input->size(); ++i) { |
459 // Note that we rely on complete deserialization taking place in order to | 508 // Note that we rely on complete deserialization taking place in order to |
460 // transfer ownership of all encoded handles. Therefore we don't | 509 // transfer ownership of all encoded handles. Therefore we don't |
461 // short-circuit on failure here. | 510 // short-circuit on failure here. |
462 if (!Deserialize<Element>(&input->at(i), &Traits::GetAt(*output, i), | 511 if (!Deserialize<Element>( |
463 context)) { | 512 &input->at(i), |
513 &GetNextHelper<Traits, MaybeConstUserType, IteratorType>(*output, | |
514 iter), | |
515 context)) { | |
464 success = false; | 516 success = false; |
465 } | 517 } |
466 } | 518 } |
467 return success; | 519 return success; |
468 } | 520 } |
469 }; | 521 }; |
470 | 522 |
471 template <typename Element, typename MaybeConstUserType> | 523 template <typename Element, typename MaybeConstUserType> |
472 struct Serializer<Array<Element>, MaybeConstUserType> { | 524 struct Serializer<Array<Element>, MaybeConstUserType> { |
473 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 525 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
515 if (!input) | 567 if (!input) |
516 return CallSetToNullIfExists<Traits>(output); | 568 return CallSetToNullIfExists<Traits>(output); |
517 return Impl::DeserializeElements(input, output, context); | 569 return Impl::DeserializeElements(input, output, context); |
518 } | 570 } |
519 }; | 571 }; |
520 | 572 |
521 } // namespace internal | 573 } // namespace internal |
522 } // namespace mojo | 574 } // namespace mojo |
523 | 575 |
524 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | 576 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ |
OLD | NEW |