| OLD | NEW |
| (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_ | |
| OLD | NEW |