blob: 0f0be5dee5e874cfde9680161be80c5bdb134a43 [file] [log] [blame]
Avi Drissmand387f0922022-09-14 20:51:311// Copyright 2014 The Chromium Authors
rockot85dce0862015-11-13 01:33:592// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Arthur Sonzognid4ee5452024-07-18 21:51:545#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
7#pragma allow_unsafe_buffers
8#endif
9
rockot85dce0862015-11-13 01:33:5910#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
11#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
12
Avi Drissman2e88ac372015-12-21 18:14:5713#include <stddef.h>
yzshenc8c4b082016-05-06 21:26:1114#include <string.h> // For |memcpy()|.
rockot85dce0862015-11-13 01:33:5915
yzshenc8c4b082016-05-06 21:26:1116#include <type_traits>
17#include <utility>
yzshenc8c4b082016-05-06 21:26:1118
Emily Andrews7f0e1942025-04-25 21:25:2619#include "base/check.h"
Ali Hijazi20b1c692023-01-11 17:47:0520#include "base/memory/raw_ptr_exclusion.h"
yzshen6dc90352016-08-24 09:12:5721#include "mojo/public/cpp/bindings/array_data_view.h"
yzshenc8c4b082016-05-06 21:26:1122#include "mojo/public/cpp/bindings/lib/array_internal.h"
Ken Rockotcae3ce22021-02-11 05:34:2523#include "mojo/public/cpp/bindings/lib/message_fragment.h"
yzshenc8c4b082016-05-06 21:26:1124#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
25#include "mojo/public/cpp/bindings/lib/template_util.h"
26#include "mojo/public/cpp/bindings/lib/validation_errors.h"
27
rockot85dce0862015-11-13 01:33:5928namespace mojo {
Ken Rockot51df42e72021-02-09 01:20:5329
30class Message;
31
yzshenc8c4b082016-05-06 21:26:1132namespace internal {
rockot85dce0862015-11-13 01:33:5933
fsamuel09ab6962016-06-13 17:56:5334template <typename Traits,
35 typename MaybeConstUserType,
36 bool HasGetBegin =
37 HasGetBeginMethod<Traits, MaybeConstUserType>::value>
38class ArrayIterator {};
yzshen507ce1262016-05-31 18:08:3039
fsamuel09ab6962016-06-13 17:56:5340// Used as the UserTypeIterator template parameter of ArraySerializer.
41template <typename Traits, typename MaybeConstUserType>
42class ArrayIterator<Traits, MaybeConstUserType, true> {
43 public:
Daniel Chenge7aa0262022-02-25 20:39:1744 using IteratorType =
45 decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>()));
fsamuel09ab6962016-06-13 17:56:5346
47 explicit ArrayIterator(MaybeConstUserType& input)
Daniel Chenge7aa0262022-02-25 20:39:1748 : input_(input), iter_(Traits::GetBegin(input)) {}
fsamuel09ab6962016-06-13 17:56:5349 ~ArrayIterator() {}
yzshen507ce1262016-05-31 18:08:3050
51 size_t GetSize() const { return Traits::GetSize(input_); }
52
Daniel Chenge7aa0262022-02-25 20:39:1753 decltype(auto) GetNext() {
54 decltype(auto) value = Traits::GetValue(iter_);
fsamuel09ab6962016-06-13 17:56:5355 Traits::AdvanceIterator(iter_);
56 return value;
yzshen507ce1262016-05-31 18:08:3057 }
58
Daniel Chenge7aa0262022-02-25 20:39:1759 const MaybeConstUserType& input() const { return input_; }
yzshen507ce1262016-05-31 18:08:3060
61 private:
Bartek Nowierskif5eeeba2024-01-25 12:49:3962 // RAW_PTR_EXCLUSION: Binary size increase.
Ali Hijazi20b1c692023-01-11 17:47:0563 RAW_PTR_EXCLUSION MaybeConstUserType& input_;
fsamuel09ab6962016-06-13 17:56:5364 IteratorType iter_;
65};
66
67// Used as the UserTypeIterator template parameter of ArraySerializer.
68template <typename Traits, typename MaybeConstUserType>
69class ArrayIterator<Traits, MaybeConstUserType, false> {
70 public:
71 explicit ArrayIterator(MaybeConstUserType& input) : input_(input), iter_(0) {}
72 ~ArrayIterator() {}
73
74 size_t GetSize() const { return Traits::GetSize(input_); }
75
Daniel Chenge7aa0262022-02-25 20:39:1776 decltype(auto) GetNext() {
fsamuel09ab6962016-06-13 17:56:5377 DCHECK_LT(iter_, Traits::GetSize(input_));
78 return Traits::GetAt(input_, iter_++);
79 }
80
Daniel Chenge7aa0262022-02-25 20:39:1781 const MaybeConstUserType& input() const { return input_; }
fsamuel09ab6962016-06-13 17:56:5382
83 private:
Bartek Nowierskif5eeeba2024-01-25 12:49:3984 // RAW_PTR_EXCLUSION: Binary size increase.
Ali Hijazi20b1c692023-01-11 17:47:0585 RAW_PTR_EXCLUSION MaybeConstUserType& input_;
fsamuel09ab6962016-06-13 17:56:5386 size_t iter_;
yzshen507ce1262016-05-31 18:08:3087};
88
89// ArraySerializer is also used to serialize map keys and values. Therefore, it
fsamuel09ab6962016-06-13 17:56:5390// has a UserTypeIterator parameter which is an adaptor for reading to hide the
yzshen507ce1262016-05-31 18:08:3091// difference between ArrayTraits and MapTraits.
yzshenc8c4b082016-05-06 21:26:1192template <typename MojomType,
93 typename MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:5394 typename UserTypeIterator,
yzshen5e5173a2016-06-22 21:49:0195 typename EnableType = void>
yzshenc8c4b082016-05-06 21:26:1196struct ArraySerializer;
rockot85dce0862015-11-13 01:33:5997
yzshenc8c4b082016-05-06 21:26:1198// Handles serialization and deserialization of arrays of pod types.
yzshen507ce1262016-05-31 18:08:3099template <typename MojomType,
100 typename MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53101 typename UserTypeIterator>
yzshen5e5173a2016-06-22 21:49:01102struct ArraySerializer<
103 MojomType,
104 MaybeConstUserType,
105 UserTypeIterator,
Fred Shih4ab323b2024-04-04 21:56:29106 std::enable_if_t<BelongsTo<typename MojomType::Element,
107 MojomTypeCategory::kPOD>::value>> {
yzshenc8c4b082016-05-06 21:26:11108 using UserType = typename std::remove_const<MaybeConstUserType>::type;
yzshen5e5173a2016-06-22 21:49:01109 using Data = typename MojomTypeTraits<MojomType>::Data;
yzshenc8c4b082016-05-06 21:26:11110 using DataElement = typename Data::Element;
111 using Element = typename MojomType::Element;
112 using Traits = ArrayTraits<UserType>;
113
yzshen442cc862016-06-10 00:34:09114 static_assert(std::is_same<Element, DataElement>::value,
yzshenc8c4b082016-05-06 21:26:11115 "Incorrect array serializer");
Daniel Cheng02908b602017-08-11 08:13:29116 static_assert(
117 std::is_same<
118 Element,
119 typename std::remove_const<typename Traits::Element>::type>::value,
120 "Incorrect array serializer");
yzshenc8c4b082016-05-06 21:26:11121
Ken Rockotcae3ce22021-02-11 05:34:25122 static void SerializeElements(
123 UserTypeIterator* input,
124 MessageFragment<Data>& fragment,
125 const ContainerValidateParams* validate_params) {
yzshenc8c4b082016-05-06 21:26:11126 DCHECK(!validate_params->element_validate_params)
127 << "Primitive type should not have array validate params";
128
yzshen507ce1262016-05-31 18:08:30129 size_t size = input->GetSize();
130 if (size == 0)
131 return;
132
Ken Rockotcae3ce22021-02-11 05:34:25133 Data* output = fragment.data();
Daniel Chenge7aa0262022-02-25 20:39:17134 if constexpr (HasGetDataMethod<Traits, MaybeConstUserType>::value) {
135 auto data = Traits::GetData(input->input());
yzshen507ce1262016-05-31 18:08:30136 memcpy(output->storage(), data, size * sizeof(DataElement));
137 } else {
138 for (size_t i = 0; i < size; ++i)
yzshen442cc862016-06-10 00:34:09139 output->at(i) = input->GetNext();
yzshenc8c4b082016-05-06 21:26:11140 }
141 }
142
143 static bool DeserializeElements(Data* input,
144 UserType* output,
Ken Rockot51df42e72021-02-09 01:20:53145 Message* message) {
fsamuel7b3867c2016-06-07 08:13:04146 if (!Traits::Resize(*output, input->size()))
147 return false;
yzshenc8c4b082016-05-06 21:26:11148 if (input->size()) {
Daniel Chenge7aa0262022-02-25 20:39:17149 if constexpr (HasGetDataMethod<Traits, UserType>::value) {
150 auto data = Traits::GetData(*output);
yzshen507ce1262016-05-31 18:08:30151 memcpy(data, input->storage(), input->size() * sizeof(DataElement));
152 } else {
Daniel Chenge7aa0262022-02-25 20:39:17153 ArrayIterator<Traits, UserType> iterator(*output);
yzshen507ce1262016-05-31 18:08:30154 for (size_t i = 0; i < input->size(); ++i)
Fred Shih4ab323b2024-04-04 21:56:29155 iterator.GetNext() = static_cast<DataElement>(input->at(i));
yzshen507ce1262016-05-31 18:08:30156 }
yzshenc8c4b082016-05-06 21:26:11157 }
158 return true;
159 }
160};
161
yzshen442cc862016-06-10 00:34:09162// Handles serialization and deserialization of arrays of enum types.
163template <typename MojomType,
164 typename MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53165 typename UserTypeIterator>
Daniel Chengfb999fd32025-06-13 02:30:16166 requires(!base::is_instantiation<typename MojomType::Element, std::optional>)
yzshen5e5173a2016-06-22 21:49:01167struct ArraySerializer<
168 MojomType,
169 MaybeConstUserType,
170 UserTypeIterator,
171 typename std::enable_if<BelongsTo<typename MojomType::Element,
James Cook591304d2019-08-06 21:23:39172 MojomTypeCategory::kEnum>::value>::type> {
yzshen442cc862016-06-10 00:34:09173 using UserType = typename std::remove_const<MaybeConstUserType>::type;
yzshen5e5173a2016-06-22 21:49:01174 using Data = typename MojomTypeTraits<MojomType>::Data;
yzshen442cc862016-06-10 00:34:09175 using DataElement = typename Data::Element;
176 using Element = typename MojomType::Element;
177 using Traits = ArrayTraits<UserType>;
178
179 static_assert(sizeof(Element) == sizeof(DataElement),
180 "Incorrect array serializer");
181
Ken Rockotcae3ce22021-02-11 05:34:25182 static void SerializeElements(
183 UserTypeIterator* input,
184 MessageFragment<Data>& fragment,
185 const ContainerValidateParams* validate_params) {
yzshen442cc862016-06-10 00:34:09186 DCHECK(!validate_params->element_is_nullable)
187 << "Primitive type should be non-nullable";
188 DCHECK(!validate_params->element_validate_params)
189 << "Primitive type should not have array validate params";
190
Ken Rockotcae3ce22021-02-11 05:34:25191 Data* output = fragment.data();
yzshen442cc862016-06-10 00:34:09192 size_t size = input->GetSize();
193 for (size_t i = 0; i < size; ++i)
194 Serialize<Element>(input->GetNext(), output->storage() + i);
195 }
196
197 static bool DeserializeElements(Data* input,
198 UserType* output,
Ken Rockot51df42e72021-02-09 01:20:53199 Message* message) {
yzshen442cc862016-06-10 00:34:09200 if (!Traits::Resize(*output, input->size()))
201 return false;
fsamuel09ab6962016-06-13 17:56:53202 ArrayIterator<Traits, UserType> iterator(*output);
yzshen442cc862016-06-10 00:34:09203 for (size_t i = 0; i < input->size(); ++i) {
fsamuel09ab6962016-06-13 17:56:53204 if (!Deserialize<Element>(input->at(i), &iterator.GetNext()))
yzshen442cc862016-06-10 00:34:09205 return false;
206 }
207 return true;
208 }
209};
210
Fred Shih4ab323b2024-04-04 21:56:29211// Handles serialization and deserialization of arrays of optional enum types.
212template <typename MojomType,
213 typename MaybeConstUserType,
214 typename UserTypeIterator>
Daniel Chengfb999fd32025-06-13 02:30:16215 requires(base::is_instantiation<typename MojomType::Element, std::optional>)
Fred Shih4ab323b2024-04-04 21:56:29216struct ArraySerializer<
217 MojomType,
218 MaybeConstUserType,
219 UserTypeIterator,
220 std::enable_if_t<BelongsTo<typename MojomType::Element,
221 MojomTypeCategory::kEnum>::value>> {
222 using UserType = typename std::remove_const<MaybeConstUserType>::type;
223 using Data = typename MojomTypeTraits<MojomType>::Data;
224 using DataElement = typename Data::Element;
225 using Element = typename MojomType::Element;
226 using Traits = ArrayTraits<UserType>;
227
228 static_assert(IsAbslOptional<typename Traits::Element>::value,
229 "Output type should be optional");
230 static_assert(sizeof(Element) == sizeof(DataElement),
231 "Incorrect array serializer");
232
233 static void SerializeElements(
234 UserTypeIterator* input,
235 MessageFragment<Data>& fragment,
236 const ContainerValidateParams* validate_params) {
237 DCHECK(!validate_params->element_validate_params)
238 << "Primitive type should not have array validate params";
239
240 Data* output = fragment.data();
241 size_t size = input->GetSize();
242 for (size_t i = 0; i < size; ++i) {
243 auto next = input->GetNext();
244 if (next) {
245 int32_t serialized;
246 Serialize<typename Element::value_type>(*next, &serialized);
247 output->at(i) = serialized;
248 } else {
249 output->at(i) = std::nullopt;
250 }
251 }
252 }
253
254 static bool DeserializeElements(Data* input,
255 UserType* output,
256 Message* message) {
257 if (!Traits::Resize(*output, input->size())) {
258 return false;
259 }
260 ArrayIterator<Traits, UserType> iterator(*output);
261 for (size_t i = 0; i < input->size(); ++i) {
262 std::optional<int32_t> element = input->at(i).ToOptional();
263 if (element) {
264 typename Element::value_type deserialized;
265 if (!Deserialize<typename Element::value_type>(*element,
266 &deserialized)) {
267 return false;
268 }
269 iterator.GetNext() = deserialized;
270 } else {
271 iterator.GetNext() = std::nullopt;
272 }
273 }
274 return true;
275 }
276};
277
yzshenc8c4b082016-05-06 21:26:11278// Serializes and deserializes arrays of bools.
yzshen507ce1262016-05-31 18:08:30279template <typename MojomType,
280 typename MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53281 typename UserTypeIterator>
yzshenc8c4b082016-05-06 21:26:11282struct ArraySerializer<MojomType,
283 MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53284 UserTypeIterator,
yzshen5e5173a2016-06-22 21:49:01285 typename std::enable_if<BelongsTo<
286 typename MojomType::Element,
James Cook591304d2019-08-06 21:23:39287 MojomTypeCategory::kBoolean>::value>::type> {
yzshenc8c4b082016-05-06 21:26:11288 using UserType = typename std::remove_const<MaybeConstUserType>::type;
289 using Traits = ArrayTraits<UserType>;
yzshen5e5173a2016-06-22 21:49:01290 using Data = typename MojomTypeTraits<MojomType>::Data;
yzshenc8c4b082016-05-06 21:26:11291
yzshen54300842016-06-16 19:08:56292 static_assert(std::is_same<bool, typename Traits::Element>::value,
yzshenc8c4b082016-05-06 21:26:11293 "Incorrect array serializer");
294
Ken Rockotcae3ce22021-02-11 05:34:25295 static void SerializeElements(
296 UserTypeIterator* input,
297 MessageFragment<Data>& fragment,
298 const ContainerValidateParams* validate_params) {
yzshenc8c4b082016-05-06 21:26:11299 DCHECK(!validate_params->element_is_nullable)
300 << "Primitive type should be non-nullable";
301 DCHECK(!validate_params->element_validate_params)
302 << "Primitive type should not have array validate params";
303
Ken Rockotcae3ce22021-02-11 05:34:25304 Data* output = fragment.data();
yzshen507ce1262016-05-31 18:08:30305 size_t size = input->GetSize();
yzshenc8c4b082016-05-06 21:26:11306 for (size_t i = 0; i < size; ++i)
yzshen507ce1262016-05-31 18:08:30307 output->at(i) = input->GetNext();
yzshenc8c4b082016-05-06 21:26:11308 }
309 static bool DeserializeElements(Data* input,
310 UserType* output,
Ken Rockot51df42e72021-02-09 01:20:53311 Message* message) {
fsamuel7b3867c2016-06-07 08:13:04312 if (!Traits::Resize(*output, input->size()))
313 return false;
fsamuel09ab6962016-06-13 17:56:53314 ArrayIterator<Traits, UserType> iterator(*output);
yzshenc8c4b082016-05-06 21:26:11315 for (size_t i = 0; i < input->size(); ++i)
fsamuel09ab6962016-06-13 17:56:53316 iterator.GetNext() = input->at(i);
yzshenc8c4b082016-05-06 21:26:11317 return true;
318 }
319};
320
yzshenf26b0532016-06-30 01:37:59321// Serializes and deserializes arrays of handles or interfaces.
yzshen507ce1262016-05-31 18:08:30322template <typename MojomType,
323 typename MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53324 typename UserTypeIterator>
yzshenf26b0532016-06-30 01:37:59325struct ArraySerializer<
326 MojomType,
327 MaybeConstUserType,
328 UserTypeIterator,
James Cook591304d2019-08-06 21:23:39329 typename std::enable_if<BelongsTo<
330 typename MojomType::Element,
331 MojomTypeCategory::kAssociatedInterface |
332 MojomTypeCategory::kAssociatedInterfaceRequest |
333 MojomTypeCategory::kHandle | MojomTypeCategory::kInterface |
334 MojomTypeCategory::kInterfaceRequest>::value>::type> {
yzshenc8c4b082016-05-06 21:26:11335 using UserType = typename std::remove_const<MaybeConstUserType>::type;
yzshen5e5173a2016-06-22 21:49:01336 using Data = typename MojomTypeTraits<MojomType>::Data;
yzshenc8c4b082016-05-06 21:26:11337 using Element = typename MojomType::Element;
338 using Traits = ArrayTraits<UserType>;
339
Ken Rockotcae3ce22021-02-11 05:34:25340 static void SerializeElements(
341 UserTypeIterator* input,
342 MessageFragment<Data>& fragment,
343 const ContainerValidateParams* validate_params) {
yzshenc8c4b082016-05-06 21:26:11344 DCHECK(!validate_params->element_validate_params)
yzshenf26b0532016-06-30 01:37:59345 << "Handle or interface type should not have array validate params";
yzshenc8c4b082016-05-06 21:26:11346
Ken Rockotcae3ce22021-02-11 05:34:25347 Data* output = fragment.data();
yzshen507ce1262016-05-31 18:08:30348 size_t size = input->GetSize();
yzshenc8c4b082016-05-06 21:26:11349 for (size_t i = 0; i < size; ++i) {
Daniel Chenge7aa0262022-02-25 20:39:17350 decltype(auto) next = input->GetNext();
Ken Rockotcae3ce22021-02-11 05:34:25351 Serialize<Element>(next, &output->at(i), &fragment.message());
yzshenf26b0532016-06-30 01:37:59352
353 static const ValidationError kError =
354 BelongsTo<Element,
James Cook591304d2019-08-06 21:23:39355 MojomTypeCategory::kAssociatedInterface |
356 MojomTypeCategory::kAssociatedInterfaceRequest>::value
yzshenf26b0532016-06-30 01:37:59357 ? VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID
358 : VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE;
Emily Andrews92983e932025-05-08 16:02:13359
360 MOJO_INTERNAL_CHECK_SERIALIZATION(
361 SendValidation::kDefault,
362 !(!validate_params->element_is_nullable &&
363 !IsHandleOrInterfaceValid(output->at(i))),
yzshenf26b0532016-06-30 01:37:59364 kError,
365 MakeMessageWithArrayIndex("invalid handle or interface ID in array "
366 "expecting valid handles or interface IDs",
367 size, i));
yzshenc8c4b082016-05-06 21:26:11368 }
369 }
370 static bool DeserializeElements(Data* input,
371 UserType* output,
Ken Rockot51df42e72021-02-09 01:20:53372 Message* message) {
fsamuel7b3867c2016-06-07 08:13:04373 if (!Traits::Resize(*output, input->size()))
374 return false;
fsamuel09ab6962016-06-13 17:56:53375 ArrayIterator<Traits, UserType> iterator(*output);
yzshenc8c4b082016-05-06 21:26:11376 for (size_t i = 0; i < input->size(); ++i) {
yzshenf26b0532016-06-30 01:37:59377 bool result =
Ken Rockot51df42e72021-02-09 01:20:53378 Deserialize<Element>(&input->at(i), &iterator.GetNext(), message);
yzshenf26b0532016-06-30 01:37:59379 DCHECK(result);
yzshenc8c4b082016-05-06 21:26:11380 }
381 return true;
382 }
383};
384
385// This template must only apply to pointer mojo entity (strings, structs,
386// arrays and maps).
yzshen507ce1262016-05-31 18:08:30387template <typename MojomType,
388 typename MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53389 typename UserTypeIterator>
yzshenc8c4b082016-05-06 21:26:11390struct ArraySerializer<MojomType,
391 MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53392 UserTypeIterator,
yzshen5e5173a2016-06-22 21:49:01393 typename std::enable_if<BelongsTo<
394 typename MojomType::Element,
James Cook591304d2019-08-06 21:23:39395 MojomTypeCategory::kArray | MojomTypeCategory::kMap |
396 MojomTypeCategory::kString |
397 MojomTypeCategory::kStruct>::value>::type> {
yzshenc8c4b082016-05-06 21:26:11398 using UserType = typename std::remove_const<MaybeConstUserType>::type;
yzshen5e5173a2016-06-22 21:49:01399 using Data = typename MojomTypeTraits<MojomType>::Data;
yzshenc8c4b082016-05-06 21:26:11400 using Element = typename MojomType::Element;
Ken Rockotcae3ce22021-02-11 05:34:25401 using ElementData = typename MojomTypeTraits<Element>::Data;
yzshenc8c4b082016-05-06 21:26:11402 using Traits = ArrayTraits<UserType>;
403
Ken Rockotcae3ce22021-02-11 05:34:25404 static void SerializeElements(
405 UserTypeIterator* input,
406 MessageFragment<Data>& fragment,
407 const ContainerValidateParams* validate_params) {
yzshen507ce1262016-05-31 18:08:30408 size_t size = input->GetSize();
yzshenc8c4b082016-05-06 21:26:11409 for (size_t i = 0; i < size; ++i) {
Ken Rockotcae3ce22021-02-11 05:34:25410 MessageFragment<ElementData> data_fragment(fragment.message());
Daniel Chenge7aa0262022-02-25 20:39:17411 decltype(auto) next = input->GetNext();
Ken Rockotcae3ce22021-02-11 05:34:25412 SerializeCaller<Element>::Run(next, data_fragment,
413 validate_params->element_validate_params);
414 fragment->at(i).Set(data_fragment.is_null() ? nullptr
415 : data_fragment.data());
Emily Andrews92983e932025-05-08 16:02:13416
417 MOJO_INTERNAL_CHECK_SERIALIZATION(
418 SendValidation::kDefault,
419 !(!validate_params->element_is_nullable && data_fragment.is_null()),
yzshenc8c4b082016-05-06 21:26:11420 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
421 MakeMessageWithArrayIndex("null in array expecting valid pointers",
422 size, i));
423 }
424 }
425 static bool DeserializeElements(Data* input,
426 UserType* output,
Ken Rockot51df42e72021-02-09 01:20:53427 Message* message) {
fsamuel7b3867c2016-06-07 08:13:04428 if (!Traits::Resize(*output, input->size()))
429 return false;
fsamuel09ab6962016-06-13 17:56:53430 ArrayIterator<Traits, UserType> iterator(*output);
yzshenc8c4b082016-05-06 21:26:11431 for (size_t i = 0; i < input->size(); ++i) {
yzshena601f032016-07-01 16:14:14432 if (!Deserialize<Element>(input->at(i).Get(), &iterator.GetNext(),
Ken Rockot51df42e72021-02-09 01:20:53433 message))
yzshena601f032016-07-01 16:14:14434 return false;
yzshenc8c4b082016-05-06 21:26:11435 }
yzshena601f032016-07-01 16:14:14436 return true;
yzshenc8c4b082016-05-06 21:26:11437 }
438
439 private:
440 template <typename T,
James Cook591304d2019-08-06 21:23:39441 bool is_array_or_map = BelongsTo<
442 T,
443 MojomTypeCategory::kArray | MojomTypeCategory::kMap>::value>
yzshenc8c4b082016-05-06 21:26:11444 struct SerializeCaller {
445 template <typename InputElementType>
446 static void Run(InputElementType&& input,
Ken Rockotcae3ce22021-02-11 05:34:25447 MessageFragment<ElementData>& fragment,
448 const ContainerValidateParams* validate_params) {
449 Serialize<T>(std::forward<InputElementType>(input), fragment);
yzshenc8c4b082016-05-06 21:26:11450 }
451 };
452
453 template <typename T>
454 struct SerializeCaller<T, true> {
455 template <typename InputElementType>
456 static void Run(InputElementType&& input,
Ken Rockotcae3ce22021-02-11 05:34:25457 MessageFragment<ElementData>& fragment,
458 const ContainerValidateParams* validate_params) {
459 Serialize<T>(std::forward<InputElementType>(input), fragment,
460 validate_params);
yzshenc8c4b082016-05-06 21:26:11461 }
462 };
463};
464
465// Handles serialization and deserialization of arrays of unions.
yzshen507ce1262016-05-31 18:08:30466template <typename MojomType,
467 typename MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53468 typename UserTypeIterator>
James Cook591304d2019-08-06 21:23:39469struct ArraySerializer<MojomType,
470 MaybeConstUserType,
471 UserTypeIterator,
472 typename std::enable_if<
473 BelongsTo<typename MojomType::Element,
474 MojomTypeCategory::kUnion>::value>::type> {
yzshenc8c4b082016-05-06 21:26:11475 using UserType = typename std::remove_const<MaybeConstUserType>::type;
yzshen5e5173a2016-06-22 21:49:01476 using Data = typename MojomTypeTraits<MojomType>::Data;
yzshen5527dbce2016-05-10 18:22:04477 using Element = typename MojomType::Element;
Ken Rockotcae3ce22021-02-11 05:34:25478 using DataElement = typename Data::Element;
yzshenc8c4b082016-05-06 21:26:11479 using Traits = ArrayTraits<UserType>;
480
Ken Rockotcae3ce22021-02-11 05:34:25481 static void SerializeElements(
482 UserTypeIterator* input,
483 MessageFragment<Data>& fragment,
484 const ContainerValidateParams* validate_params) {
yzshen507ce1262016-05-31 18:08:30485 size_t size = input->GetSize();
yzshenc8c4b082016-05-06 21:26:11486 for (size_t i = 0; i < size; ++i) {
Ken Rockotcae3ce22021-02-11 05:34:25487 MessageFragment<DataElement> inlined_union_element(fragment.message());
488 inlined_union_element.Claim(fragment->storage() + i);
Daniel Chenge7aa0262022-02-25 20:39:17489 decltype(auto) next = input->GetNext();
Ken Rockotcae3ce22021-02-11 05:34:25490 Serialize<Element>(next, inlined_union_element, true);
Emily Andrews92983e932025-05-08 16:02:13491
492 MOJO_INTERNAL_CHECK_SERIALIZATION(
493 SendValidation::kDefault,
494 !(!validate_params->element_is_nullable &&
495 inlined_union_element.is_null()),
yzshenc8c4b082016-05-06 21:26:11496 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
497 MakeMessageWithArrayIndex("null in array expecting valid unions",
498 size, i));
499 }
500 }
501
502 static bool DeserializeElements(Data* input,
503 UserType* output,
Ken Rockot51df42e72021-02-09 01:20:53504 Message* message) {
fsamuel7b3867c2016-06-07 08:13:04505 if (!Traits::Resize(*output, input->size()))
506 return false;
fsamuel09ab6962016-06-13 17:56:53507 ArrayIterator<Traits, UserType> iterator(*output);
yzshenc8c4b082016-05-06 21:26:11508 for (size_t i = 0; i < input->size(); ++i) {
Ken Rockot51df42e72021-02-09 01:20:53509 if (!Deserialize<Element>(&input->at(i), &iterator.GetNext(), message))
yzshena601f032016-07-01 16:14:14510 return false;
yzshenc8c4b082016-05-06 21:26:11511 }
yzshena601f032016-07-01 16:14:14512 return true;
yzshenc8c4b082016-05-06 21:26:11513 }
514};
515
516template <typename Element, typename MaybeConstUserType>
yzshen6dc90352016-08-24 09:12:57517struct Serializer<ArrayDataView<Element>, MaybeConstUserType> {
yzshenc8c4b082016-05-06 21:26:11518 using UserType = typename std::remove_const<MaybeConstUserType>::type;
fsamuel09ab6962016-06-13 17:56:53519 using Traits = ArrayTraits<UserType>;
yzshen6dc90352016-08-24 09:12:57520 using Impl = ArraySerializer<ArrayDataView<Element>,
yzshen507ce1262016-05-31 18:08:30521 MaybeConstUserType,
fsamuel09ab6962016-06-13 17:56:53522 ArrayIterator<Traits, MaybeConstUserType>>;
yzshen6dc90352016-08-24 09:12:57523 using Data = typename MojomTypeTraits<ArrayDataView<Element>>::Data;
yzshenc8c4b082016-05-06 21:26:11524
yzshenc8c4b082016-05-06 21:26:11525 static void Serialize(MaybeConstUserType& input,
Ken Rockotcae3ce22021-02-11 05:34:25526 MessageFragment<Data>& fragment,
527 const ContainerValidateParams* validate_params) {
Ken Rockot7c91af2d2017-07-28 09:54:40528 if (CallIsNullIfExists<Traits>(input))
529 return;
530
531 const size_t size = Traits::GetSize(input);
Emily Andrews92983e932025-05-08 16:02:13532
533 MOJO_INTERNAL_CHECK_SERIALIZATION(
534 SendValidation::kDefault,
535 !(validate_params->expected_num_elements != 0 &&
536 size != validate_params->expected_num_elements),
537 VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
538 MakeMessageWithExpectedArraySize(
Ken Rockot7c91af2d2017-07-28 09:54:40539 "fixed-size array has wrong number of elements", size,
540 validate_params->expected_num_elements));
Emily Andrews92983e932025-05-08 16:02:13541
Ken Rockotcae3ce22021-02-11 05:34:25542 fragment.AllocateArrayData(size);
Ken Rockot7c91af2d2017-07-28 09:54:40543 ArrayIterator<Traits, MaybeConstUserType> iterator(input);
Ken Rockotcae3ce22021-02-11 05:34:25544 Impl::SerializeElements(&iterator, fragment, validate_params);
yzshenc8c4b082016-05-06 21:26:11545 }
546
Ken Rockot51df42e72021-02-09 01:20:53547 static bool Deserialize(Data* input, UserType* output, Message* message) {
yzshen20176462016-05-13 04:42:22548 if (!input)
549 return CallSetToNullIfExists<Traits>(output);
Ken Rockot51df42e72021-02-09 01:20:53550 return Impl::DeserializeElements(input, output, message);
yzshenc8c4b082016-05-06 21:26:11551 }
552};
553
554} // namespace internal
rockot85dce0862015-11-13 01:33:59555} // namespace mojo
556
557#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_