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.
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
8 #include <string.h> // For |memcpy()|.
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/string_serialization.h"
15 #include "mojo/public/cpp/bindings/lib/template_util.h"
16 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
21 inline size_t GetSerializedSize_(const Array
<E
>& input
);
23 // Because ValidateParams requires explicit argument specification, the
24 // argument-dependent loopup technique used to omit namespace when calling
25 // Serialize_() doesn't seem to work. Therefore, this function is named
26 // differently from those Serialize_() overloads.
27 template <typename ValidateParams
, typename E
, typename F
>
28 inline void SerializeArray_(Array
<E
> input
, internal::Buffer
* buf
,
29 internal::Array_Data
<F
>** output
);
31 template <typename E
, typename F
>
32 inline void Deserialize_(internal::Array_Data
<F
>* data
, Array
<E
>* output
);
36 template <typename E
, typename F
, bool move_only
= IsMoveOnlyType
<E
>::value
>
37 struct ArraySerializer
;
39 template <typename E
, typename F
> struct ArraySerializer
<E
, F
, false> {
40 MOJO_COMPILE_ASSERT(sizeof(E
) == sizeof(F
), wrong_array_serializer
);
41 static size_t GetSerializedSize(const Array
<E
>& input
) {
42 return sizeof(Array_Data
<F
>) + Align(input
.size() * sizeof(E
));
44 template <bool element_is_nullable
, typename ElementValidateParams
>
45 static void SerializeElements(
46 Array
<E
> input
, Buffer
* buf
, Array_Data
<F
>* output
) {
47 MOJO_COMPILE_ASSERT(!element_is_nullable
,
48 Primitive_type_should_be_non_nullable
);
50 (IsSame
<ElementValidateParams
, NoValidateParams
>::value
),
51 Primitive_type_should_not_have_array_validate_params
);
53 memcpy(output
->storage(), &input
.storage()[0], input
.size() * sizeof(E
));
55 static void DeserializeElements(
56 Array_Data
<F
>* input
, Array
<E
>* output
) {
57 std::vector
<E
> result(input
->size());
58 memcpy(&result
[0], input
->storage(), input
->size() * sizeof(E
));
59 output
->Swap(&result
);
63 template <> struct ArraySerializer
<bool, bool, false> {
64 static size_t GetSerializedSize(const Array
<bool>& input
) {
65 return sizeof(Array_Data
<bool>) + Align((input
.size() + 7) / 8);
67 template <bool element_is_nullable
, typename ElementValidateParams
>
68 static void SerializeElements(
69 Array
<bool> input
, Buffer
* buf
, Array_Data
<bool>* output
) {
70 MOJO_COMPILE_ASSERT(!element_is_nullable
,
71 Primitive_type_should_be_non_nullable
);
73 (IsSame
<ElementValidateParams
, NoValidateParams
>::value
),
74 Primitive_type_should_not_have_array_validate_params
);
76 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
77 for (size_t i
= 0; i
< input
.size(); ++i
)
78 output
->at(i
) = input
[i
];
80 static void DeserializeElements(
81 Array_Data
<bool>* input
, Array
<bool>* output
) {
82 Array
<bool> result(input
->size());
83 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
84 for (size_t i
= 0; i
< input
->size(); ++i
)
85 result
.at(i
) = input
->at(i
);
86 output
->Swap(&result
);
90 template <typename H
> struct ArraySerializer
<ScopedHandleBase
<H
>, H
, true> {
91 static size_t GetSerializedSize(const Array
<ScopedHandleBase
<H
> >& input
) {
92 return sizeof(Array_Data
<H
>) + Align(input
.size() * sizeof(H
));
94 template <bool element_is_nullable
, typename ElementValidateParams
>
95 static void SerializeElements(Array
<ScopedHandleBase
<H
> > input
,
97 Array_Data
<H
>* output
) {
99 (IsSame
<ElementValidateParams
, NoValidateParams
>::value
),
100 Handle_type_should_not_have_array_validate_params
);
102 for (size_t i
= 0; i
< input
.size(); ++i
) {
103 output
->at(i
) = input
[i
].release(); // Transfer ownership of the handle.
104 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
105 !element_is_nullable
&& !output
->at(i
).is_valid(),
106 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE
,
107 MakeMessageWithArrayIndex(
108 "invalid handle in array expecting valid handles",
112 static void DeserializeElements(
113 Array_Data
<H
>* input
, Array
<ScopedHandleBase
<H
> >* output
) {
114 Array
<ScopedHandleBase
<H
> > result(input
->size());
115 for (size_t i
= 0; i
< input
->size(); ++i
)
116 result
.at(i
) = MakeScopedHandle(FetchAndReset(&input
->at(i
)));
117 output
->Swap(&result
);
121 template <typename S
> struct ArraySerializer
<S
, typename
S::Data_
*, true> {
122 static size_t GetSerializedSize(const Array
<S
>& input
) {
123 size_t size
= sizeof(Array_Data
<typename
S::Data_
*>) +
124 input
.size() * sizeof(internal::StructPointer
<typename
S::Data_
>);
125 for (size_t i
= 0; i
< input
.size(); ++i
)
126 size
+= GetSerializedSize_(input
[i
]);
129 template <bool element_is_nullable
, typename ElementValidateParams
>
130 static void SerializeElements(Array
<S
> input
,
132 Array_Data
<typename
S::Data_
*>* output
) {
133 for (size_t i
= 0; i
< input
.size(); ++i
) {
134 typename
S::Data_
* element
;
135 SerializeCaller
<S
, ElementValidateParams
>::Run(
136 input
[i
].Pass(), buf
, &element
);
137 output
->at(i
) = element
;
138 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
139 !element_is_nullable
&& !element
,
140 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER
,
141 MakeMessageWithArrayIndex(
142 "null in array expecting valid pointers", input
.size(), i
));
145 static void DeserializeElements(
146 Array_Data
<typename
S::Data_
*>* input
, Array
<S
>* output
) {
147 Array
<S
> result(input
->size());
148 for (size_t i
= 0; i
< input
->size(); ++i
) {
150 Deserialize_(input
->at(i
), &element
);
151 result
[i
] = element
.Pass();
153 output
->Swap(&result
);
157 template <typename T
, typename Params
>
158 struct SerializeCaller
{
159 static void Run(T input
, Buffer
* buf
, typename
T::Data_
** output
) {
160 MOJO_COMPILE_ASSERT((IsSame
<Params
, NoValidateParams
>::value
),
161 Struct_type_should_not_have_array_validate_params
);
163 Serialize_(input
.Pass(), buf
, output
);
167 template <typename T
, typename Params
>
168 struct SerializeCaller
<Array
<T
>, Params
> {
169 static void Run(Array
<T
> input
,
171 typename Array
<T
>::Data_
** output
) {
172 SerializeArray_
<Params
>(input
.Pass(), buf
, output
);
177 template <> struct ArraySerializer
<String
, String_Data
*, false> {
178 static size_t GetSerializedSize(const Array
<String
>& input
) {
179 size_t size
= sizeof(Array_Data
<String_Data
*>) +
180 input
.size() * sizeof(internal::StringPointer
);
181 for (size_t i
= 0; i
< input
.size(); ++i
)
182 size
+= GetSerializedSize_(input
[i
]);
185 template <bool element_is_nullable
, typename ElementValidateParams
>
186 static void SerializeElements(
189 Array_Data
<String_Data
*>* output
) {
191 (IsSame
<ElementValidateParams
,
192 ArrayValidateParams
<0, false, NoValidateParams
> >::value
),
193 String_type_has_unexpected_array_validate_params
);
195 for (size_t i
= 0; i
< input
.size(); ++i
) {
196 String_Data
* element
;
197 Serialize_(input
[i
], buf
, &element
);
198 output
->at(i
) = element
;
199 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
200 !element_is_nullable
&& !element
,
201 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER
,
202 MakeMessageWithArrayIndex(
203 "null in array expecting valid strings", input
.size(), i
));
206 static void DeserializeElements(
207 Array_Data
<String_Data
*>* input
, Array
<String
>* output
) {
208 Array
<String
> result(input
->size());
209 for (size_t i
= 0; i
< input
->size(); ++i
)
210 Deserialize_(input
->at(i
), &result
[i
]);
211 output
->Swap(&result
);
215 } // namespace internal
217 template <typename E
>
218 inline size_t GetSerializedSize_(const Array
<E
>& input
) {
221 typedef typename
internal::WrapperTraits
<E
>::DataType F
;
222 return internal::ArraySerializer
<E
, F
>::GetSerializedSize(input
);
225 template <typename ValidateParams
, typename E
, typename F
>
226 inline void SerializeArray_(Array
<E
> input
, internal::Buffer
* buf
,
227 internal::Array_Data
<F
>** output
) {
229 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
230 ValidateParams::expected_num_elements
!= 0 &&
231 input
.size() != ValidateParams::expected_num_elements
,
232 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER
,
233 internal::MakeMessageWithExpectedArraySize(
234 "fixed-size array has wrong number of elements",
235 input
.size(), ValidateParams::expected_num_elements
));
237 internal::Array_Data
<F
>* result
=
238 internal::Array_Data
<F
>::New(input
.size(), buf
);
240 internal::ArraySerializer
<E
, F
>::template SerializeElements
<
241 ValidateParams::element_is_nullable
,
242 typename
ValidateParams::ElementValidateParams
>(
243 internal::Forward(input
), buf
, result
);
251 template <typename E
, typename F
>
252 inline void Deserialize_(internal::Array_Data
<F
>* input
, Array
<E
>* output
) {
254 internal::ArraySerializer
<E
, F
>::DeserializeElements(input
, output
);
262 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_