Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1670)

Unified Diff: mojo/public/cpp/bindings/lib/array_serialization.h

Issue 1953493002: Mojo C++ bindings: custom type mapping for array - part 2 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@21_simplify
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/public/cpp/bindings/BUILD.gn ('k') | mojo/public/cpp/bindings/lib/array_serialization_traits.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 91fa5d71b8cd1e394f57767429a6a11ba5f3e8b1..1961a0bbec2bb09abef66333f249af7195415db4 100644
--- a/mojo/public/cpp/bindings/lib/array_serialization.h
+++ b/mojo/public/cpp/bindings/lib/array_serialization.h
@@ -6,39 +6,395 @@
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
#include <stddef.h>
+#include <string.h> // For |memcpy()|.
-#include "mojo/public/cpp/bindings/array.h"
-#include "mojo/public/cpp/bindings/lib/array_serialization_traits.h"
+#include <limits>
+#include <type_traits>
+#include <utility>
+#include <vector>
-namespace mojo {
+#include "base/logging.h"
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
+#include "mojo/public/cpp/bindings/lib/template_util.h"
+#include "mojo/public/cpp/bindings/lib/validation_errors.h"
-template <typename E>
-inline size_t GetSerializedSize_(const Array<E>& input,
- internal::SerializationContext* context) {
- return internal::ArraySerializationImpl<Array<E>,
- Array<E>>::GetSerializedSize(input,
- context);
+namespace WTF {
+class String;
}
-template <typename E>
-inline void SerializeArray_(
- Array<E> input,
- internal::Buffer* buf,
- typename Array<E>::Data_** output,
- const internal::ArrayValidateParams* validate_params,
- internal::SerializationContext* context) {
- return internal::ArraySerializationImpl<Array<E>, Array<E>>::Serialize(
- std::move(input), buf, output, validate_params, context);
-}
+namespace mojo {
+namespace internal {
-template <typename E>
-inline bool Deserialize_(typename Array<E>::Data_* input,
- Array<E>* output,
- internal::SerializationContext* context) {
- return internal::ArraySerializationImpl<Array<E>, Array<E>>::Deserialize(
- input, output, context);
-}
+enum class ArraySerializerType {
+ BOOLEAN,
+ // Except boolean.
+ POD,
+ HANDLE,
+ // String, array, map and struct.
+ POINTER,
+ UNION
+};
+
+template <typename T>
+struct GetArraySerializerType {
+ static const ArraySerializerType value =
+ IsUnionDataType<T>::value
+ ? ArraySerializerType::UNION
+ : (std::is_pointer<T>::value
+ ? ArraySerializerType::POINTER
+ : (IsHandle<T>::value ? ArraySerializerType::HANDLE
+ : (std::is_same<T, bool>::value
+ ? ArraySerializerType::BOOLEAN
+ : ArraySerializerType::POD)));
+};
+
+template <typename MojomType,
+ typename MaybeConstUserType,
+ ArraySerializerType type =
+ GetArraySerializerType<typename MojomType::Data_::Element>::value>
+struct ArraySerializer;
+
+// Handles serialization and deserialization of arrays of pod types.
+template <typename MojomType, typename MaybeConstUserType>
+struct ArraySerializer<MojomType,
+ MaybeConstUserType,
+ ArraySerializerType::POD> {
+ using UserType = typename std::remove_const<MaybeConstUserType>::type;
+ using Data = typename MojomType::Data_;
+ using DataElement = typename Data::Element;
+ using Element = typename MojomType::Element;
+ using Traits = ArrayTraits<UserType>;
+
+ static_assert(sizeof(Element) == sizeof(DataElement),
+ "Incorrect array serializer");
+ static_assert(std::is_same<Element, typename Traits::Element>::value,
+ "Incorrect array serializer");
+
+ static size_t GetSerializedSize(MaybeConstUserType& input,
+ SerializationContext* context) {
+ return sizeof(Data) + Align(Traits::GetSize(input) * sizeof(DataElement));
+ }
+
+ static void SerializeElements(MaybeConstUserType& input,
+ Buffer* buf,
+ Data* output,
+ const ArrayValidateParams* validate_params,
+ SerializationContext* context) {
+ DCHECK(!validate_params->element_is_nullable)
+ << "Primitive type should be non-nullable";
+ 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));
+ }
+ }
+
+ static bool DeserializeElements(Data* input,
+ UserType* output,
+ SerializationContext* context) {
+ Traits::Resize(*output, input->size());
+ if (input->size()) {
+ memcpy(Traits::GetData(*output), input->storage(),
+ input->size() * sizeof(DataElement));
+ }
+ return true;
+ }
+};
+
+// Serializes and deserializes arrays of bools.
+template <typename MojomType, typename MaybeConstUserType>
+struct ArraySerializer<MojomType,
+ MaybeConstUserType,
+ ArraySerializerType::BOOLEAN> {
+ using UserType = typename std::remove_const<MaybeConstUserType>::type;
+ using Traits = ArrayTraits<UserType>;
+ using Data = typename MojomType::Data_;
+
+ static_assert(std::is_same<bool, typename UserType::Element>::value,
+ "Incorrect array serializer");
+
+ static size_t GetSerializedSize(MaybeConstUserType& input,
+ SerializationContext* context) {
+ return sizeof(Data) + Align((Traits::GetSize(input) + 7) / 8);
+ }
+
+ static void SerializeElements(MaybeConstUserType& input,
+ Buffer* buf,
+ Data* output,
+ const ArrayValidateParams* validate_params,
+ SerializationContext* context) {
+ DCHECK(!validate_params->element_is_nullable)
+ << "Primitive type should be non-nullable";
+ 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);
+ for (size_t i = 0; i < size; ++i)
+ output->at(i) = Traits::GetAt(input, i);
+ }
+ 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;
+ }
+};
+
+// Serializes and deserializes arrays of handles.
+template <typename MojomType, typename MaybeConstUserType>
+struct ArraySerializer<MojomType,
+ MaybeConstUserType,
+ ArraySerializerType::HANDLE> {
+ using UserType = typename std::remove_const<MaybeConstUserType>::type;
+ using Data = typename MojomType::Data_;
+ using Element = typename MojomType::Element;
+ using Traits = ArrayTraits<UserType>;
+
+ static_assert(std::is_same<Element, typename Traits::Element>::value,
+ "Incorrect array serializer");
+
+ static size_t GetSerializedSize(MaybeConstUserType& input,
+ SerializationContext* context) {
+ return sizeof(Data) +
+ Align(Traits::GetSize(input) * sizeof(typename Data::Element));
+ }
+
+ static void SerializeElements(MaybeConstUserType& input,
+ Buffer* buf,
+ Data* output,
+ const ArrayValidateParams* validate_params,
+ SerializationContext* context) {
+ DCHECK(!validate_params->element_validate_params)
+ << "Handle type should not have array validate params";
+
+ size_t size = Traits::GetSize(input);
+ for (size_t i = 0; i < size; ++i) {
+ // Transfer ownership of the handle.
+ output->at(i) =
+ context->handles.AddHandle(Traits::GetAt(input, i).release());
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ !validate_params->element_is_nullable && !output->at(i).is_valid(),
+ VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
+ MakeMessageWithArrayIndex(
+ "invalid handle in array expecting valid handles", size, i));
+ }
+ }
+ static bool DeserializeElements(Data* input,
+ UserType* output,
+ SerializationContext* context) {
+ using HandleType = typename Element::RawHandleType;
+ Traits::Resize(*output, input->size());
+ for (size_t i = 0; i < input->size(); ++i) {
+ Traits::GetAt(*output, i) = MakeScopedHandle(
+ HandleType(context->handles.TakeHandle(input->at(i)).value()));
+ }
+ return true;
+ }
+};
+
+// This template must only apply to pointer mojo entity (strings, structs,
+// arrays and maps).
+template <typename MojomType, typename MaybeConstUserType>
+struct ArraySerializer<MojomType,
+ MaybeConstUserType,
+ ArraySerializerType::POINTER> {
+ using UserType = typename std::remove_const<MaybeConstUserType>::type;
+ using Data = typename MojomType::Data_;
+ using DataElement = typename Data::Element;
+ using Element = typename MojomType::Element;
+ using Traits = ArrayTraits<UserType>;
+
+ static size_t GetSerializedSize(MaybeConstUserType& input,
+ SerializationContext* context) {
+ size_t element_count = Traits::GetSize(input);
+ 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);
+ return size;
+ }
+
+ static void SerializeElements(MaybeConstUserType& input,
+ Buffer* buf,
+ Data* output,
+ const ArrayValidateParams* validate_params,
+ SerializationContext* context) {
+ size_t size = Traits::GetSize(input);
+ for (size_t i = 0; i < size; ++i) {
+ DataElement element;
+ SerializeCaller<Element>::Run(Traits::GetAt(input, i), buf, &element,
+ validate_params->element_validate_params,
+ context);
+ output->at(i) = element;
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ !validate_params->element_is_nullable && !element,
+ VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
+ MakeMessageWithArrayIndex("null in array expecting valid pointers",
+ size, i));
+ }
+ }
+ static bool DeserializeElements(Data* input,
+ UserType* output,
+ SerializationContext* context) {
+ bool success = true;
+ Traits::Resize(*output, input->size());
+ for (size_t i = 0; i < input->size(); ++i) {
+ // Note that we rely on complete deserialization taking place in order to
+ // transfer ownership of all encoded handles. Therefore we don't
+ // short-circuit on failure here.
+ if (!Deserialize<Element>(input->at(i), &Traits::GetAt(*output, i),
+ context)) {
+ success = false;
+ }
+ }
+ return success;
+ }
+
+ private:
+ template <typename T,
+ bool is_array_or_map = IsSpecializationOf<Array, T>::value ||
+ IsSpecializationOf<Map, T>::value>
+ struct SerializeCaller {
+ template <typename InputElementType>
+ static void Run(InputElementType&& input,
+ Buffer* buf,
+ DataElement* output,
+ const ArrayValidateParams* validate_params,
+ SerializationContext* context) {
+ Serialize<T>(std::forward<InputElementType>(input), buf, output, context);
+ }
+ };
+
+ template <typename T>
+ struct SerializeCaller<T, true> {
+ template <typename InputElementType>
+ static void Run(InputElementType&& input,
+ Buffer* buf,
+ DataElement* output,
+ const ArrayValidateParams* validate_params,
+ SerializationContext* context) {
+ Serialize<T>(std::forward<InputElementType>(input), buf, output,
+ validate_params, context);
+ }
+ };
+};
+
+// Handles serialization and deserialization of arrays of unions.
+template <typename MojomType, typename MaybeConstUserType>
+struct ArraySerializer<MojomType,
+ MaybeConstUserType,
+ ArraySerializerType::UNION> {
+ using UserType = typename std::remove_const<MaybeConstUserType>::type;
+ using Data = typename MojomType::Data_;
+ using Traits = ArrayTraits<UserType>;
+
+ static_assert(std::is_same<typename MojomType::Element,
+ typename Traits::Element>::value,
+ "Incorrect array serializer");
+
+ static size_t GetSerializedSize(MaybeConstUserType& input,
+ SerializationContext* context) {
+ size_t element_count = Traits::GetSize(input);
+ size_t size = sizeof(Data);
+ for (size_t i = 0; i < element_count; ++i) {
+ // Call GetSerializedSize_ 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 += GetSerializedSize_(Traits::GetAt(input, i), false, context);
+ }
+ return size;
+ }
+
+ static void SerializeElements(MaybeConstUserType& input,
+ Buffer* buf,
+ Data* output,
+ const ArrayValidateParams* validate_params,
+ SerializationContext* context) {
+ size_t size = Traits::GetSize(input);
+ for (size_t i = 0; i < size; ++i) {
+ typename Data::Element* result = output->storage() + i;
+ SerializeUnion_(std::move(Traits::GetAt(input, i)), buf, &result, true,
+ context);
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ !validate_params->element_is_nullable && output->at(i).is_null(),
+ VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
+ MakeMessageWithArrayIndex("null in array expecting valid unions",
+ size, i));
+ }
+ }
+
+ static bool DeserializeElements(Data* input,
+ UserType* output,
+ SerializationContext* context) {
+ bool success = true;
+ Traits::Resize(*output, input->size());
+ for (size_t i = 0; i < input->size(); ++i) {
+ // Note that we rely on complete deserialization taking place in order to
+ // transfer ownership of all encoded handles. Therefore we don't
+ // short-circuit on failure here.
+ if (!Deserialize_(&input->at(i), &Traits::GetAt(*output, i), context))
+ success = false;
+ }
+ return success;
+ }
+};
+
+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 Traits = ArrayTraits<UserType>;
+ using Data = typename Array<Element>::Data_;
+
+ static size_t PrepareToSerialize(MaybeConstUserType& input,
+ SerializationContext* context) {
+ if (CallIsNullIfExists<Traits>(input))
+ return 0;
+ return Impl::GetSerializedSize(input, context);
+ }
+
+ static void Serialize(MaybeConstUserType& input,
+ Buffer* buf,
+ Data** output,
+ const ArrayValidateParams* validate_params,
+ SerializationContext* context) {
+ if (!CallIsNullIfExists<Traits>(input)) {
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ validate_params->expected_num_elements != 0 &&
+ Traits::GetSize(input) != validate_params->expected_num_elements,
+ internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
+ internal::MakeMessageWithExpectedArraySize(
+ "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);
+ *output = result;
+ } else {
+ *output = nullptr;
+ }
+ }
+
+ static bool Deserialize(Data* input,
+ UserType* output,
+ SerializationContext* context) {
+ if (input)
+ return Impl::DeserializeElements(input, output, context);
+ Traits::SetToNull(*output);
+ return true;
+ }
+};
+} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
« no previous file with comments | « mojo/public/cpp/bindings/BUILD.gn ('k') | mojo/public/cpp/bindings/lib/array_serialization_traits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698