Chromium Code Reviews| 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..ee09ed1c0319e33a175c475ef60167c7b145f790 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 GetDataIfAvailableResult = |
| + decltype(Traits::GetData(std::declval<MaybeConstUserType&>())); |
| + GetDataIfAvailableResult GetDataIfAvailable() { |
| + return Traits::GetData(input_); |
|
Ken Rockot(use gerrit already)
2016/05/27 16:07:39
If this can work in the general case (returning nu
yzshen1
2016/05/28 00:23:07
I made the GetData() function of ArrayTraits optio
|
| + } |
| + |
| + 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->GetDataIfAvailable(); |
| + if (data) { |
| + memcpy(output->storage(), data, size * sizeof(DataElement)); |
| + } else { |
| + for (size_t i = 0; i < size; ++i) |
|
Ken Rockot(use gerrit already)
2016/05/27 16:07:39
Nice, this should also be useful for things like b
yzshen1
2016/05/28 00:23:07
Done.
|
| + output->at(i) = static_cast<DataElement>(input->GetNext()); |
| } |
| } |
| @@ -106,9 +146,12 @@ struct ArraySerializer<MojomType, |
| }; |
| // 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 +160,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 +175,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 +190,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 +205,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 +219,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 +245,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 +258,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 +336,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 +352,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 +402,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 +412,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 +430,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; |