| Index: mojo/public/cpp/bindings/lib/array_serialization.h
|
| diff --git a/mojo/public/cpp/bindings/lib/array_serialization.h b/mojo/public/cpp/bindings/lib/array_serialization.h
|
| index 3b4033b4fdfa47cb6bd14af92f131f041cfb89e6..83d94ce1fbcd351acbac03f86271aa21dbc8277c 100644
|
| --- a/mojo/public/cpp/bindings/lib/array_serialization.h
|
| +++ b/mojo/public/cpp/bindings/lib/array_serialization.h
|
| @@ -20,10 +20,6 @@
|
| #include "mojo/public/cpp/bindings/lib/template_util.h"
|
| #include "mojo/public/cpp/bindings/lib/validation_errors.h"
|
|
|
| -namespace WTF {
|
| -class String;
|
| -}
|
| -
|
| namespace mojo {
|
| namespace internal {
|
|
|
| @@ -50,16 +46,53 @@ struct GetArraySerializerType {
|
| : ArraySerializerType::POD)));
|
| };
|
|
|
| +// Used as the UserTypeReader template parameter of ArraySerializer.
|
| +template <typename MaybeConstUserType>
|
| +class ArrayReader {
|
| + public:
|
| + using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
| + using Traits = ArrayTraits<UserType>;
|
| +
|
| + explicit ArrayReader(MaybeConstUserType& input) : input_(input) {}
|
| + ~ArrayReader() {}
|
| +
|
| + size_t GetSize() const { return Traits::GetSize(input_); }
|
| +
|
| + using GetNextResult =
|
| + decltype(Traits::GetAt(std::declval<MaybeConstUserType&>(), 0));
|
| + GetNextResult GetNext() {
|
| + DCHECK_LT(index_, Traits::GetSize(input_));
|
| + return Traits::GetAt(input_, index_++);
|
| + }
|
| +
|
| + using GetDataIfExistsResult = decltype(
|
| + CallGetDataIfExists<Traits>(std::declval<MaybeConstUserType&>()));
|
| + GetDataIfExistsResult GetDataIfExists() {
|
| + return CallGetDataIfExists<Traits>(input_);
|
| + }
|
| +
|
| + private:
|
| + MaybeConstUserType& input_;
|
| + size_t index_ = 0;
|
| +};
|
| +
|
| +// ArraySerializer is also used to serialize map keys and values. Therefore, it
|
| +// has a UserTypeReader parameter which is an adaptor for reading to hide the
|
| +// difference between ArrayTraits and MapTraits.
|
| template <typename MojomType,
|
| typename MaybeConstUserType,
|
| + typename UserTypeReader,
|
| ArraySerializerType type =
|
| GetArraySerializerType<typename MojomType::Data_::Element>::value>
|
| struct ArraySerializer;
|
|
|
| // Handles serialization and deserialization of arrays of pod types.
|
| -template <typename MojomType, typename MaybeConstUserType>
|
| +template <typename MojomType,
|
| + typename MaybeConstUserType,
|
| + typename UserTypeReader>
|
| struct ArraySerializer<MojomType,
|
| MaybeConstUserType,
|
| + UserTypeReader,
|
| ArraySerializerType::POD> {
|
| using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
| using Data = typename MojomType::Data_;
|
| @@ -72,12 +105,12 @@ struct ArraySerializer<MojomType,
|
| static_assert(std::is_same<Element, typename Traits::Element>::value,
|
| "Incorrect array serializer");
|
|
|
| - static size_t GetSerializedSize(MaybeConstUserType& input,
|
| + static size_t GetSerializedSize(UserTypeReader* input,
|
| SerializationContext* context) {
|
| - return sizeof(Data) + Align(Traits::GetSize(input) * sizeof(DataElement));
|
| + return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement));
|
| }
|
|
|
| - static void SerializeElements(MaybeConstUserType& input,
|
| + static void SerializeElements(UserTypeReader* input,
|
| Buffer* buf,
|
| Data* output,
|
| const ArrayValidateParams* validate_params,
|
| @@ -87,9 +120,16 @@ struct ArraySerializer<MojomType,
|
| DCHECK(!validate_params->element_validate_params)
|
| << "Primitive type should not have array validate params";
|
|
|
| - if (Traits::GetSize(input)) {
|
| - memcpy(output->storage(), Traits::GetData(input),
|
| - Traits::GetSize(input) * sizeof(DataElement));
|
| + size_t size = input->GetSize();
|
| + if (size == 0)
|
| + return;
|
| +
|
| + auto data = input->GetDataIfExists();
|
| + if (data) {
|
| + memcpy(output->storage(), data, size * sizeof(DataElement));
|
| + } else {
|
| + for (size_t i = 0; i < size; ++i)
|
| + output->at(i) = static_cast<DataElement>(input->GetNext());
|
| }
|
| }
|
|
|
| @@ -98,17 +138,25 @@ struct ArraySerializer<MojomType,
|
| SerializationContext* context) {
|
| Traits::Resize(*output, input->size());
|
| if (input->size()) {
|
| - memcpy(Traits::GetData(*output), input->storage(),
|
| - input->size() * sizeof(DataElement));
|
| + auto data = CallGetDataIfExists<Traits>(*output);
|
| + if (data) {
|
| + memcpy(data, input->storage(), input->size() * sizeof(DataElement));
|
| + } else {
|
| + for (size_t i = 0; i < input->size(); ++i)
|
| + Traits::GetAt(*output, i) = static_cast<Element>(input->at(i));
|
| + }
|
| }
|
| return true;
|
| }
|
| };
|
|
|
| // Serializes and deserializes arrays of bools.
|
| -template <typename MojomType, typename MaybeConstUserType>
|
| +template <typename MojomType,
|
| + typename MaybeConstUserType,
|
| + typename UserTypeReader>
|
| struct ArraySerializer<MojomType,
|
| MaybeConstUserType,
|
| + UserTypeReader,
|
| ArraySerializerType::BOOLEAN> {
|
| using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
| using Traits = ArrayTraits<UserType>;
|
| @@ -117,12 +165,12 @@ struct ArraySerializer<MojomType,
|
| static_assert(std::is_same<bool, typename UserType::Element>::value,
|
| "Incorrect array serializer");
|
|
|
| - static size_t GetSerializedSize(MaybeConstUserType& input,
|
| + static size_t GetSerializedSize(UserTypeReader* input,
|
| SerializationContext* context) {
|
| - return sizeof(Data) + Align((Traits::GetSize(input) + 7) / 8);
|
| + return sizeof(Data) + Align((input->GetSize() + 7) / 8);
|
| }
|
|
|
| - static void SerializeElements(MaybeConstUserType& input,
|
| + static void SerializeElements(UserTypeReader* input,
|
| Buffer* buf,
|
| Data* output,
|
| const ArrayValidateParams* validate_params,
|
| @@ -132,16 +180,14 @@ struct ArraySerializer<MojomType,
|
| DCHECK(!validate_params->element_validate_params)
|
| << "Primitive type should not have array validate params";
|
|
|
| - // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
|
| - size_t size = Traits::GetSize(input);
|
| + size_t size = input->GetSize();
|
| for (size_t i = 0; i < size; ++i)
|
| - output->at(i) = Traits::GetAt(input, i);
|
| + output->at(i) = input->GetNext();
|
| }
|
| static bool DeserializeElements(Data* input,
|
| UserType* output,
|
| SerializationContext* context) {
|
| Traits::Resize(*output, input->size());
|
| - // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
|
| for (size_t i = 0; i < input->size(); ++i)
|
| Traits::GetAt(*output, i) = input->at(i);
|
| return true;
|
| @@ -149,9 +195,12 @@ struct ArraySerializer<MojomType,
|
| };
|
|
|
| // Serializes and deserializes arrays of handles.
|
| -template <typename MojomType, typename MaybeConstUserType>
|
| +template <typename MojomType,
|
| + typename MaybeConstUserType,
|
| + typename UserTypeReader>
|
| struct ArraySerializer<MojomType,
|
| MaybeConstUserType,
|
| + UserTypeReader,
|
| ArraySerializerType::HANDLE> {
|
| using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
| using Data = typename MojomType::Data_;
|
| @@ -161,13 +210,13 @@ struct ArraySerializer<MojomType,
|
| static_assert(std::is_same<Element, typename Traits::Element>::value,
|
| "Incorrect array serializer");
|
|
|
| - static size_t GetSerializedSize(MaybeConstUserType& input,
|
| + static size_t GetSerializedSize(UserTypeReader* input,
|
| SerializationContext* context) {
|
| return sizeof(Data) +
|
| - Align(Traits::GetSize(input) * sizeof(typename Data::Element));
|
| + Align(input->GetSize() * sizeof(typename Data::Element));
|
| }
|
|
|
| - static void SerializeElements(MaybeConstUserType& input,
|
| + static void SerializeElements(UserTypeReader* input,
|
| Buffer* buf,
|
| Data* output,
|
| const ArrayValidateParams* validate_params,
|
| @@ -175,11 +224,10 @@ struct ArraySerializer<MojomType,
|
| DCHECK(!validate_params->element_validate_params)
|
| << "Handle type should not have array validate params";
|
|
|
| - size_t size = Traits::GetSize(input);
|
| + size_t size = input->GetSize();
|
| for (size_t i = 0; i < size; ++i) {
|
| // Transfer ownership of the handle.
|
| - output->at(i) =
|
| - context->handles.AddHandle(Traits::GetAt(input, i).release());
|
| + output->at(i) = context->handles.AddHandle(input->GetNext().release());
|
| MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
|
| !validate_params->element_is_nullable && !output->at(i).is_valid(),
|
| VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
|
| @@ -202,9 +250,12 @@ struct ArraySerializer<MojomType,
|
|
|
| // This template must only apply to pointer mojo entity (strings, structs,
|
| // arrays and maps).
|
| -template <typename MojomType, typename MaybeConstUserType>
|
| +template <typename MojomType,
|
| + typename MaybeConstUserType,
|
| + typename UserTypeReader>
|
| struct ArraySerializer<MojomType,
|
| MaybeConstUserType,
|
| + UserTypeReader,
|
| ArraySerializerType::POINTER> {
|
| using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
| using Data = typename MojomType::Data_;
|
| @@ -212,27 +263,27 @@ struct ArraySerializer<MojomType,
|
| using Element = typename MojomType::Element;
|
| using Traits = ArrayTraits<UserType>;
|
|
|
| - static size_t GetSerializedSize(MaybeConstUserType& input,
|
| + static size_t GetSerializedSize(UserTypeReader* input,
|
| SerializationContext* context) {
|
| - size_t element_count = Traits::GetSize(input);
|
| + size_t element_count = input->GetSize();
|
| size_t size =
|
| sizeof(Data) +
|
| element_count *
|
| sizeof(Pointer<typename std::remove_pointer<DataElement>::type>);
|
| for (size_t i = 0; i < element_count; ++i)
|
| - size += PrepareToSerialize<Element>(Traits::GetAt(input, i), context);
|
| + size += PrepareToSerialize<Element>(input->GetNext(), context);
|
| return size;
|
| }
|
|
|
| - static void SerializeElements(MaybeConstUserType& input,
|
| + static void SerializeElements(UserTypeReader* input,
|
| Buffer* buf,
|
| Data* output,
|
| const ArrayValidateParams* validate_params,
|
| SerializationContext* context) {
|
| - size_t size = Traits::GetSize(input);
|
| + size_t size = input->GetSize();
|
| for (size_t i = 0; i < size; ++i) {
|
| DataElement element;
|
| - SerializeCaller<Element>::Run(Traits::GetAt(input, i), buf, &element,
|
| + SerializeCaller<Element>::Run(input->GetNext(), buf, &element,
|
| validate_params->element_validate_params,
|
| context);
|
| output->at(i) = element;
|
| @@ -290,9 +341,12 @@ struct ArraySerializer<MojomType,
|
| };
|
|
|
| // Handles serialization and deserialization of arrays of unions.
|
| -template <typename MojomType, typename MaybeConstUserType>
|
| +template <typename MojomType,
|
| + typename MaybeConstUserType,
|
| + typename UserTypeReader>
|
| struct ArraySerializer<MojomType,
|
| MaybeConstUserType,
|
| + UserTypeReader,
|
| ArraySerializerType::UNION> {
|
| using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
| using Data = typename MojomType::Data_;
|
| @@ -303,28 +357,27 @@ struct ArraySerializer<MojomType,
|
| typename Traits::Element>::value,
|
| "Incorrect array serializer");
|
|
|
| - static size_t GetSerializedSize(MaybeConstUserType& input,
|
| + static size_t GetSerializedSize(UserTypeReader* input,
|
| SerializationContext* context) {
|
| - size_t element_count = Traits::GetSize(input);
|
| + size_t element_count = input->GetSize();
|
| size_t size = sizeof(Data);
|
| for (size_t i = 0; i < element_count; ++i) {
|
| // Call with |inlined| set to false, so that it will account for both the
|
| // data in the union and the space in the array used to hold the union.
|
| - size +=
|
| - PrepareToSerialize<Element>(Traits::GetAt(input, i), false, context);
|
| + size += PrepareToSerialize<Element>(input->GetNext(), false, context);
|
| }
|
| return size;
|
| }
|
|
|
| - static void SerializeElements(MaybeConstUserType& input,
|
| + static void SerializeElements(UserTypeReader* input,
|
| Buffer* buf,
|
| Data* output,
|
| const ArrayValidateParams* validate_params,
|
| SerializationContext* context) {
|
| - size_t size = Traits::GetSize(input);
|
| + size_t size = input->GetSize();
|
| for (size_t i = 0; i < size; ++i) {
|
| typename Data::Element* result = output->storage() + i;
|
| - Serialize<Element>(Traits::GetAt(input, i), buf, &result, true, context);
|
| + Serialize<Element>(input->GetNext(), buf, &result, true, context);
|
| MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
|
| !validate_params->element_is_nullable && output->at(i).is_null(),
|
| VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
|
| @@ -354,7 +407,9 @@ struct ArraySerializer<MojomType,
|
| template <typename Element, typename MaybeConstUserType>
|
| struct Serializer<Array<Element>, MaybeConstUserType> {
|
| using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
| - using Impl = ArraySerializer<Array<Element>, MaybeConstUserType>;
|
| + using Impl = ArraySerializer<Array<Element>,
|
| + MaybeConstUserType,
|
| + ArrayReader<MaybeConstUserType>>;
|
| using Traits = ArrayTraits<UserType>;
|
| using Data = typename Array<Element>::Data_;
|
|
|
| @@ -362,7 +417,8 @@ struct Serializer<Array<Element>, MaybeConstUserType> {
|
| SerializationContext* context) {
|
| if (CallIsNullIfExists<Traits>(input))
|
| return 0;
|
| - return Impl::GetSerializedSize(input, context);
|
| + ArrayReader<MaybeConstUserType> reader(input);
|
| + return Impl::GetSerializedSize(&reader, context);
|
| }
|
|
|
| static void Serialize(MaybeConstUserType& input,
|
| @@ -379,8 +435,10 @@ struct Serializer<Array<Element>, MaybeConstUserType> {
|
| "fixed-size array has wrong number of elements",
|
| Traits::GetSize(input), validate_params->expected_num_elements));
|
| Data* result = Data::New(Traits::GetSize(input), buf);
|
| - if (result)
|
| - Impl::SerializeElements(input, buf, result, validate_params, context);
|
| + if (result) {
|
| + ArrayReader<MaybeConstUserType> reader(input);
|
| + Impl::SerializeElements(&reader, buf, result, validate_params, context);
|
| + }
|
| *output = result;
|
| } else {
|
| *output = nullptr;
|
|
|