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 <string.h> // For |memcpy()|. | 8 #include <string.h> // For |memcpy()|. |
9 | |
10 #include <vector> | 9 #include <vector> |
11 | 10 |
12 #include "mojo/public/c/system/macros.h" | 11 #include "mojo/public/c/system/macros.h" |
13 #include "mojo/public/cpp/bindings/lib/array_internal.h" | 12 #include "mojo/public/cpp/bindings/lib/array_internal.h" |
14 #include "mojo/public/cpp/bindings/lib/map_serialization.h" | 13 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" |
14 #include "mojo/public/cpp/bindings/lib/iterator_util.h" | |
15 #include "mojo/public/cpp/bindings/lib/map_data_internal.h" | |
16 #include "mojo/public/cpp/bindings/lib/map_serialization_forward.h" | |
15 #include "mojo/public/cpp/bindings/lib/string_serialization.h" | 17 #include "mojo/public/cpp/bindings/lib/string_serialization.h" |
16 #include "mojo/public/cpp/bindings/lib/template_util.h" | 18 #include "mojo/public/cpp/bindings/lib/template_util.h" |
17 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | 19 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
18 | 20 |
19 namespace mojo { | 21 namespace mojo { |
20 | |
21 template <typename E> | |
22 inline size_t GetSerializedSize_(const Array<E>& input); | |
23 | |
24 template <typename E, typename F> | |
25 inline void SerializeArray_( | |
26 Array<E> input, | |
27 internal::Buffer* buf, | |
28 internal::Array_Data<F>** output, | |
29 const internal::ArrayValidateParams* validate_params); | |
30 | |
31 template <typename E, typename F> | |
32 inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output); | |
33 | |
34 namespace internal { | 22 namespace internal { |
35 | 23 |
24 // The ArraySerializer template contains static methods for serializing |Array|s | |
25 // of various types. These methods include: | |
26 // * size_t GetSerializedSize(..) | |
27 // Computes the size of the serialized version of the |Array|. | |
28 // * void SerializeElementsWithIterator(..) | |
29 // Takes an iterator and |num_elements| representing an |Array| (or | |
30 // possibly a |Map|), and serializes it. | |
31 // * void SerializeElements(..) | |
32 // Takes an |Array| directly and serializes it. This usually calls into | |
33 // SerializeElementsWithIterator(), except for an |Array| of PODs which | |
34 // will directly memcpy the PODs as an optimization. | |
36 template <typename E, | 35 template <typename E, |
37 typename F, | 36 typename F, |
38 bool is_union = | 37 bool is_union = |
39 IsUnionDataType<typename RemovePointer<F>::type>::value> | 38 IsUnionDataType<typename RemovePointer<F>::type>::value> |
40 struct ArraySerializer; | 39 struct ArraySerializer; |
41 | 40 |
42 // Handles serialization and deserialization of arrays of pod types. | 41 // Handles serialization and deserialization of arrays of pod types. |
43 template <typename E, typename F> | 42 template <typename E, typename F> |
44 struct ArraySerializer<E, F, false> { | 43 struct ArraySerializer<E, F, false> { |
45 static_assert(sizeof(E) == sizeof(F), "Incorrect array serializer"); | 44 static_assert(sizeof(E) == sizeof(F), "Incorrect array serializer"); |
46 static size_t GetSerializedSize(const Array<E>& input) { | 45 static size_t GetSerializedSize(const Array<E>& input) { |
47 return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E)); | 46 return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E)); |
48 } | 47 } |
49 | 48 |
50 static void SerializeElements(Array<E> input, | 49 template <typename Iterator> |
50 static void SerializeElementsWithIterator( | |
51 Iterator it, | |
52 size_t num_elements, | |
53 Buffer* buf, | |
54 Array_Data<F>* output, | |
55 const ArrayValidateParams* validate_params) { | |
56 MOJO_DCHECK(!validate_params->element_is_nullable) | |
57 << "Primitive type should be non-nullable"; | |
58 MOJO_DCHECK(!validate_params->element_validate_params) | |
59 << "Primitive type should not have array validate params"; | |
60 if (num_elements) { | |
viettrungluu
2015/09/23 23:20:24
This seems redundant.
vardhan
2015/09/25 19:33:05
oops
| |
61 for (size_t i = 0; i < num_elements; ++i, ++it) { | |
viettrungluu
2015/09/23 23:20:24
nit: For consistency with other stuff in this file
vardhan
2015/09/25 19:33:05
Done.
| |
62 output->at(i) = *it; | |
63 } | |
64 } | |
65 } | |
66 | |
67 // We can optimize serializing PODs by |memcpy|ing directly. | |
68 static void SerializeElements(Array<E>* input, | |
51 Buffer* buf, | 69 Buffer* buf, |
52 Array_Data<F>* output, | 70 Array_Data<F>* output, |
53 const ArrayValidateParams* validate_params) { | 71 const ArrayValidateParams* validate_params) { |
54 MOJO_DCHECK(!validate_params->element_is_nullable) | 72 MOJO_DCHECK(!validate_params->element_is_nullable) |
55 << "Primitive type should be non-nullable"; | 73 << "Primitive type should be non-nullable"; |
56 MOJO_DCHECK(!validate_params->element_validate_params) | 74 MOJO_DCHECK(!validate_params->element_validate_params) |
57 << "Primitive type should not have array validate params"; | 75 << "Primitive type should not have array validate params"; |
76 if (input->size()) { | |
viettrungluu
2015/09/23 23:20:24
Assuming that output->storage() and &input->storag
vardhan
2015/09/25 19:33:05
output->storage() could point to memory we shouldn
| |
77 memcpy(output->storage(), &input->storage()[0], | |
78 input->size() * sizeof(E)); | |
79 } | |
80 } | |
58 | 81 |
59 if (input.size()) | |
60 memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E)); | |
61 } | |
62 static void DeserializeElements(Array_Data<F>* input, Array<E>* output) { | 82 static void DeserializeElements(Array_Data<F>* input, Array<E>* output) { |
63 std::vector<E> result(input->size()); | 83 std::vector<E> result(input->size()); |
64 if (input->size()) | 84 if (input->size()) |
65 memcpy(&result[0], input->storage(), input->size() * sizeof(E)); | 85 memcpy(&result[0], input->storage(), input->size() * sizeof(E)); |
66 output->Swap(&result); | 86 output->Swap(&result); |
67 } | 87 } |
68 }; | 88 }; |
69 | 89 |
70 // Serializes and deserializes arrays of bools. | 90 // Serializes and deserializes arrays of bools. |
71 template <> | 91 template <> |
72 struct ArraySerializer<bool, bool, false> { | 92 struct ArraySerializer<bool, bool, false> { |
73 static size_t GetSerializedSize(const Array<bool>& input) { | 93 static size_t GetSerializedSize(const Array<bool>& input) { |
74 return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8); | 94 return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8); |
75 } | 95 } |
76 | 96 |
77 static void SerializeElements(Array<bool> input, | 97 template <typename Iterator> |
78 Buffer* buf, | 98 static void SerializeElementsWithIterator( |
79 Array_Data<bool>* output, | 99 Iterator it, |
80 const ArrayValidateParams* validate_params) { | 100 size_t num_elements, |
101 Buffer* buf, | |
102 Array_Data<bool>* output, | |
103 const ArrayValidateParams* validate_params) { | |
81 MOJO_DCHECK(!validate_params->element_is_nullable) | 104 MOJO_DCHECK(!validate_params->element_is_nullable) |
82 << "Primitive type should be non-nullable"; | 105 << "Primitive type should be non-nullable"; |
83 MOJO_DCHECK(!validate_params->element_validate_params) | 106 MOJO_DCHECK(!validate_params->element_validate_params) |
84 << "Primitive type should not have array validate params"; | 107 << "Primitive type should not have array validate params"; |
85 | 108 |
86 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | 109 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? |
87 for (size_t i = 0; i < input.size(); ++i) | 110 for (size_t i = 0; i < num_elements; ++i, ++it) { |
viettrungluu
2015/09/23 23:20:24
Omit {}.
(Probably do so elsewhere too.)
vardhan
2015/09/25 19:33:05
Done.
| |
88 output->at(i) = input[i]; | 111 output->at(i) = *it; |
112 } | |
89 } | 113 } |
114 | |
115 static void SerializeElements(Array<bool>* input, | |
116 Buffer* buf, | |
117 Array_Data<bool>* output, | |
118 const ArrayValidateParams* validate_params) { | |
119 SerializeElementsWithIterator(input->begin(), input->size(), buf, output, | |
120 validate_params); | |
121 } | |
122 | |
90 static void DeserializeElements(Array_Data<bool>* input, | 123 static void DeserializeElements(Array_Data<bool>* input, |
91 Array<bool>* output) { | 124 Array<bool>* output) { |
92 Array<bool> result(input->size()); | 125 Array<bool> result(input->size()); |
93 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | 126 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? |
94 for (size_t i = 0; i < input->size(); ++i) | 127 for (size_t i = 0; i < input->size(); ++i) |
95 result.at(i) = input->at(i); | 128 result.at(i) = input->at(i); |
96 output->Swap(&result); | 129 output->Swap(&result); |
97 } | 130 } |
98 }; | 131 }; |
99 | 132 |
100 // Serializes and deserializes arrays of handles. | 133 // Serializes and deserializes arrays of handles. |
101 template <typename H> | 134 template <typename H> |
102 struct ArraySerializer<ScopedHandleBase<H>, H, false> { | 135 struct ArraySerializer<ScopedHandleBase<H>, H, false> { |
103 static size_t GetSerializedSize(const Array<ScopedHandleBase<H>>& input) { | 136 static size_t GetSerializedSize(const Array<ScopedHandleBase<H>>& input) { |
104 return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H)); | 137 return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H)); |
105 } | 138 } |
106 | 139 |
107 static void SerializeElements(Array<ScopedHandleBase<H>> input, | 140 template <typename Iterator> |
108 Buffer* buf, | 141 static void SerializeElementsWithIterator( |
109 Array_Data<H>* output, | 142 Iterator it, |
110 const ArrayValidateParams* validate_params) { | 143 size_t num_elements, |
144 Buffer* buf, | |
145 Array_Data<H>* output, | |
146 const ArrayValidateParams* validate_params) { | |
111 MOJO_DCHECK(!validate_params->element_validate_params) | 147 MOJO_DCHECK(!validate_params->element_validate_params) |
112 << "Handle type should not have array validate params"; | 148 << "Handle type should not have array validate params"; |
113 | 149 |
114 for (size_t i = 0; i < input.size(); ++i) { | 150 for (size_t i = 0; i < num_elements; ++i, ++it) { |
115 output->at(i) = input[i].release(); // Transfer ownership of the handle. | 151 // Transfer ownership of the handle. |
152 output->at(i) = (*it).release(); | |
116 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 153 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
117 !validate_params->element_is_nullable && !output->at(i).is_valid(), | 154 !validate_params->element_is_nullable && !output->at(i).is_valid(), |
118 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, | 155 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, |
119 MakeMessageWithArrayIndex( | 156 MakeMessageWithArrayIndex( |
120 "invalid handle in array expecting valid handles", input.size(), | 157 "invalid handle in array expecting valid handles", num_elements, |
121 i)); | 158 i)); |
122 } | 159 } |
123 } | 160 } |
161 | |
162 static void SerializeElements(Array<ScopedHandleBase<H>>* input, | |
163 Buffer* buf, | |
164 Array_Data<H>* output, | |
165 const ArrayValidateParams* validate_params) { | |
166 SerializeElementsWithIterator(input->begin(), input->size(), buf, output, | |
167 validate_params); | |
168 } | |
169 | |
124 static void DeserializeElements(Array_Data<H>* input, | 170 static void DeserializeElements(Array_Data<H>* input, |
125 Array<ScopedHandleBase<H>>* output) { | 171 Array<ScopedHandleBase<H>>* output) { |
126 Array<ScopedHandleBase<H>> result(input->size()); | 172 Array<ScopedHandleBase<H>> result(input->size()); |
127 for (size_t i = 0; i < input->size(); ++i) | 173 for (size_t i = 0; i < input->size(); ++i) |
128 result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i))); | 174 result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i))); |
129 output->Swap(&result); | 175 output->Swap(&result); |
130 } | 176 } |
131 }; | 177 }; |
132 | 178 |
133 // This template must only apply to pointer mojo entity (structs and arrays). | 179 // SerializeCaller template is used by |ArraySerializer| to dispatch a serialize |
134 // This is done by ensuring that WrapperTraits<S>::DataType is a pointer. | 180 // call on a non-POD type. This template is defined outside |ArraySerializer| |
181 // since you cannot specialize a struct within a class definition. | |
182 template <typename T> | |
183 struct SerializeCaller { | |
184 static void Run(T* input, | |
185 Buffer* buf, | |
186 typename WrapperTraits<T>::DataType* output, | |
187 const ArrayValidateParams* validate_params) { | |
188 MOJO_DCHECK(!validate_params) | |
189 << "Struct type should not have array validate params"; | |
190 Serialize_(UnwrapStructPtr<T>::value(*input), buf, output); | |
191 } | |
192 }; | |
193 | |
194 template <> | |
195 struct SerializeCaller<String> { | |
196 static void Run(const String* input, | |
197 Buffer* buf, | |
198 String_Data** output, | |
199 const ArrayValidateParams* validate_params) { | |
200 MOJO_DCHECK(validate_params && !validate_params->element_validate_params && | |
201 !validate_params->element_is_nullable && | |
202 validate_params->expected_num_elements == 0) | |
203 << "String type has unexpected array validate params"; | |
204 SerializeString_(*input, buf, output); | |
205 } | |
206 }; | |
207 | |
208 template <typename T> | |
209 struct SerializeCaller<Array<T>> { | |
210 static void Run(Array<T>* input, | |
211 Buffer* buf, | |
212 typename Array<T>::Data_** output, | |
213 const ArrayValidateParams* validate_params) { | |
214 SerializeArray_(input, buf, output, validate_params); | |
215 } | |
216 }; | |
217 | |
218 template <typename Key, typename Value> | |
219 struct SerializeCaller<Map<Key, Value>> { | |
220 static void Run(Map<Key, Value>* input, | |
221 Buffer* buf, | |
222 typename Map<Key, Value>::Data_** output, | |
223 const ArrayValidateParams* validate_params) { | |
224 SerializeMap_(input, buf, output, validate_params); | |
225 } | |
226 }; | |
227 | |
228 template <typename T, | |
229 bool IsStructPtr = IsSpecializationOf<StructPtr, T>::value || | |
230 IsSpecializationOf<InlinedStructPtr, T>::value> | |
231 struct DeserializeCaller; | |
232 | |
233 template <typename T> | |
234 struct DeserializeCaller<T, false> { | |
235 static void Run(typename WrapperTraits<T>::DataType input, T* output) { | |
236 Deserialize_(input, output); | |
237 } | |
238 }; | |
239 | |
240 template <typename T> | |
241 struct DeserializeCaller<T, true> { | |
242 static void Run(typename WrapperTraits<T>::DataType input, T* output) { | |
243 // Since Deserialize_ takes in a |Struct*| (not |StructPtr|), we need to | |
244 // initialize the |StructPtr| here before deserializing into its underlying | |
245 // data. | |
246 // TODO(vardhan): Either all containers, or just Deserialize_(), should | |
247 // support taking in an allocator. | |
248 using UnwrapedStructType = typename RemoveStructPtr<T>::type; | |
249 *output = UnwrapedStructType::New(); | |
250 Deserialize_(input, output->get()); | |
251 } | |
252 }; | |
253 | |
254 // This template must only apply to pointer mojo entity (structs, arrays, | |
255 // strings). This is done by ensuring that WrapperTraits<S>::DataType is a | |
256 // pointer. | |
135 template <typename S> | 257 template <typename S> |
136 struct ArraySerializer< | 258 struct ArraySerializer< |
137 S, | 259 S, |
138 typename EnableIf<IsPointer<typename WrapperTraits<S>::DataType>::value, | 260 typename EnableIf<IsPointer<typename WrapperTraits<S>::DataType>::value, |
139 typename WrapperTraits<S>::DataType>::type, | 261 typename WrapperTraits<S>::DataType>::type, |
140 false> { | 262 false> { |
141 typedef | 263 typedef |
142 typename RemovePointer<typename WrapperTraits<S>::DataType>::type S_Data; | 264 typename RemovePointer<typename WrapperTraits<S>::DataType>::type S_Data; |
143 static size_t GetSerializedSize(const Array<S>& input) { | 265 static size_t GetSerializedSize(const Array<S>& input) { |
144 size_t size = sizeof(Array_Data<S_Data*>) + | 266 size_t size = sizeof(Array_Data<S_Data*>) + |
145 input.size() * sizeof(StructPointer<S_Data>); | 267 input.size() * sizeof(StructPointer<S_Data>); |
146 for (size_t i = 0; i < input.size(); ++i) | 268 for (size_t i = 0; i < input.size(); ++i) |
147 size += GetSerializedSize_(input[i]); | 269 size += GetSerializedSize_(*(UnwrapConstStructPtr<S>::value(input[i]))); |
148 return size; | 270 return size; |
149 } | 271 } |
150 | 272 |
151 static void SerializeElements(Array<S> input, | 273 template <typename Iterator> |
152 Buffer* buf, | 274 static void SerializeElementsWithIterator( |
153 Array_Data<S_Data*>* output, | 275 Iterator it, |
154 const ArrayValidateParams* validate_params) { | 276 size_t num_elements, |
155 for (size_t i = 0; i < input.size(); ++i) { | 277 Buffer* buf, |
278 Array_Data<S_Data*>* output, | |
279 const ArrayValidateParams* validate_params) { | |
280 for (size_t i = 0; i < num_elements; ++i, ++it) { | |
156 S_Data* element; | 281 S_Data* element; |
157 SerializeCaller<S>::Run(input[i].Pass(), buf, &element, | 282 SerializeCaller<S>::Run(&(*it), buf, &element, |
158 validate_params->element_validate_params); | 283 validate_params->element_validate_params); |
159 output->at(i) = element; | 284 output->at(i) = element; |
160 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 285 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
161 !validate_params->element_is_nullable && !element, | 286 !validate_params->element_is_nullable && !element, |
162 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 287 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
163 MakeMessageWithArrayIndex("null in array expecting valid pointers", | 288 MakeMessageWithArrayIndex("null in array expecting valid pointers", |
164 input.size(), i)); | 289 num_elements, i)); |
165 } | 290 } |
166 } | 291 } |
292 | |
293 static void SerializeElements(Array<S>* input, | |
294 Buffer* buf, | |
295 Array_Data<S_Data*>* output, | |
296 const ArrayValidateParams* validate_params) { | |
297 SerializeElementsWithIterator(input->begin(), input->size(), buf, output, | |
298 validate_params); | |
299 } | |
300 | |
167 static void DeserializeElements(Array_Data<S_Data*>* input, | 301 static void DeserializeElements(Array_Data<S_Data*>* input, |
168 Array<S>* output) { | 302 Array<S>* output) { |
169 Array<S> result(input->size()); | 303 Array<S> result(input->size()); |
170 for (size_t i = 0; i < input->size(); ++i) { | 304 for (size_t i = 0; i < input->size(); ++i) { |
171 Deserialize_(input->at(i), &result[i]); | 305 DeserializeCaller<S>::Run(input->at(i), &result[i]); |
172 } | 306 } |
173 output->Swap(&result); | 307 output->Swap(&result); |
174 } | 308 } |
175 | |
176 private: | |
177 template <typename T> | |
178 struct SerializeCaller { | |
179 static void Run(T input, | |
180 Buffer* buf, | |
181 typename WrapperTraits<T>::DataType* output, | |
182 const ArrayValidateParams* validate_params) { | |
183 MOJO_DCHECK(!validate_params) | |
184 << "Struct type should not have array validate params"; | |
185 | |
186 Serialize_(input.Pass(), buf, output); | |
187 } | |
188 }; | |
189 | |
190 template <typename T> | |
191 struct SerializeCaller<Array<T>> { | |
192 static void Run(Array<T> input, | |
193 Buffer* buf, | |
194 typename Array<T>::Data_** output, | |
195 const ArrayValidateParams* validate_params) { | |
196 SerializeArray_(input.Pass(), buf, output, validate_params); | |
197 } | |
198 }; | |
199 | |
200 template <typename T, typename U> | |
201 struct SerializeCaller<Map<T, U>> { | |
202 static void Run(Map<T, U> input, | |
203 Buffer* buf, | |
204 typename Map<T, U>::Data_** output, | |
205 const ArrayValidateParams* validate_params) { | |
206 SerializeMap_(input.Pass(), buf, output, validate_params); | |
207 } | |
208 }; | |
209 }; | 309 }; |
210 | 310 |
211 // Handles serialization and deserialization of arrays of unions. | 311 // Handles serialization and deserialization of arrays of unions. |
212 template <typename U, typename U_Data> | 312 template <typename U, typename U_Data> |
213 struct ArraySerializer<U, U_Data, true> { | 313 struct ArraySerializer<U, U_Data, true> { |
214 static size_t GetSerializedSize(const Array<U>& input) { | 314 static size_t GetSerializedSize(const Array<U>& input) { |
215 size_t size = sizeof(Array_Data<U_Data>); | 315 size_t size = sizeof(Array_Data<U_Data>); |
216 for (size_t i = 0; i < input.size(); ++i) { | 316 for (size_t i = 0; i < input.size(); ++i) { |
217 // GetSerializedSize_ will account for both the data in the union and the | 317 // GetSerializedSize_ will account for both the data in the union and the |
218 // space in the array used to hold the union. | 318 // space in the array used to hold the union. |
219 size += GetSerializedSize_(input[i], false); | 319 size += GetSerializedSize_(input[i], false); |
220 } | 320 } |
221 return size; | 321 return size; |
222 } | 322 } |
223 | 323 |
224 static void SerializeElements(Array<U> input, | 324 template <typename Iterator> |
225 Buffer* buf, | 325 static void SerializeElementsWithIterator( |
226 Array_Data<U_Data>* output, | 326 Iterator it, |
227 const ArrayValidateParams* validate_params) { | 327 size_t num_elements, |
228 for (size_t i = 0; i < input.size(); ++i) { | 328 Buffer* buf, |
329 Array_Data<U_Data>* output, | |
330 const ArrayValidateParams* validate_params) { | |
331 for (size_t i = 0; i < num_elements; ++i, ++it) { | |
229 U_Data* result = output->storage() + i; | 332 U_Data* result = output->storage() + i; |
230 SerializeUnion_(input[i].Pass(), buf, &result, true); | 333 SerializeUnion_((*it).get(), buf, &result, true); |
231 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 334 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
232 !validate_params->element_is_nullable && output->at(i).is_null(), | 335 !validate_params->element_is_nullable && output->at(i).is_null(), |
233 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 336 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
234 MakeMessageWithArrayIndex("null in array expecting valid unions", | 337 MakeMessageWithArrayIndex("null in array expecting valid unions", |
235 input.size(), i)); | 338 num_elements, i)); |
236 } | 339 } |
237 } | 340 } |
238 | 341 |
342 static void SerializeElements(Array<U>* input, | |
343 Buffer* buf, | |
344 Array_Data<U_Data>* output, | |
345 const ArrayValidateParams* validate_params) { | |
346 SerializeElementsWithIterator(input->begin(), input->size(), buf, output, | |
347 validate_params); | |
348 } | |
349 | |
239 static void DeserializeElements(Array_Data<U_Data>* input, Array<U>* output) { | 350 static void DeserializeElements(Array_Data<U_Data>* input, Array<U>* output) { |
240 Array<U> result(input->size()); | 351 Array<U> result(input->size()); |
241 for (size_t i = 0; i < input->size(); ++i) { | 352 for (size_t i = 0; i < input->size(); ++i) { |
242 Deserialize_(&input->at(i), &result[i]); | 353 auto& elem = input->at(i); |
354 if (!elem.is_null()) { | |
355 using UnwrapedUnionType = typename RemoveStructPtr<U>::type; | |
356 result[i] = UnwrapedUnionType::New(); | |
357 Deserialize_(&elem, result[i].get()); | |
358 } | |
243 } | 359 } |
244 output->Swap(&result); | 360 output->Swap(&result); |
245 } | 361 } |
246 }; | 362 }; |
247 | |
248 // Handles serialization and deserialization of arrays of strings. | |
249 template <> | |
250 struct ArraySerializer<String, String_Data*> { | |
251 static size_t GetSerializedSize(const Array<String>& input) { | |
252 size_t size = | |
253 sizeof(Array_Data<String_Data*>) + input.size() * sizeof(StringPointer); | |
254 for (size_t i = 0; i < input.size(); ++i) | |
255 size += GetSerializedSize_(input[i]); | |
256 return size; | |
257 } | |
258 | |
259 static void SerializeElements(Array<String> input, | |
260 Buffer* buf, | |
261 Array_Data<String_Data*>* output, | |
262 const ArrayValidateParams* validate_params) { | |
263 MOJO_DCHECK( | |
264 validate_params->element_validate_params && | |
265 !validate_params->element_validate_params->element_validate_params && | |
266 !validate_params->element_validate_params->element_is_nullable && | |
267 validate_params->element_validate_params->expected_num_elements == 0) | |
268 << "String type has unexpected array validate params"; | |
269 | |
270 for (size_t i = 0; i < input.size(); ++i) { | |
271 String_Data* element; | |
272 Serialize_(input[i], buf, &element); | |
273 output->at(i) = element; | |
274 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
275 !validate_params->element_is_nullable && !element, | |
276 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | |
277 MakeMessageWithArrayIndex("null in array expecting valid strings", | |
278 input.size(), i)); | |
279 } | |
280 } | |
281 static void DeserializeElements(Array_Data<String_Data*>* input, | |
282 Array<String>* output) { | |
283 Array<String> result(input->size()); | |
284 for (size_t i = 0; i < input->size(); ++i) | |
285 Deserialize_(input->at(i), &result[i]); | |
286 output->Swap(&result); | |
287 } | |
288 }; | |
289 | 363 |
290 } // namespace internal | 364 } // namespace internal |
291 | 365 |
292 template <typename E> | 366 template <typename E> |
293 inline size_t GetSerializedSize_(const Array<E>& input) { | 367 inline size_t GetSerializedSize_(const Array<E>& input) { |
294 if (!input) | 368 if (!input) |
295 return 0; | 369 return 0; |
296 typedef typename internal::WrapperTraits<E>::DataType F; | 370 typedef typename internal::WrapperTraits<E>::DataType F; |
297 return internal::ArraySerializer<E, F>::GetSerializedSize(input); | 371 return internal::ArraySerializer<E, F>::GetSerializedSize(input); |
298 } | 372 } |
299 | 373 |
300 template <typename E, typename F> | 374 template <typename E, typename F> |
301 inline void SerializeArray_( | 375 inline void SerializeArray_( |
302 Array<E> input, | 376 Array<E>* input, |
303 internal::Buffer* buf, | 377 internal::Buffer* buf, |
304 internal::Array_Data<F>** output, | 378 internal::Array_Data<F>** output, |
305 const internal::ArrayValidateParams* validate_params) { | 379 const internal::ArrayValidateParams* validate_params) { |
306 if (input) { | 380 if (input && *input) { |
307 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 381 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
308 validate_params->expected_num_elements != 0 && | 382 validate_params->expected_num_elements != 0 && |
309 input.size() != validate_params->expected_num_elements, | 383 input->size() != validate_params->expected_num_elements, |
310 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, | 384 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, |
311 internal::MakeMessageWithExpectedArraySize( | 385 internal::MakeMessageWithExpectedArraySize( |
312 "fixed-size array has wrong number of elements", input.size(), | 386 "fixed-size array has wrong number of elements", input->size(), |
313 validate_params->expected_num_elements)); | 387 validate_params->expected_num_elements)); |
314 | 388 |
315 internal::Array_Data<F>* result = | 389 internal::Array_Data<F>* result = |
316 internal::Array_Data<F>::New(input.size(), buf); | 390 internal::Array_Data<F>::New(input->size(), buf); |
317 if (result) { | 391 if (result) { |
318 internal::ArraySerializer<E, F>::SerializeElements( | 392 internal::ArraySerializer<E, F>::SerializeElements(input, buf, result, |
319 internal::Forward(input), buf, result, validate_params); | 393 validate_params); |
320 } | 394 } |
321 *output = result; | 395 *output = result; |
322 } else { | 396 } else { |
323 *output = nullptr; | 397 *output = nullptr; |
324 } | 398 } |
325 } | 399 } |
326 | 400 |
327 template <typename E, typename F> | 401 template <typename E, typename F> |
328 inline void Deserialize_(internal::Array_Data<F>* input, Array<E>* output) { | 402 inline void Deserialize_(internal::Array_Data<F>* input, Array<E>* output) { |
329 if (input) { | 403 if (input) { |
330 internal::ArraySerializer<E, F>::DeserializeElements(input, output); | 404 internal::ArraySerializer<E, F>::DeserializeElements(input, output); |
331 } else { | 405 } else { |
332 output->reset(); | 406 output->reset(); |
333 } | 407 } |
334 } | 408 } |
335 | 409 |
336 } // namespace mojo | 410 } // namespace mojo |
337 | 411 |
338 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | 412 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ |
OLD | NEW |