OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | |
7 | |
8 #include <string.h> // For |memcpy()|. | |
9 | |
10 #include <vector> | |
11 | |
12 #include "mojo/public/c/system/macros.h" | |
13 #include "mojo/public/cpp/bindings/lib/array_internal.h" | |
14 #include "mojo/public/cpp/bindings/lib/map_serialization.h" | |
15 #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/validation_errors.h" | |
18 | |
19 namespace mojo { | |
20 | |
21 template <typename E> | |
22 inline size_t GetSerializedSize_(const Array<E>& input); | |
23 | |
24 // Because ValidateParams requires explicit argument specification, the | |
25 // argument-dependent loopup technique used to omit namespace when calling | |
26 // Serialize_() doesn't seem to work. Therefore, this function is named | |
27 // differently from those Serialize_() overloads. | |
28 template <typename ValidateParams, typename E, typename F> | |
29 inline void SerializeArray_(Array<E> input, | |
30 internal::Buffer* buf, | |
31 internal::Array_Data<F>** output); | |
32 | |
33 template <typename ValueValidateParams, | |
34 typename KeyWrapperType, | |
35 typename ValueWrapperType, | |
36 typename KeySerializationType, | |
37 typename ValueSerializationType> | |
38 inline void SerializeMap_( | |
39 Map<KeyWrapperType, ValueWrapperType> input, | |
40 internal::Buffer* buf, | |
41 internal::Map_Data<KeySerializationType, ValueSerializationType>** output); | |
42 | |
43 template <typename E, typename F> | |
44 inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output); | |
45 | |
46 namespace internal { | |
47 | |
48 template <typename E, typename F, bool move_only = IsMoveOnlyType<E>::value> | |
49 struct ArraySerializer; | |
50 | |
51 template <typename E, typename F> | |
52 struct ArraySerializer<E, F, false> { | |
53 static_assert(sizeof(E) == sizeof(F), "Incorrect array serializer"); | |
54 static size_t GetSerializedSize(const Array<E>& input) { | |
55 return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E)); | |
56 } | |
57 template <bool element_is_nullable, typename ElementValidateParams> | |
58 static void SerializeElements(Array<E> input, | |
59 Buffer* buf, | |
60 Array_Data<F>* output) { | |
61 static_assert(!element_is_nullable, | |
62 "Primitive type should be non-nullable"); | |
63 static_assert((IsSame<ElementValidateParams, NoValidateParams>::value), | |
64 "Primitive type should not have array validate params"); | |
65 | |
66 if (input.size()) | |
67 memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E)); | |
68 } | |
69 static void DeserializeElements(Array_Data<F>* input, Array<E>* output) { | |
70 std::vector<E> result(input->size()); | |
71 if (input->size()) | |
72 memcpy(&result[0], input->storage(), input->size() * sizeof(E)); | |
73 output->Swap(&result); | |
74 } | |
75 }; | |
76 | |
77 template <> | |
78 struct ArraySerializer<bool, bool, false> { | |
79 static size_t GetSerializedSize(const Array<bool>& input) { | |
80 return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8); | |
81 } | |
82 template <bool element_is_nullable, typename ElementValidateParams> | |
83 static void SerializeElements(Array<bool> input, | |
84 Buffer* buf, | |
85 Array_Data<bool>* output) { | |
86 static_assert(!element_is_nullable, | |
87 "Primitive type should be non-nullable"); | |
88 static_assert((IsSame<ElementValidateParams, NoValidateParams>::value), | |
89 "Primitive type should not have array validate params"); | |
90 | |
91 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | |
92 for (size_t i = 0; i < input.size(); ++i) | |
93 output->at(i) = input[i]; | |
94 } | |
95 static void DeserializeElements(Array_Data<bool>* input, | |
96 Array<bool>* output) { | |
97 Array<bool> result(input->size()); | |
98 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | |
99 for (size_t i = 0; i < input->size(); ++i) | |
100 result.at(i) = input->at(i); | |
101 output->Swap(&result); | |
102 } | |
103 }; | |
104 | |
105 template <typename H> | |
106 struct ArraySerializer<ScopedHandleBase<H>, H, true> { | |
107 static size_t GetSerializedSize(const Array<ScopedHandleBase<H>>& input) { | |
108 return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H)); | |
109 } | |
110 template <bool element_is_nullable, typename ElementValidateParams> | |
111 static void SerializeElements(Array<ScopedHandleBase<H>> input, | |
112 Buffer* buf, | |
113 Array_Data<H>* output) { | |
114 static_assert((IsSame<ElementValidateParams, NoValidateParams>::value), | |
115 "Handle type should not have array validate params"); | |
116 | |
117 for (size_t i = 0; i < input.size(); ++i) { | |
118 output->at(i) = input[i].release(); // Transfer ownership of the handle. | |
119 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
120 !element_is_nullable && !output->at(i).is_valid(), | |
121 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, | |
122 MakeMessageWithArrayIndex( | |
123 "invalid handle in array expecting valid handles", | |
124 input.size(), | |
125 i)); | |
126 } | |
127 } | |
128 static void DeserializeElements(Array_Data<H>* input, | |
129 Array<ScopedHandleBase<H>>* output) { | |
130 Array<ScopedHandleBase<H>> result(input->size()); | |
131 for (size_t i = 0; i < input->size(); ++i) | |
132 result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i))); | |
133 output->Swap(&result); | |
134 } | |
135 }; | |
136 | |
137 // This template must only apply to pointer mojo entity (structs and arrays). | |
138 // This is done by ensuring that WrapperTraits<S>::DataType is a pointer. | |
139 template <typename S> | |
140 struct ArraySerializer<S, | |
141 typename internal::EnableIf< | |
142 internal::IsPointer<typename internal::WrapperTraits< | |
143 S>::DataType>::value, | |
144 typename internal::WrapperTraits<S>::DataType>::type, | |
145 true> { | |
146 typedef typename internal::RemovePointer< | |
147 typename internal::WrapperTraits<S>::DataType>::type S_Data; | |
148 static size_t GetSerializedSize(const Array<S>& input) { | |
149 size_t size = sizeof(Array_Data<S_Data*>) + | |
150 input.size() * sizeof(internal::StructPointer<S_Data>); | |
151 for (size_t i = 0; i < input.size(); ++i) | |
152 size += GetSerializedSize_(input[i]); | |
153 return size; | |
154 } | |
155 template <bool element_is_nullable, typename ElementValidateParams> | |
156 static void SerializeElements(Array<S> input, | |
157 Buffer* buf, | |
158 Array_Data<S_Data*>* output) { | |
159 for (size_t i = 0; i < input.size(); ++i) { | |
160 S_Data* element; | |
161 SerializeCaller<S, ElementValidateParams>::Run( | |
162 input[i].Pass(), buf, &element); | |
163 output->at(i) = element; | |
164 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
165 !element_is_nullable && !element, | |
166 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | |
167 MakeMessageWithArrayIndex( | |
168 "null in array expecting valid pointers", input.size(), i)); | |
169 } | |
170 } | |
171 static void DeserializeElements(Array_Data<S_Data*>* input, | |
172 Array<S>* output) { | |
173 Array<S> result(input->size()); | |
174 for (size_t i = 0; i < input->size(); ++i) { | |
175 S element; | |
176 Deserialize_(input->at(i), &element); | |
177 result[i] = element.Pass(); | |
178 } | |
179 output->Swap(&result); | |
180 } | |
181 | |
182 private: | |
183 template <typename T, typename Params> | |
184 struct SerializeCaller { | |
185 static void Run(T input, | |
186 Buffer* buf, | |
187 typename internal::WrapperTraits<T>::DataType* output) { | |
188 static_assert((IsSame<Params, NoValidateParams>::value), | |
189 "Struct type should not have array validate params"); | |
190 | |
191 Serialize_(input.Pass(), buf, output); | |
192 } | |
193 }; | |
194 | |
195 template <typename T, typename Params> | |
196 struct SerializeCaller<Array<T>, Params> { | |
197 static void Run(Array<T> input, | |
198 Buffer* buf, | |
199 typename Array<T>::Data_** output) { | |
200 SerializeArray_<Params>(input.Pass(), buf, output); | |
201 } | |
202 }; | |
203 | |
204 template <typename T, typename U, typename Params> | |
205 struct SerializeCaller<Map<T, U>, Params> { | |
206 static void Run(Map<T, U> input, | |
207 Buffer* buf, | |
208 typename Map<T, U>::Data_** output) { | |
209 SerializeMap_<Params>(input.Pass(), buf, output); | |
210 } | |
211 }; | |
212 }; | |
213 | |
214 template <> | |
215 struct ArraySerializer<String, String_Data*, false> { | |
216 static size_t GetSerializedSize(const Array<String>& input) { | |
217 size_t size = sizeof(Array_Data<String_Data*>) + | |
218 input.size() * sizeof(internal::StringPointer); | |
219 for (size_t i = 0; i < input.size(); ++i) | |
220 size += GetSerializedSize_(input[i]); | |
221 return size; | |
222 } | |
223 template <bool element_is_nullable, typename ElementValidateParams> | |
224 static void SerializeElements(Array<String> input, | |
225 Buffer* buf, | |
226 Array_Data<String_Data*>* output) { | |
227 static_assert( | |
228 (IsSame<ElementValidateParams, | |
229 ArrayValidateParams<0, false, NoValidateParams>>::value), | |
230 "String type has unexpected array validate params"); | |
231 | |
232 for (size_t i = 0; i < input.size(); ++i) { | |
233 String_Data* element; | |
234 Serialize_(input[i], buf, &element); | |
235 output->at(i) = element; | |
236 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
237 !element_is_nullable && !element, | |
238 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | |
239 MakeMessageWithArrayIndex( | |
240 "null in array expecting valid strings", input.size(), i)); | |
241 } | |
242 } | |
243 static void DeserializeElements(Array_Data<String_Data*>* input, | |
244 Array<String>* output) { | |
245 Array<String> result(input->size()); | |
246 for (size_t i = 0; i < input->size(); ++i) | |
247 Deserialize_(input->at(i), &result[i]); | |
248 output->Swap(&result); | |
249 } | |
250 }; | |
251 | |
252 } // namespace internal | |
253 | |
254 template <typename E> | |
255 inline size_t GetSerializedSize_(const Array<E>& input) { | |
256 if (!input) | |
257 return 0; | |
258 typedef typename internal::WrapperTraits<E>::DataType F; | |
259 return internal::ArraySerializer<E, F>::GetSerializedSize(input); | |
260 } | |
261 | |
262 template <typename ValidateParams, typename E, typename F> | |
263 inline void SerializeArray_(Array<E> input, | |
264 internal::Buffer* buf, | |
265 internal::Array_Data<F>** output) { | |
266 if (input) { | |
267 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
268 ValidateParams::expected_num_elements != 0 && | |
269 input.size() != ValidateParams::expected_num_elements, | |
270 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, | |
271 internal::MakeMessageWithExpectedArraySize( | |
272 "fixed-size array has wrong number of elements", | |
273 input.size(), | |
274 ValidateParams::expected_num_elements)); | |
275 | |
276 internal::Array_Data<F>* result = | |
277 internal::Array_Data<F>::New(input.size(), buf); | |
278 if (result) { | |
279 internal::ArraySerializer<E, F>::template SerializeElements< | |
280 ValidateParams::element_is_nullable, | |
281 typename ValidateParams::ElementValidateParams>( | |
282 internal::Forward(input), buf, result); | |
283 } | |
284 *output = result; | |
285 } else { | |
286 *output = nullptr; | |
287 } | |
288 } | |
289 | |
290 template <typename E, typename F> | |
291 inline void Deserialize_(internal::Array_Data<F>* input, Array<E>* output) { | |
292 if (input) { | |
293 internal::ArraySerializer<E, F>::DeserializeElements(input, output); | |
294 } else { | |
295 output->reset(); | |
296 } | |
297 } | |
298 | |
299 } // namespace mojo | |
300 | |
301 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | |
OLD | NEW |