Chromium Code Reviews| 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 |
| 11 #include <limits> | 11 #include <limits> |
| 12 #include <type_traits> | 12 #include <type_traits> |
| 13 #include <utility> | 13 #include <utility> |
| 14 #include <vector> | 14 #include <vector> |
| 15 | 15 |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "mojo/public/cpp/bindings/array.h" | 17 #include "mojo/public/cpp/bindings/array.h" |
| 18 #include "mojo/public/cpp/bindings/lib/array_internal.h" | 18 #include "mojo/public/cpp/bindings/lib/array_internal.h" |
| 19 #include "mojo/public/cpp/bindings/lib/serialization_forward.h" | 19 #include "mojo/public/cpp/bindings/lib/serialization_forward.h" |
| 20 #include "mojo/public/cpp/bindings/lib/template_util.h" | 20 #include "mojo/public/cpp/bindings/lib/template_util.h" |
| 21 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | 21 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
| 22 | 22 |
| 23 namespace WTF { | |
| 24 class String; | |
| 25 } | |
| 26 | |
| 27 namespace mojo { | 23 namespace mojo { |
| 28 namespace internal { | 24 namespace internal { |
| 29 | 25 |
| 30 enum class ArraySerializerType { | 26 enum class ArraySerializerType { |
| 31 BOOLEAN, | 27 BOOLEAN, |
| 32 // Except boolean. | 28 // Except boolean. |
| 33 POD, | 29 POD, |
| 34 HANDLE, | 30 HANDLE, |
| 35 // String, array, map and struct. | 31 // String, array, map and struct. |
| 36 POINTER, | 32 POINTER, |
| 37 UNION | 33 UNION |
| 38 }; | 34 }; |
| 39 | 35 |
| 40 template <typename T> | 36 template <typename T> |
| 41 struct GetArraySerializerType { | 37 struct GetArraySerializerType { |
| 42 static const ArraySerializerType value = | 38 static const ArraySerializerType value = |
| 43 IsUnionDataType<T>::value | 39 IsUnionDataType<T>::value |
| 44 ? ArraySerializerType::UNION | 40 ? ArraySerializerType::UNION |
| 45 : (std::is_pointer<T>::value | 41 : (std::is_pointer<T>::value |
| 46 ? ArraySerializerType::POINTER | 42 ? ArraySerializerType::POINTER |
| 47 : (IsHandle<T>::value ? ArraySerializerType::HANDLE | 43 : (IsHandle<T>::value ? ArraySerializerType::HANDLE |
| 48 : (std::is_same<T, bool>::value | 44 : (std::is_same<T, bool>::value |
| 49 ? ArraySerializerType::BOOLEAN | 45 ? ArraySerializerType::BOOLEAN |
| 50 : ArraySerializerType::POD))); | 46 : ArraySerializerType::POD))); |
| 51 }; | 47 }; |
| 52 | 48 |
| 49 // Used as the UserTypeReader template parameter of ArraySerializer. | |
| 50 template <typename MaybeConstUserType> | |
| 51 class ArrayReader { | |
| 52 public: | |
| 53 using UserType = typename std::remove_const<MaybeConstUserType>::type; | |
| 54 using Traits = ArrayTraits<UserType>; | |
| 55 | |
| 56 explicit ArrayReader(MaybeConstUserType& input) : input_(input) {} | |
| 57 ~ArrayReader() {} | |
| 58 | |
| 59 size_t GetSize() const { return Traits::GetSize(input_); } | |
| 60 | |
| 61 using GetNextResult = | |
| 62 decltype(Traits::GetAt(std::declval<MaybeConstUserType&>(), 0)); | |
| 63 GetNextResult GetNext() { | |
| 64 DCHECK_LT(index_, Traits::GetSize(input_)); | |
| 65 return Traits::GetAt(input_, index_++); | |
| 66 } | |
| 67 | |
| 68 using GetDataIfAvailableResult = | |
| 69 decltype(Traits::GetData(std::declval<MaybeConstUserType&>())); | |
| 70 GetDataIfAvailableResult GetDataIfAvailable() { | |
| 71 return Traits::GetData(input_); | |
|
Ken Rockot(use gerrit already)
2016/05/27 16:07:39
If this can work in the general case (returning nu
yzshen1
2016/05/28 00:23:07
I made the GetData() function of ArrayTraits optio
| |
| 72 } | |
| 73 | |
| 74 private: | |
| 75 MaybeConstUserType& input_; | |
| 76 size_t index_ = 0; | |
| 77 }; | |
| 78 | |
| 79 // ArraySerializer is also used to serialize map keys and values. Therefore, it | |
| 80 // has a UserTypeReader parameter which is an adaptor for reading to hide the | |
| 81 // difference between ArrayTraits and MapTraits. | |
| 53 template <typename MojomType, | 82 template <typename MojomType, |
| 54 typename MaybeConstUserType, | 83 typename MaybeConstUserType, |
| 84 typename UserTypeReader, | |
| 55 ArraySerializerType type = | 85 ArraySerializerType type = |
| 56 GetArraySerializerType<typename MojomType::Data_::Element>::value> | 86 GetArraySerializerType<typename MojomType::Data_::Element>::value> |
| 57 struct ArraySerializer; | 87 struct ArraySerializer; |
| 58 | 88 |
| 59 // Handles serialization and deserialization of arrays of pod types. | 89 // Handles serialization and deserialization of arrays of pod types. |
| 60 template <typename MojomType, typename MaybeConstUserType> | 90 template <typename MojomType, |
| 91 typename MaybeConstUserType, | |
| 92 typename UserTypeReader> | |
| 61 struct ArraySerializer<MojomType, | 93 struct ArraySerializer<MojomType, |
| 62 MaybeConstUserType, | 94 MaybeConstUserType, |
| 95 UserTypeReader, | |
| 63 ArraySerializerType::POD> { | 96 ArraySerializerType::POD> { |
| 64 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 97 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| 65 using Data = typename MojomType::Data_; | 98 using Data = typename MojomType::Data_; |
| 66 using DataElement = typename Data::Element; | 99 using DataElement = typename Data::Element; |
| 67 using Element = typename MojomType::Element; | 100 using Element = typename MojomType::Element; |
| 68 using Traits = ArrayTraits<UserType>; | 101 using Traits = ArrayTraits<UserType>; |
| 69 | 102 |
| 70 static_assert(sizeof(Element) == sizeof(DataElement), | 103 static_assert(sizeof(Element) == sizeof(DataElement), |
| 71 "Incorrect array serializer"); | 104 "Incorrect array serializer"); |
| 72 static_assert(std::is_same<Element, typename Traits::Element>::value, | 105 static_assert(std::is_same<Element, typename Traits::Element>::value, |
| 73 "Incorrect array serializer"); | 106 "Incorrect array serializer"); |
| 74 | 107 |
| 75 static size_t GetSerializedSize(MaybeConstUserType& input, | 108 static size_t GetSerializedSize(UserTypeReader* input, |
| 76 SerializationContext* context) { | 109 SerializationContext* context) { |
| 77 return sizeof(Data) + Align(Traits::GetSize(input) * sizeof(DataElement)); | 110 return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement)); |
| 78 } | 111 } |
| 79 | 112 |
| 80 static void SerializeElements(MaybeConstUserType& input, | 113 static void SerializeElements(UserTypeReader* input, |
| 81 Buffer* buf, | 114 Buffer* buf, |
| 82 Data* output, | 115 Data* output, |
| 83 const ArrayValidateParams* validate_params, | 116 const ArrayValidateParams* validate_params, |
| 84 SerializationContext* context) { | 117 SerializationContext* context) { |
| 85 DCHECK(!validate_params->element_is_nullable) | 118 DCHECK(!validate_params->element_is_nullable) |
| 86 << "Primitive type should be non-nullable"; | 119 << "Primitive type should be non-nullable"; |
| 87 DCHECK(!validate_params->element_validate_params) | 120 DCHECK(!validate_params->element_validate_params) |
| 88 << "Primitive type should not have array validate params"; | 121 << "Primitive type should not have array validate params"; |
| 89 | 122 |
| 90 if (Traits::GetSize(input)) { | 123 size_t size = input->GetSize(); |
| 91 memcpy(output->storage(), Traits::GetData(input), | 124 if (size == 0) |
| 92 Traits::GetSize(input) * sizeof(DataElement)); | 125 return; |
| 126 | |
| 127 auto data = input->GetDataIfAvailable(); | |
| 128 if (data) { | |
| 129 memcpy(output->storage(), data, size * sizeof(DataElement)); | |
| 130 } else { | |
| 131 for (size_t i = 0; i < size; ++i) | |
|
Ken Rockot(use gerrit already)
2016/05/27 16:07:39
Nice, this should also be useful for things like b
yzshen1
2016/05/28 00:23:07
Done.
| |
| 132 output->at(i) = static_cast<DataElement>(input->GetNext()); | |
| 93 } | 133 } |
| 94 } | 134 } |
| 95 | 135 |
| 96 static bool DeserializeElements(Data* input, | 136 static bool DeserializeElements(Data* input, |
| 97 UserType* output, | 137 UserType* output, |
| 98 SerializationContext* context) { | 138 SerializationContext* context) { |
| 99 Traits::Resize(*output, input->size()); | 139 Traits::Resize(*output, input->size()); |
| 100 if (input->size()) { | 140 if (input->size()) { |
| 101 memcpy(Traits::GetData(*output), input->storage(), | 141 memcpy(Traits::GetData(*output), input->storage(), |
| 102 input->size() * sizeof(DataElement)); | 142 input->size() * sizeof(DataElement)); |
| 103 } | 143 } |
| 104 return true; | 144 return true; |
| 105 } | 145 } |
| 106 }; | 146 }; |
| 107 | 147 |
| 108 // Serializes and deserializes arrays of bools. | 148 // Serializes and deserializes arrays of bools. |
| 109 template <typename MojomType, typename MaybeConstUserType> | 149 template <typename MojomType, |
| 150 typename MaybeConstUserType, | |
| 151 typename UserTypeReader> | |
| 110 struct ArraySerializer<MojomType, | 152 struct ArraySerializer<MojomType, |
| 111 MaybeConstUserType, | 153 MaybeConstUserType, |
| 154 UserTypeReader, | |
| 112 ArraySerializerType::BOOLEAN> { | 155 ArraySerializerType::BOOLEAN> { |
| 113 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 156 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| 114 using Traits = ArrayTraits<UserType>; | 157 using Traits = ArrayTraits<UserType>; |
| 115 using Data = typename MojomType::Data_; | 158 using Data = typename MojomType::Data_; |
| 116 | 159 |
| 117 static_assert(std::is_same<bool, typename UserType::Element>::value, | 160 static_assert(std::is_same<bool, typename UserType::Element>::value, |
| 118 "Incorrect array serializer"); | 161 "Incorrect array serializer"); |
| 119 | 162 |
| 120 static size_t GetSerializedSize(MaybeConstUserType& input, | 163 static size_t GetSerializedSize(UserTypeReader* input, |
| 121 SerializationContext* context) { | 164 SerializationContext* context) { |
| 122 return sizeof(Data) + Align((Traits::GetSize(input) + 7) / 8); | 165 return sizeof(Data) + Align((input->GetSize() + 7) / 8); |
| 123 } | 166 } |
| 124 | 167 |
| 125 static void SerializeElements(MaybeConstUserType& input, | 168 static void SerializeElements(UserTypeReader* input, |
| 126 Buffer* buf, | 169 Buffer* buf, |
| 127 Data* output, | 170 Data* output, |
| 128 const ArrayValidateParams* validate_params, | 171 const ArrayValidateParams* validate_params, |
| 129 SerializationContext* context) { | 172 SerializationContext* context) { |
| 130 DCHECK(!validate_params->element_is_nullable) | 173 DCHECK(!validate_params->element_is_nullable) |
| 131 << "Primitive type should be non-nullable"; | 174 << "Primitive type should be non-nullable"; |
| 132 DCHECK(!validate_params->element_validate_params) | 175 DCHECK(!validate_params->element_validate_params) |
| 133 << "Primitive type should not have array validate params"; | 176 << "Primitive type should not have array validate params"; |
| 134 | 177 |
| 135 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | 178 size_t size = input->GetSize(); |
| 136 size_t size = Traits::GetSize(input); | |
| 137 for (size_t i = 0; i < size; ++i) | 179 for (size_t i = 0; i < size; ++i) |
| 138 output->at(i) = Traits::GetAt(input, i); | 180 output->at(i) = input->GetNext(); |
| 139 } | 181 } |
| 140 static bool DeserializeElements(Data* input, | 182 static bool DeserializeElements(Data* input, |
| 141 UserType* output, | 183 UserType* output, |
| 142 SerializationContext* context) { | 184 SerializationContext* context) { |
| 143 Traits::Resize(*output, input->size()); | 185 Traits::Resize(*output, input->size()); |
| 144 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | |
| 145 for (size_t i = 0; i < input->size(); ++i) | 186 for (size_t i = 0; i < input->size(); ++i) |
| 146 Traits::GetAt(*output, i) = input->at(i); | 187 Traits::GetAt(*output, i) = input->at(i); |
| 147 return true; | 188 return true; |
| 148 } | 189 } |
| 149 }; | 190 }; |
| 150 | 191 |
| 151 // Serializes and deserializes arrays of handles. | 192 // Serializes and deserializes arrays of handles. |
| 152 template <typename MojomType, typename MaybeConstUserType> | 193 template <typename MojomType, |
| 194 typename MaybeConstUserType, | |
| 195 typename UserTypeReader> | |
| 153 struct ArraySerializer<MojomType, | 196 struct ArraySerializer<MojomType, |
| 154 MaybeConstUserType, | 197 MaybeConstUserType, |
| 198 UserTypeReader, | |
| 155 ArraySerializerType::HANDLE> { | 199 ArraySerializerType::HANDLE> { |
| 156 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 200 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| 157 using Data = typename MojomType::Data_; | 201 using Data = typename MojomType::Data_; |
| 158 using Element = typename MojomType::Element; | 202 using Element = typename MojomType::Element; |
| 159 using Traits = ArrayTraits<UserType>; | 203 using Traits = ArrayTraits<UserType>; |
| 160 | 204 |
| 161 static_assert(std::is_same<Element, typename Traits::Element>::value, | 205 static_assert(std::is_same<Element, typename Traits::Element>::value, |
| 162 "Incorrect array serializer"); | 206 "Incorrect array serializer"); |
| 163 | 207 |
| 164 static size_t GetSerializedSize(MaybeConstUserType& input, | 208 static size_t GetSerializedSize(UserTypeReader* input, |
| 165 SerializationContext* context) { | 209 SerializationContext* context) { |
| 166 return sizeof(Data) + | 210 return sizeof(Data) + |
| 167 Align(Traits::GetSize(input) * sizeof(typename Data::Element)); | 211 Align(input->GetSize() * sizeof(typename Data::Element)); |
| 168 } | 212 } |
| 169 | 213 |
| 170 static void SerializeElements(MaybeConstUserType& input, | 214 static void SerializeElements(UserTypeReader* input, |
| 171 Buffer* buf, | 215 Buffer* buf, |
| 172 Data* output, | 216 Data* output, |
| 173 const ArrayValidateParams* validate_params, | 217 const ArrayValidateParams* validate_params, |
| 174 SerializationContext* context) { | 218 SerializationContext* context) { |
| 175 DCHECK(!validate_params->element_validate_params) | 219 DCHECK(!validate_params->element_validate_params) |
| 176 << "Handle type should not have array validate params"; | 220 << "Handle type should not have array validate params"; |
| 177 | 221 |
| 178 size_t size = Traits::GetSize(input); | 222 size_t size = input->GetSize(); |
| 179 for (size_t i = 0; i < size; ++i) { | 223 for (size_t i = 0; i < size; ++i) { |
| 180 // Transfer ownership of the handle. | 224 // Transfer ownership of the handle. |
| 181 output->at(i) = | 225 output->at(i) = context->handles.AddHandle(input->GetNext().release()); |
| 182 context->handles.AddHandle(Traits::GetAt(input, i).release()); | |
| 183 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 226 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
| 184 !validate_params->element_is_nullable && !output->at(i).is_valid(), | 227 !validate_params->element_is_nullable && !output->at(i).is_valid(), |
| 185 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, | 228 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, |
| 186 MakeMessageWithArrayIndex( | 229 MakeMessageWithArrayIndex( |
| 187 "invalid handle in array expecting valid handles", size, i)); | 230 "invalid handle in array expecting valid handles", size, i)); |
| 188 } | 231 } |
| 189 } | 232 } |
| 190 static bool DeserializeElements(Data* input, | 233 static bool DeserializeElements(Data* input, |
| 191 UserType* output, | 234 UserType* output, |
| 192 SerializationContext* context) { | 235 SerializationContext* context) { |
| 193 using HandleType = typename Element::RawHandleType; | 236 using HandleType = typename Element::RawHandleType; |
| 194 Traits::Resize(*output, input->size()); | 237 Traits::Resize(*output, input->size()); |
| 195 for (size_t i = 0; i < input->size(); ++i) { | 238 for (size_t i = 0; i < input->size(); ++i) { |
| 196 Traits::GetAt(*output, i) = MakeScopedHandle( | 239 Traits::GetAt(*output, i) = MakeScopedHandle( |
| 197 HandleType(context->handles.TakeHandle(input->at(i)).value())); | 240 HandleType(context->handles.TakeHandle(input->at(i)).value())); |
| 198 } | 241 } |
| 199 return true; | 242 return true; |
| 200 } | 243 } |
| 201 }; | 244 }; |
| 202 | 245 |
| 203 // This template must only apply to pointer mojo entity (strings, structs, | 246 // This template must only apply to pointer mojo entity (strings, structs, |
| 204 // arrays and maps). | 247 // arrays and maps). |
| 205 template <typename MojomType, typename MaybeConstUserType> | 248 template <typename MojomType, |
| 249 typename MaybeConstUserType, | |
| 250 typename UserTypeReader> | |
| 206 struct ArraySerializer<MojomType, | 251 struct ArraySerializer<MojomType, |
| 207 MaybeConstUserType, | 252 MaybeConstUserType, |
| 253 UserTypeReader, | |
| 208 ArraySerializerType::POINTER> { | 254 ArraySerializerType::POINTER> { |
| 209 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 255 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| 210 using Data = typename MojomType::Data_; | 256 using Data = typename MojomType::Data_; |
| 211 using DataElement = typename Data::Element; | 257 using DataElement = typename Data::Element; |
| 212 using Element = typename MojomType::Element; | 258 using Element = typename MojomType::Element; |
| 213 using Traits = ArrayTraits<UserType>; | 259 using Traits = ArrayTraits<UserType>; |
| 214 | 260 |
| 215 static size_t GetSerializedSize(MaybeConstUserType& input, | 261 static size_t GetSerializedSize(UserTypeReader* input, |
| 216 SerializationContext* context) { | 262 SerializationContext* context) { |
| 217 size_t element_count = Traits::GetSize(input); | 263 size_t element_count = input->GetSize(); |
| 218 size_t size = | 264 size_t size = |
| 219 sizeof(Data) + | 265 sizeof(Data) + |
| 220 element_count * | 266 element_count * |
| 221 sizeof(Pointer<typename std::remove_pointer<DataElement>::type>); | 267 sizeof(Pointer<typename std::remove_pointer<DataElement>::type>); |
| 222 for (size_t i = 0; i < element_count; ++i) | 268 for (size_t i = 0; i < element_count; ++i) |
| 223 size += PrepareToSerialize<Element>(Traits::GetAt(input, i), context); | 269 size += PrepareToSerialize<Element>(input->GetNext(), context); |
| 224 return size; | 270 return size; |
| 225 } | 271 } |
| 226 | 272 |
| 227 static void SerializeElements(MaybeConstUserType& input, | 273 static void SerializeElements(UserTypeReader* input, |
| 228 Buffer* buf, | 274 Buffer* buf, |
| 229 Data* output, | 275 Data* output, |
| 230 const ArrayValidateParams* validate_params, | 276 const ArrayValidateParams* validate_params, |
| 231 SerializationContext* context) { | 277 SerializationContext* context) { |
| 232 size_t size = Traits::GetSize(input); | 278 size_t size = input->GetSize(); |
| 233 for (size_t i = 0; i < size; ++i) { | 279 for (size_t i = 0; i < size; ++i) { |
| 234 DataElement element; | 280 DataElement element; |
| 235 SerializeCaller<Element>::Run(Traits::GetAt(input, i), buf, &element, | 281 SerializeCaller<Element>::Run(input->GetNext(), buf, &element, |
| 236 validate_params->element_validate_params, | 282 validate_params->element_validate_params, |
| 237 context); | 283 context); |
| 238 output->at(i) = element; | 284 output->at(i) = element; |
| 239 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 285 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
| 240 !validate_params->element_is_nullable && !element, | 286 !validate_params->element_is_nullable && !element, |
| 241 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 287 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
| 242 MakeMessageWithArrayIndex("null in array expecting valid pointers", | 288 MakeMessageWithArrayIndex("null in array expecting valid pointers", |
| 243 size, i)); | 289 size, i)); |
| 244 } | 290 } |
| 245 } | 291 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 DataElement* output, | 329 DataElement* output, |
| 284 const ArrayValidateParams* validate_params, | 330 const ArrayValidateParams* validate_params, |
| 285 SerializationContext* context) { | 331 SerializationContext* context) { |
| 286 Serialize<T>(std::forward<InputElementType>(input), buf, output, | 332 Serialize<T>(std::forward<InputElementType>(input), buf, output, |
| 287 validate_params, context); | 333 validate_params, context); |
| 288 } | 334 } |
| 289 }; | 335 }; |
| 290 }; | 336 }; |
| 291 | 337 |
| 292 // Handles serialization and deserialization of arrays of unions. | 338 // Handles serialization and deserialization of arrays of unions. |
| 293 template <typename MojomType, typename MaybeConstUserType> | 339 template <typename MojomType, |
| 340 typename MaybeConstUserType, | |
| 341 typename UserTypeReader> | |
| 294 struct ArraySerializer<MojomType, | 342 struct ArraySerializer<MojomType, |
| 295 MaybeConstUserType, | 343 MaybeConstUserType, |
| 344 UserTypeReader, | |
| 296 ArraySerializerType::UNION> { | 345 ArraySerializerType::UNION> { |
| 297 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 346 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| 298 using Data = typename MojomType::Data_; | 347 using Data = typename MojomType::Data_; |
| 299 using Element = typename MojomType::Element; | 348 using Element = typename MojomType::Element; |
| 300 using Traits = ArrayTraits<UserType>; | 349 using Traits = ArrayTraits<UserType>; |
| 301 | 350 |
| 302 static_assert(std::is_same<typename MojomType::Element, | 351 static_assert(std::is_same<typename MojomType::Element, |
| 303 typename Traits::Element>::value, | 352 typename Traits::Element>::value, |
| 304 "Incorrect array serializer"); | 353 "Incorrect array serializer"); |
| 305 | 354 |
| 306 static size_t GetSerializedSize(MaybeConstUserType& input, | 355 static size_t GetSerializedSize(UserTypeReader* input, |
| 307 SerializationContext* context) { | 356 SerializationContext* context) { |
| 308 size_t element_count = Traits::GetSize(input); | 357 size_t element_count = input->GetSize(); |
| 309 size_t size = sizeof(Data); | 358 size_t size = sizeof(Data); |
| 310 for (size_t i = 0; i < element_count; ++i) { | 359 for (size_t i = 0; i < element_count; ++i) { |
| 311 // Call with |inlined| set to false, so that it will account for both the | 360 // Call with |inlined| set to false, so that it will account for both the |
| 312 // data in the union and the space in the array used to hold the union. | 361 // data in the union and the space in the array used to hold the union. |
| 313 size += | 362 size += PrepareToSerialize<Element>(input->GetNext(), false, context); |
| 314 PrepareToSerialize<Element>(Traits::GetAt(input, i), false, context); | |
| 315 } | 363 } |
| 316 return size; | 364 return size; |
| 317 } | 365 } |
| 318 | 366 |
| 319 static void SerializeElements(MaybeConstUserType& input, | 367 static void SerializeElements(UserTypeReader* input, |
| 320 Buffer* buf, | 368 Buffer* buf, |
| 321 Data* output, | 369 Data* output, |
| 322 const ArrayValidateParams* validate_params, | 370 const ArrayValidateParams* validate_params, |
| 323 SerializationContext* context) { | 371 SerializationContext* context) { |
| 324 size_t size = Traits::GetSize(input); | 372 size_t size = input->GetSize(); |
| 325 for (size_t i = 0; i < size; ++i) { | 373 for (size_t i = 0; i < size; ++i) { |
| 326 typename Data::Element* result = output->storage() + i; | 374 typename Data::Element* result = output->storage() + i; |
| 327 Serialize<Element>(Traits::GetAt(input, i), buf, &result, true, context); | 375 Serialize<Element>(input->GetNext(), buf, &result, true, context); |
| 328 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 376 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
| 329 !validate_params->element_is_nullable && output->at(i).is_null(), | 377 !validate_params->element_is_nullable && output->at(i).is_null(), |
| 330 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 378 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
| 331 MakeMessageWithArrayIndex("null in array expecting valid unions", | 379 MakeMessageWithArrayIndex("null in array expecting valid unions", |
| 332 size, i)); | 380 size, i)); |
| 333 } | 381 } |
| 334 } | 382 } |
| 335 | 383 |
| 336 static bool DeserializeElements(Data* input, | 384 static bool DeserializeElements(Data* input, |
| 337 UserType* output, | 385 UserType* output, |
| 338 SerializationContext* context) { | 386 SerializationContext* context) { |
| 339 bool success = true; | 387 bool success = true; |
| 340 Traits::Resize(*output, input->size()); | 388 Traits::Resize(*output, input->size()); |
| 341 for (size_t i = 0; i < input->size(); ++i) { | 389 for (size_t i = 0; i < input->size(); ++i) { |
| 342 // Note that we rely on complete deserialization taking place in order to | 390 // Note that we rely on complete deserialization taking place in order to |
| 343 // transfer ownership of all encoded handles. Therefore we don't | 391 // transfer ownership of all encoded handles. Therefore we don't |
| 344 // short-circuit on failure here. | 392 // short-circuit on failure here. |
| 345 if (!Deserialize<Element>(&input->at(i), &Traits::GetAt(*output, i), | 393 if (!Deserialize<Element>(&input->at(i), &Traits::GetAt(*output, i), |
| 346 context)) { | 394 context)) { |
| 347 success = false; | 395 success = false; |
| 348 } | 396 } |
| 349 } | 397 } |
| 350 return success; | 398 return success; |
| 351 } | 399 } |
| 352 }; | 400 }; |
| 353 | 401 |
| 354 template <typename Element, typename MaybeConstUserType> | 402 template <typename Element, typename MaybeConstUserType> |
| 355 struct Serializer<Array<Element>, MaybeConstUserType> { | 403 struct Serializer<Array<Element>, MaybeConstUserType> { |
| 356 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 404 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| 357 using Impl = ArraySerializer<Array<Element>, MaybeConstUserType>; | 405 using Impl = ArraySerializer<Array<Element>, |
| 406 MaybeConstUserType, | |
| 407 ArrayReader<MaybeConstUserType>>; | |
| 358 using Traits = ArrayTraits<UserType>; | 408 using Traits = ArrayTraits<UserType>; |
| 359 using Data = typename Array<Element>::Data_; | 409 using Data = typename Array<Element>::Data_; |
| 360 | 410 |
| 361 static size_t PrepareToSerialize(MaybeConstUserType& input, | 411 static size_t PrepareToSerialize(MaybeConstUserType& input, |
| 362 SerializationContext* context) { | 412 SerializationContext* context) { |
| 363 if (CallIsNullIfExists<Traits>(input)) | 413 if (CallIsNullIfExists<Traits>(input)) |
| 364 return 0; | 414 return 0; |
| 365 return Impl::GetSerializedSize(input, context); | 415 ArrayReader<MaybeConstUserType> reader(input); |
| 416 return Impl::GetSerializedSize(&reader, context); | |
| 366 } | 417 } |
| 367 | 418 |
| 368 static void Serialize(MaybeConstUserType& input, | 419 static void Serialize(MaybeConstUserType& input, |
| 369 Buffer* buf, | 420 Buffer* buf, |
| 370 Data** output, | 421 Data** output, |
| 371 const ArrayValidateParams* validate_params, | 422 const ArrayValidateParams* validate_params, |
| 372 SerializationContext* context) { | 423 SerializationContext* context) { |
| 373 if (!CallIsNullIfExists<Traits>(input)) { | 424 if (!CallIsNullIfExists<Traits>(input)) { |
| 374 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 425 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
| 375 validate_params->expected_num_elements != 0 && | 426 validate_params->expected_num_elements != 0 && |
| 376 Traits::GetSize(input) != validate_params->expected_num_elements, | 427 Traits::GetSize(input) != validate_params->expected_num_elements, |
| 377 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, | 428 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, |
| 378 internal::MakeMessageWithExpectedArraySize( | 429 internal::MakeMessageWithExpectedArraySize( |
| 379 "fixed-size array has wrong number of elements", | 430 "fixed-size array has wrong number of elements", |
| 380 Traits::GetSize(input), validate_params->expected_num_elements)); | 431 Traits::GetSize(input), validate_params->expected_num_elements)); |
| 381 Data* result = Data::New(Traits::GetSize(input), buf); | 432 Data* result = Data::New(Traits::GetSize(input), buf); |
| 382 if (result) | 433 if (result) { |
| 383 Impl::SerializeElements(input, buf, result, validate_params, context); | 434 ArrayReader<MaybeConstUserType> reader(input); |
| 435 Impl::SerializeElements(&reader, buf, result, validate_params, context); | |
| 436 } | |
| 384 *output = result; | 437 *output = result; |
| 385 } else { | 438 } else { |
| 386 *output = nullptr; | 439 *output = nullptr; |
| 387 } | 440 } |
| 388 } | 441 } |
| 389 | 442 |
| 390 static bool Deserialize(Data* input, | 443 static bool Deserialize(Data* input, |
| 391 UserType* output, | 444 UserType* output, |
| 392 SerializationContext* context) { | 445 SerializationContext* context) { |
| 393 if (!input) | 446 if (!input) |
| 394 return CallSetToNullIfExists<Traits>(output); | 447 return CallSetToNullIfExists<Traits>(output); |
| 395 return Impl::DeserializeElements(input, output, context); | 448 return Impl::DeserializeElements(input, output, context); |
| 396 } | 449 } |
| 397 }; | 450 }; |
| 398 | 451 |
| 399 } // namespace internal | 452 } // namespace internal |
| 400 } // namespace mojo | 453 } // namespace mojo |
| 401 | 454 |
| 402 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | 455 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ |
| OLD | NEW |