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; |