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 GetDataIfExistsResult = decltype( |
| 69 CallGetDataIfExists<Traits>(std::declval<MaybeConstUserType&>())); |
| 70 GetDataIfExistsResult GetDataIfExists() { |
| 71 return CallGetDataIfExists<Traits>(input_); |
| 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->GetDataIfExists(); |
| 128 if (data) { |
| 129 memcpy(output->storage(), data, size * sizeof(DataElement)); |
| 130 } else { |
| 131 for (size_t i = 0; i < size; ++i) |
| 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 auto data = CallGetDataIfExists<Traits>(*output); |
102 input->size() * sizeof(DataElement)); | 142 if (data) { |
| 143 memcpy(data, input->storage(), input->size() * sizeof(DataElement)); |
| 144 } else { |
| 145 for (size_t i = 0; i < input->size(); ++i) |
| 146 Traits::GetAt(*output, i) = static_cast<Element>(input->at(i)); |
| 147 } |
103 } | 148 } |
104 return true; | 149 return true; |
105 } | 150 } |
106 }; | 151 }; |
107 | 152 |
108 // Serializes and deserializes arrays of bools. | 153 // Serializes and deserializes arrays of bools. |
109 template <typename MojomType, typename MaybeConstUserType> | 154 template <typename MojomType, |
| 155 typename MaybeConstUserType, |
| 156 typename UserTypeReader> |
110 struct ArraySerializer<MojomType, | 157 struct ArraySerializer<MojomType, |
111 MaybeConstUserType, | 158 MaybeConstUserType, |
| 159 UserTypeReader, |
112 ArraySerializerType::BOOLEAN> { | 160 ArraySerializerType::BOOLEAN> { |
113 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 161 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
114 using Traits = ArrayTraits<UserType>; | 162 using Traits = ArrayTraits<UserType>; |
115 using Data = typename MojomType::Data_; | 163 using Data = typename MojomType::Data_; |
116 | 164 |
117 static_assert(std::is_same<bool, typename UserType::Element>::value, | 165 static_assert(std::is_same<bool, typename UserType::Element>::value, |
118 "Incorrect array serializer"); | 166 "Incorrect array serializer"); |
119 | 167 |
120 static size_t GetSerializedSize(MaybeConstUserType& input, | 168 static size_t GetSerializedSize(UserTypeReader* input, |
121 SerializationContext* context) { | 169 SerializationContext* context) { |
122 return sizeof(Data) + Align((Traits::GetSize(input) + 7) / 8); | 170 return sizeof(Data) + Align((input->GetSize() + 7) / 8); |
123 } | 171 } |
124 | 172 |
125 static void SerializeElements(MaybeConstUserType& input, | 173 static void SerializeElements(UserTypeReader* input, |
126 Buffer* buf, | 174 Buffer* buf, |
127 Data* output, | 175 Data* output, |
128 const ArrayValidateParams* validate_params, | 176 const ArrayValidateParams* validate_params, |
129 SerializationContext* context) { | 177 SerializationContext* context) { |
130 DCHECK(!validate_params->element_is_nullable) | 178 DCHECK(!validate_params->element_is_nullable) |
131 << "Primitive type should be non-nullable"; | 179 << "Primitive type should be non-nullable"; |
132 DCHECK(!validate_params->element_validate_params) | 180 DCHECK(!validate_params->element_validate_params) |
133 << "Primitive type should not have array validate params"; | 181 << "Primitive type should not have array validate params"; |
134 | 182 |
135 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | 183 size_t size = input->GetSize(); |
136 size_t size = Traits::GetSize(input); | |
137 for (size_t i = 0; i < size; ++i) | 184 for (size_t i = 0; i < size; ++i) |
138 output->at(i) = Traits::GetAt(input, i); | 185 output->at(i) = input->GetNext(); |
139 } | 186 } |
140 static bool DeserializeElements(Data* input, | 187 static bool DeserializeElements(Data* input, |
141 UserType* output, | 188 UserType* output, |
142 SerializationContext* context) { | 189 SerializationContext* context) { |
143 Traits::Resize(*output, input->size()); | 190 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) | 191 for (size_t i = 0; i < input->size(); ++i) |
146 Traits::GetAt(*output, i) = input->at(i); | 192 Traits::GetAt(*output, i) = input->at(i); |
147 return true; | 193 return true; |
148 } | 194 } |
149 }; | 195 }; |
150 | 196 |
151 // Serializes and deserializes arrays of handles. | 197 // Serializes and deserializes arrays of handles. |
152 template <typename MojomType, typename MaybeConstUserType> | 198 template <typename MojomType, |
| 199 typename MaybeConstUserType, |
| 200 typename UserTypeReader> |
153 struct ArraySerializer<MojomType, | 201 struct ArraySerializer<MojomType, |
154 MaybeConstUserType, | 202 MaybeConstUserType, |
| 203 UserTypeReader, |
155 ArraySerializerType::HANDLE> { | 204 ArraySerializerType::HANDLE> { |
156 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 205 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
157 using Data = typename MojomType::Data_; | 206 using Data = typename MojomType::Data_; |
158 using Element = typename MojomType::Element; | 207 using Element = typename MojomType::Element; |
159 using Traits = ArrayTraits<UserType>; | 208 using Traits = ArrayTraits<UserType>; |
160 | 209 |
161 static_assert(std::is_same<Element, typename Traits::Element>::value, | 210 static_assert(std::is_same<Element, typename Traits::Element>::value, |
162 "Incorrect array serializer"); | 211 "Incorrect array serializer"); |
163 | 212 |
164 static size_t GetSerializedSize(MaybeConstUserType& input, | 213 static size_t GetSerializedSize(UserTypeReader* input, |
165 SerializationContext* context) { | 214 SerializationContext* context) { |
166 return sizeof(Data) + | 215 return sizeof(Data) + |
167 Align(Traits::GetSize(input) * sizeof(typename Data::Element)); | 216 Align(input->GetSize() * sizeof(typename Data::Element)); |
168 } | 217 } |
169 | 218 |
170 static void SerializeElements(MaybeConstUserType& input, | 219 static void SerializeElements(UserTypeReader* input, |
171 Buffer* buf, | 220 Buffer* buf, |
172 Data* output, | 221 Data* output, |
173 const ArrayValidateParams* validate_params, | 222 const ArrayValidateParams* validate_params, |
174 SerializationContext* context) { | 223 SerializationContext* context) { |
175 DCHECK(!validate_params->element_validate_params) | 224 DCHECK(!validate_params->element_validate_params) |
176 << "Handle type should not have array validate params"; | 225 << "Handle type should not have array validate params"; |
177 | 226 |
178 size_t size = Traits::GetSize(input); | 227 size_t size = input->GetSize(); |
179 for (size_t i = 0; i < size; ++i) { | 228 for (size_t i = 0; i < size; ++i) { |
180 // Transfer ownership of the handle. | 229 // Transfer ownership of the handle. |
181 output->at(i) = | 230 output->at(i) = context->handles.AddHandle(input->GetNext().release()); |
182 context->handles.AddHandle(Traits::GetAt(input, i).release()); | |
183 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 231 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
184 !validate_params->element_is_nullable && !output->at(i).is_valid(), | 232 !validate_params->element_is_nullable && !output->at(i).is_valid(), |
185 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, | 233 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, |
186 MakeMessageWithArrayIndex( | 234 MakeMessageWithArrayIndex( |
187 "invalid handle in array expecting valid handles", size, i)); | 235 "invalid handle in array expecting valid handles", size, i)); |
188 } | 236 } |
189 } | 237 } |
190 static bool DeserializeElements(Data* input, | 238 static bool DeserializeElements(Data* input, |
191 UserType* output, | 239 UserType* output, |
192 SerializationContext* context) { | 240 SerializationContext* context) { |
193 using HandleType = typename Element::RawHandleType; | 241 using HandleType = typename Element::RawHandleType; |
194 Traits::Resize(*output, input->size()); | 242 Traits::Resize(*output, input->size()); |
195 for (size_t i = 0; i < input->size(); ++i) { | 243 for (size_t i = 0; i < input->size(); ++i) { |
196 Traits::GetAt(*output, i) = MakeScopedHandle( | 244 Traits::GetAt(*output, i) = MakeScopedHandle( |
197 HandleType(context->handles.TakeHandle(input->at(i)).value())); | 245 HandleType(context->handles.TakeHandle(input->at(i)).value())); |
198 } | 246 } |
199 return true; | 247 return true; |
200 } | 248 } |
201 }; | 249 }; |
202 | 250 |
203 // This template must only apply to pointer mojo entity (strings, structs, | 251 // This template must only apply to pointer mojo entity (strings, structs, |
204 // arrays and maps). | 252 // arrays and maps). |
205 template <typename MojomType, typename MaybeConstUserType> | 253 template <typename MojomType, |
| 254 typename MaybeConstUserType, |
| 255 typename UserTypeReader> |
206 struct ArraySerializer<MojomType, | 256 struct ArraySerializer<MojomType, |
207 MaybeConstUserType, | 257 MaybeConstUserType, |
| 258 UserTypeReader, |
208 ArraySerializerType::POINTER> { | 259 ArraySerializerType::POINTER> { |
209 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 260 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
210 using Data = typename MojomType::Data_; | 261 using Data = typename MojomType::Data_; |
211 using DataElement = typename Data::Element; | 262 using DataElement = typename Data::Element; |
212 using Element = typename MojomType::Element; | 263 using Element = typename MojomType::Element; |
213 using Traits = ArrayTraits<UserType>; | 264 using Traits = ArrayTraits<UserType>; |
214 | 265 |
215 static size_t GetSerializedSize(MaybeConstUserType& input, | 266 static size_t GetSerializedSize(UserTypeReader* input, |
216 SerializationContext* context) { | 267 SerializationContext* context) { |
217 size_t element_count = Traits::GetSize(input); | 268 size_t element_count = input->GetSize(); |
218 size_t size = | 269 size_t size = |
219 sizeof(Data) + | 270 sizeof(Data) + |
220 element_count * | 271 element_count * |
221 sizeof(Pointer<typename std::remove_pointer<DataElement>::type>); | 272 sizeof(Pointer<typename std::remove_pointer<DataElement>::type>); |
222 for (size_t i = 0; i < element_count; ++i) | 273 for (size_t i = 0; i < element_count; ++i) |
223 size += PrepareToSerialize<Element>(Traits::GetAt(input, i), context); | 274 size += PrepareToSerialize<Element>(input->GetNext(), context); |
224 return size; | 275 return size; |
225 } | 276 } |
226 | 277 |
227 static void SerializeElements(MaybeConstUserType& input, | 278 static void SerializeElements(UserTypeReader* input, |
228 Buffer* buf, | 279 Buffer* buf, |
229 Data* output, | 280 Data* output, |
230 const ArrayValidateParams* validate_params, | 281 const ArrayValidateParams* validate_params, |
231 SerializationContext* context) { | 282 SerializationContext* context) { |
232 size_t size = Traits::GetSize(input); | 283 size_t size = input->GetSize(); |
233 for (size_t i = 0; i < size; ++i) { | 284 for (size_t i = 0; i < size; ++i) { |
234 DataElement element; | 285 DataElement element; |
235 SerializeCaller<Element>::Run(Traits::GetAt(input, i), buf, &element, | 286 SerializeCaller<Element>::Run(input->GetNext(), buf, &element, |
236 validate_params->element_validate_params, | 287 validate_params->element_validate_params, |
237 context); | 288 context); |
238 output->at(i) = element; | 289 output->at(i) = element; |
239 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 290 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
240 !validate_params->element_is_nullable && !element, | 291 !validate_params->element_is_nullable && !element, |
241 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 292 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
242 MakeMessageWithArrayIndex("null in array expecting valid pointers", | 293 MakeMessageWithArrayIndex("null in array expecting valid pointers", |
243 size, i)); | 294 size, i)); |
244 } | 295 } |
245 } | 296 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 DataElement* output, | 334 DataElement* output, |
284 const ArrayValidateParams* validate_params, | 335 const ArrayValidateParams* validate_params, |
285 SerializationContext* context) { | 336 SerializationContext* context) { |
286 Serialize<T>(std::forward<InputElementType>(input), buf, output, | 337 Serialize<T>(std::forward<InputElementType>(input), buf, output, |
287 validate_params, context); | 338 validate_params, context); |
288 } | 339 } |
289 }; | 340 }; |
290 }; | 341 }; |
291 | 342 |
292 // Handles serialization and deserialization of arrays of unions. | 343 // Handles serialization and deserialization of arrays of unions. |
293 template <typename MojomType, typename MaybeConstUserType> | 344 template <typename MojomType, |
| 345 typename MaybeConstUserType, |
| 346 typename UserTypeReader> |
294 struct ArraySerializer<MojomType, | 347 struct ArraySerializer<MojomType, |
295 MaybeConstUserType, | 348 MaybeConstUserType, |
| 349 UserTypeReader, |
296 ArraySerializerType::UNION> { | 350 ArraySerializerType::UNION> { |
297 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 351 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
298 using Data = typename MojomType::Data_; | 352 using Data = typename MojomType::Data_; |
299 using Element = typename MojomType::Element; | 353 using Element = typename MojomType::Element; |
300 using Traits = ArrayTraits<UserType>; | 354 using Traits = ArrayTraits<UserType>; |
301 | 355 |
302 static_assert(std::is_same<typename MojomType::Element, | 356 static_assert(std::is_same<typename MojomType::Element, |
303 typename Traits::Element>::value, | 357 typename Traits::Element>::value, |
304 "Incorrect array serializer"); | 358 "Incorrect array serializer"); |
305 | 359 |
306 static size_t GetSerializedSize(MaybeConstUserType& input, | 360 static size_t GetSerializedSize(UserTypeReader* input, |
307 SerializationContext* context) { | 361 SerializationContext* context) { |
308 size_t element_count = Traits::GetSize(input); | 362 size_t element_count = input->GetSize(); |
309 size_t size = sizeof(Data); | 363 size_t size = sizeof(Data); |
310 for (size_t i = 0; i < element_count; ++i) { | 364 for (size_t i = 0; i < element_count; ++i) { |
311 // Call with |inlined| set to false, so that it will account for both the | 365 // 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. | 366 // data in the union and the space in the array used to hold the union. |
313 size += | 367 size += PrepareToSerialize<Element>(input->GetNext(), false, context); |
314 PrepareToSerialize<Element>(Traits::GetAt(input, i), false, context); | |
315 } | 368 } |
316 return size; | 369 return size; |
317 } | 370 } |
318 | 371 |
319 static void SerializeElements(MaybeConstUserType& input, | 372 static void SerializeElements(UserTypeReader* input, |
320 Buffer* buf, | 373 Buffer* buf, |
321 Data* output, | 374 Data* output, |
322 const ArrayValidateParams* validate_params, | 375 const ArrayValidateParams* validate_params, |
323 SerializationContext* context) { | 376 SerializationContext* context) { |
324 size_t size = Traits::GetSize(input); | 377 size_t size = input->GetSize(); |
325 for (size_t i = 0; i < size; ++i) { | 378 for (size_t i = 0; i < size; ++i) { |
326 typename Data::Element* result = output->storage() + i; | 379 typename Data::Element* result = output->storage() + i; |
327 Serialize<Element>(Traits::GetAt(input, i), buf, &result, true, context); | 380 Serialize<Element>(input->GetNext(), buf, &result, true, context); |
328 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 381 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
329 !validate_params->element_is_nullable && output->at(i).is_null(), | 382 !validate_params->element_is_nullable && output->at(i).is_null(), |
330 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 383 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
331 MakeMessageWithArrayIndex("null in array expecting valid unions", | 384 MakeMessageWithArrayIndex("null in array expecting valid unions", |
332 size, i)); | 385 size, i)); |
333 } | 386 } |
334 } | 387 } |
335 | 388 |
336 static bool DeserializeElements(Data* input, | 389 static bool DeserializeElements(Data* input, |
337 UserType* output, | 390 UserType* output, |
338 SerializationContext* context) { | 391 SerializationContext* context) { |
339 bool success = true; | 392 bool success = true; |
340 Traits::Resize(*output, input->size()); | 393 Traits::Resize(*output, input->size()); |
341 for (size_t i = 0; i < input->size(); ++i) { | 394 for (size_t i = 0; i < input->size(); ++i) { |
342 // Note that we rely on complete deserialization taking place in order to | 395 // Note that we rely on complete deserialization taking place in order to |
343 // transfer ownership of all encoded handles. Therefore we don't | 396 // transfer ownership of all encoded handles. Therefore we don't |
344 // short-circuit on failure here. | 397 // short-circuit on failure here. |
345 if (!Deserialize<Element>(&input->at(i), &Traits::GetAt(*output, i), | 398 if (!Deserialize<Element>(&input->at(i), &Traits::GetAt(*output, i), |
346 context)) { | 399 context)) { |
347 success = false; | 400 success = false; |
348 } | 401 } |
349 } | 402 } |
350 return success; | 403 return success; |
351 } | 404 } |
352 }; | 405 }; |
353 | 406 |
354 template <typename Element, typename MaybeConstUserType> | 407 template <typename Element, typename MaybeConstUserType> |
355 struct Serializer<Array<Element>, MaybeConstUserType> { | 408 struct Serializer<Array<Element>, MaybeConstUserType> { |
356 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 409 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
357 using Impl = ArraySerializer<Array<Element>, MaybeConstUserType>; | 410 using Impl = ArraySerializer<Array<Element>, |
| 411 MaybeConstUserType, |
| 412 ArrayReader<MaybeConstUserType>>; |
358 using Traits = ArrayTraits<UserType>; | 413 using Traits = ArrayTraits<UserType>; |
359 using Data = typename Array<Element>::Data_; | 414 using Data = typename Array<Element>::Data_; |
360 | 415 |
361 static size_t PrepareToSerialize(MaybeConstUserType& input, | 416 static size_t PrepareToSerialize(MaybeConstUserType& input, |
362 SerializationContext* context) { | 417 SerializationContext* context) { |
363 if (CallIsNullIfExists<Traits>(input)) | 418 if (CallIsNullIfExists<Traits>(input)) |
364 return 0; | 419 return 0; |
365 return Impl::GetSerializedSize(input, context); | 420 ArrayReader<MaybeConstUserType> reader(input); |
| 421 return Impl::GetSerializedSize(&reader, context); |
366 } | 422 } |
367 | 423 |
368 static void Serialize(MaybeConstUserType& input, | 424 static void Serialize(MaybeConstUserType& input, |
369 Buffer* buf, | 425 Buffer* buf, |
370 Data** output, | 426 Data** output, |
371 const ArrayValidateParams* validate_params, | 427 const ArrayValidateParams* validate_params, |
372 SerializationContext* context) { | 428 SerializationContext* context) { |
373 if (!CallIsNullIfExists<Traits>(input)) { | 429 if (!CallIsNullIfExists<Traits>(input)) { |
374 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 430 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
375 validate_params->expected_num_elements != 0 && | 431 validate_params->expected_num_elements != 0 && |
376 Traits::GetSize(input) != validate_params->expected_num_elements, | 432 Traits::GetSize(input) != validate_params->expected_num_elements, |
377 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, | 433 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, |
378 internal::MakeMessageWithExpectedArraySize( | 434 internal::MakeMessageWithExpectedArraySize( |
379 "fixed-size array has wrong number of elements", | 435 "fixed-size array has wrong number of elements", |
380 Traits::GetSize(input), validate_params->expected_num_elements)); | 436 Traits::GetSize(input), validate_params->expected_num_elements)); |
381 Data* result = Data::New(Traits::GetSize(input), buf); | 437 Data* result = Data::New(Traits::GetSize(input), buf); |
382 if (result) | 438 if (result) { |
383 Impl::SerializeElements(input, buf, result, validate_params, context); | 439 ArrayReader<MaybeConstUserType> reader(input); |
| 440 Impl::SerializeElements(&reader, buf, result, validate_params, context); |
| 441 } |
384 *output = result; | 442 *output = result; |
385 } else { | 443 } else { |
386 *output = nullptr; | 444 *output = nullptr; |
387 } | 445 } |
388 } | 446 } |
389 | 447 |
390 static bool Deserialize(Data* input, | 448 static bool Deserialize(Data* input, |
391 UserType* output, | 449 UserType* output, |
392 SerializationContext* context) { | 450 SerializationContext* context) { |
393 if (!input) | 451 if (!input) |
394 return CallSetToNullIfExists<Traits>(output); | 452 return CallSetToNullIfExists<Traits>(output); |
395 return Impl::DeserializeElements(input, output, context); | 453 return Impl::DeserializeElements(input, output, context); |
396 } | 454 } |
397 }; | 455 }; |
398 | 456 |
399 } // namespace internal | 457 } // namespace internal |
400 } // namespace mojo | 458 } // namespace mojo |
401 | 459 |
402 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | 460 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ |
OLD | NEW |