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