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