* Change C++ serialization/deserialization to not be move-only operations (with the except of |Handle|, which is move-only). * Change deserialization of structs and unions to take in a pre-initialized struct instead of initializing it inside Deserialize_(). This is all related to issue #419. Details on what this change has: * Generated Serialize_(), SerializeArray_(), and related functions operate on pointers to their types, since these types are move-only. * Generated [De]Serialize_() for mojom structs and unions don't operate on |StructPtr|, but instead on |Struct*|. This is also true for Serialize[Array|Map]_(). * |Map| will uses iterator_util.h to help serialize its keys and values, instead of constructing an |Array| by moving its elements and calling SerializeArray_(). R=viettrungluu@chromium.org, jamesr@chromium.org Review URL: https://codereview.chromium.org/1358353002 .
diff --git a/mojo/public/cpp/bindings/lib/array_serialization.h b/mojo/public/cpp/bindings/lib/array_serialization.h index 9d0e7bb..dc98245 100644 --- a/mojo/public/cpp/bindings/lib/array_serialization.h +++ b/mojo/public/cpp/bindings/lib/array_serialization.h
@@ -6,33 +6,30 @@ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ #include <string.h> // For |memcpy()|. - #include <vector> #include "mojo/public/c/system/macros.h" #include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/map_serialization.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/bindings/lib/iterator_util.h" +#include "mojo/public/cpp/bindings/lib/map_data_internal.h" +#include "mojo/public/cpp/bindings/lib/map_serialization_forward.h" #include "mojo/public/cpp/bindings/lib/string_serialization.h" #include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" namespace mojo { - -template <typename E> -inline size_t GetSerializedSize_(const Array<E>& input); - -template <typename E, typename F> -inline void SerializeArray_( - Array<E> input, - internal::Buffer* buf, - internal::Array_Data<F>** output, - const internal::ArrayValidateParams* validate_params); - -template <typename E, typename F> -inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output); - namespace internal { +// The ArraySerializer template contains static methods for serializing |Array|s +// of various types. These methods include: +// * size_t GetSerializedSize(..) +// Computes the size of the serialized version of the |Array|. +// * void SerializeElements(..) +// Takes an |Iterator| and a size and serializes it. +// * void DeserializeElements(..) +// Takes a pointer to an |Array_Data| and deserializes it into a given +// |Array|. template <typename E, typename F, bool is_union = @@ -47,7 +44,9 @@ return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E)); } - static void SerializeElements(Array<E> input, + template <typename Iterator> + static void SerializeElements(Iterator it, + size_t num_elements, Buffer* buf, Array_Data<F>* output, const ArrayValidateParams* validate_params) { @@ -55,10 +54,25 @@ << "Primitive type should be non-nullable"; MOJO_DCHECK(!validate_params->element_validate_params) << "Primitive type should not have array validate params"; - - if (input.size()) - memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E)); + for (size_t i = 0; i < num_elements; ++i, ++it) + output->at(i) = *it; } + + // We can optimize serializing PODs by |memcpy|ing directly. + // Note that this has precedence over its templated sibling defined above. + static void SerializeElements(typename Array<E>::Iterator it, + size_t num_elements, + Buffer* buf, + Array_Data<F>* output, + const ArrayValidateParams* validate_params) { + MOJO_DCHECK(!validate_params->element_is_nullable) + << "Primitive type should be non-nullable"; + MOJO_DCHECK(!validate_params->element_validate_params) + << "Primitive type should not have array validate params"; + if (num_elements) + memcpy(output->storage(), &(*it), num_elements * sizeof(E)); + } + static void DeserializeElements(Array_Data<F>* input, Array<E>* output) { std::vector<E> result(input->size()); if (input->size()) @@ -74,7 +88,9 @@ return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8); } - static void SerializeElements(Array<bool> input, + template <typename Iterator> + static void SerializeElements(Iterator it, + size_t num_elements, Buffer* buf, Array_Data<bool>* output, const ArrayValidateParams* validate_params) { @@ -84,9 +100,10 @@ << "Primitive type should not have array validate params"; // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? - for (size_t i = 0; i < input.size(); ++i) - output->at(i) = input[i]; + for (size_t i = 0; i < num_elements; ++i, ++it) + output->at(i) = *it; } + static void DeserializeElements(Array_Data<bool>* input, Array<bool>* output) { Array<bool> result(input->size()); @@ -104,23 +121,27 @@ return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H)); } - static void SerializeElements(Array<ScopedHandleBase<H>> input, + template <typename Iterator> + static void SerializeElements(Iterator it, + size_t num_elements, Buffer* buf, Array_Data<H>* output, const ArrayValidateParams* validate_params) { MOJO_DCHECK(!validate_params->element_validate_params) << "Handle type should not have array validate params"; - for (size_t i = 0; i < input.size(); ++i) { - output->at(i) = input[i].release(); // Transfer ownership of the handle. + for (size_t i = 0; i < num_elements; ++i, ++it) { + // Transfer ownership of the handle. + output->at(i) = it->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", input.size(), + "invalid handle in array expecting valid handles", num_elements, i)); } } + static void DeserializeElements(Array_Data<H>* input, Array<ScopedHandleBase<H>>* output) { Array<ScopedHandleBase<H>> result(input->size()); @@ -130,8 +151,9 @@ } }; -// This template must only apply to pointer mojo entity (structs and arrays). -// This is done by ensuring that WrapperTraits<S>::DataType is a pointer. +// This template must only apply to pointer mojo entity (structs, arrays, +// strings). This is done by ensuring that WrapperTraits<S>::DataType is a +// pointer. template <typename S> struct ArraySerializer< S, @@ -144,66 +166,109 @@ size_t size = sizeof(Array_Data<S_Data*>) + input.size() * sizeof(StructPointer<S_Data>); for (size_t i = 0; i < input.size(); ++i) - size += GetSerializedSize_(input[i]); + size += GetSerializedSize_(*(UnwrapConstStructPtr<S>::value(input[i]))); return size; } - static void SerializeElements(Array<S> input, + template <typename Iterator> + static void SerializeElements(Iterator it, + size_t num_elements, Buffer* buf, Array_Data<S_Data*>* output, const ArrayValidateParams* validate_params) { - for (size_t i = 0; i < input.size(); ++i) { + for (size_t i = 0; i < num_elements; ++i, ++it) { S_Data* element; - SerializeCaller<S>::Run(input[i].Pass(), buf, &element, - validate_params->element_validate_params); + SerializeCaller::Run(&(*it), buf, &element, + validate_params->element_validate_params); 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", - input.size(), i)); + num_elements, i)); } } + static void DeserializeElements(Array_Data<S_Data*>* input, Array<S>* output) { Array<S> result(input->size()); for (size_t i = 0; i < input->size(); ++i) { - Deserialize_(input->at(i), &result[i]); + DeserializeCaller::Run(input->at(i), &result[i]); } output->Swap(&result); } private: - template <typename T> + // SerializeCaller template is used by |ArraySerializer| to dispatch a + // serialize call on a non-POD type. This template is defined outside + // |ArraySerializer| since you cannot specialize a struct within a class + // definition. struct SerializeCaller { - static void Run(T input, + // This template needs to be suppressed if |T| is |String|, otherwise it + // takes precedence over the |String|-overloaded Run() below. + template <typename T, + typename = typename EnableIf<!IsSame<T, String>::value, T>::type> + static void Run(T* input, Buffer* buf, typename WrapperTraits<T>::DataType* output, const ArrayValidateParams* validate_params) { MOJO_DCHECK(!validate_params) << "Struct type should not have array validate params"; - - Serialize_(input.Pass(), buf, output); + Serialize_(UnwrapStructPtr<T>::value(*input), buf, output); } - }; - template <typename T> - struct SerializeCaller<Array<T>> { - static void Run(Array<T> input, + static void Run(const String* input, + Buffer* buf, + String_Data** output, + const ArrayValidateParams* validate_params) { + MOJO_DCHECK(validate_params && + !validate_params->element_validate_params && + !validate_params->element_is_nullable && + validate_params->expected_num_elements == 0) + << "String type has unexpected array validate params"; + SerializeString_(*input, buf, output); + } + + template <typename T> + static void Run(Array<T>* input, Buffer* buf, typename Array<T>::Data_** output, const ArrayValidateParams* validate_params) { - SerializeArray_(input.Pass(), buf, output, validate_params); + SerializeArray_(input, buf, output, validate_params); + } + + template <typename Key, typename Value> + static void Run(Map<Key, Value>* input, + Buffer* buf, + typename Map<Key, Value>::Data_** output, + const ArrayValidateParams* validate_params) { + SerializeMap_(input, buf, output, validate_params); } }; - template <typename T, typename U> - struct SerializeCaller<Map<T, U>> { - static void Run(Map<T, U> input, - Buffer* buf, - typename Map<T, U>::Data_** output, - const ArrayValidateParams* validate_params) { - SerializeMap_(input.Pass(), buf, output, validate_params); + struct DeserializeCaller { + template <typename T> + static void Run(typename WrapperTraits<T>::DataType input, T* output) { + Deserialize_(input, output); + } + + // Since Deserialize_ takes in a |Struct*| (not |StructPtr|), we need to + // initialize the |StructPtr| here before deserializing into its underlying + // data. + // TODO(vardhan): Either all containers, or just Deserialize_(), should + // support taking in an allocator. + template <typename T> + static void Run(typename WrapperTraits<StructPtr<T>>::DataType input, + StructPtr<T>* output) { + *output = T::New(); + Deserialize_(input, output->get()); + } + + template <typename T> + static void Run(typename WrapperTraits<InlinedStructPtr<T>>::DataType input, + InlinedStructPtr<T>* output) { + *output = T::New(); + Deserialize_(input, output->get()); } }; }; @@ -221,72 +286,37 @@ return size; } - static void SerializeElements(Array<U> input, + template <typename Iterator> + static void SerializeElements(Iterator it, + size_t num_elements, Buffer* buf, Array_Data<U_Data>* output, const ArrayValidateParams* validate_params) { - for (size_t i = 0; i < input.size(); ++i) { + for (size_t i = 0; i < num_elements; ++i, ++it) { U_Data* result = output->storage() + i; - SerializeUnion_(input[i].Pass(), buf, &result, true); + SerializeUnion_(it->get(), buf, &result, true); 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", - input.size(), i)); + num_elements, i)); } } static void DeserializeElements(Array_Data<U_Data>* input, Array<U>* output) { Array<U> result(input->size()); for (size_t i = 0; i < input->size(); ++i) { - Deserialize_(&input->at(i), &result[i]); + auto& elem = input->at(i); + if (!elem.is_null()) { + using UnwrapedUnionType = typename RemoveStructPtr<U>::type; + result[i] = UnwrapedUnionType::New(); + Deserialize_(&elem, result[i].get()); + } } output->Swap(&result); } }; -// Handles serialization and deserialization of arrays of strings. -template <> -struct ArraySerializer<String, String_Data*> { - static size_t GetSerializedSize(const Array<String>& input) { - size_t size = - sizeof(Array_Data<String_Data*>) + input.size() * sizeof(StringPointer); - for (size_t i = 0; i < input.size(); ++i) - size += GetSerializedSize_(input[i]); - return size; - } - - static void SerializeElements(Array<String> input, - Buffer* buf, - Array_Data<String_Data*>* output, - const ArrayValidateParams* validate_params) { - MOJO_DCHECK( - validate_params->element_validate_params && - !validate_params->element_validate_params->element_validate_params && - !validate_params->element_validate_params->element_is_nullable && - validate_params->element_validate_params->expected_num_elements == 0) - << "String type has unexpected array validate params"; - - for (size_t i = 0; i < input.size(); ++i) { - String_Data* element; - Serialize_(input[i], buf, &element); - 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 strings", - input.size(), i)); - } - } - static void DeserializeElements(Array_Data<String_Data*>* input, - Array<String>* output) { - Array<String> result(input->size()); - for (size_t i = 0; i < input->size(); ++i) - Deserialize_(input->at(i), &result[i]); - output->Swap(&result); - } -}; - } // namespace internal template <typename E> @@ -299,24 +329,25 @@ template <typename E, typename F> inline void SerializeArray_( - Array<E> input, + Array<E>* input, internal::Buffer* buf, internal::Array_Data<F>** output, const internal::ArrayValidateParams* validate_params) { - if (input) { + MOJO_DCHECK(input); + if (*input) { MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( validate_params->expected_num_elements != 0 && - input.size() != validate_params->expected_num_elements, + input->size() != validate_params->expected_num_elements, internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, internal::MakeMessageWithExpectedArraySize( - "fixed-size array has wrong number of elements", input.size(), + "fixed-size array has wrong number of elements", input->size(), validate_params->expected_num_elements)); internal::Array_Data<F>* result = - internal::Array_Data<F>::New(input.size(), buf); + internal::Array_Data<F>::New(input->size(), buf); if (result) { internal::ArraySerializer<E, F>::SerializeElements( - internal::Forward(input), buf, result, validate_params); + input->begin(), input->size(), buf, result, validate_params); } *output = result; } else {
diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h index bb7347e..e0a3939 100644 --- a/mojo/public/cpp/bindings/lib/bindings_internal.h +++ b/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -105,6 +105,42 @@ }; template <typename T> +struct UnwrapStructPtr { + static T* value(T& x) { return &x; } +}; + +template <typename T> +struct UnwrapStructPtr<StructPtr<T>> { + static T* value(StructPtr<T>& x) { return x.get(); } +}; + +template <typename T> +struct UnwrapStructPtr<InlinedStructPtr<T>> { + static T* value(InlinedStructPtr<T>& x) { return x.get(); } +}; + +template <typename T> +struct UnwrapConstStructPtr { + static const T* value(const T& x) { return &x; } +}; + +template <typename T> +struct UnwrapConstStructPtr<StructPtr<T>> { + static const T* value(const StructPtr<T>& x) { return x.get(); } +}; + +template <typename T> +struct UnwrapConstStructPtr<InlinedStructPtr<T>> { + static const T* value(const InlinedStructPtr<T>& x) { return x.get(); } +}; + +template <typename T> +struct IsStructPtr { + static bool const value = IsSpecializationOf<StructPtr, T>::value || + IsSpecializationOf<InlinedStructPtr, T>::value; +}; + +template <typename T> struct IsUnionWrapperType { template <typename U> static YesType Test(const typename U::Data_::MojomUnionDataType*);
diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.cc b/mojo/public/cpp/bindings/lib/control_message_handler.cc index 5113bb0..4e7efc8 100644 --- a/mojo/public/cpp/bindings/lib/control_message_handler.cc +++ b/mojo/public/cpp/bindings/lib/control_message_handler.cc
@@ -51,11 +51,11 @@ response_params_ptr->query_version_result = QueryVersionResult::New(); response_params_ptr->query_version_result->version = interface_version_; - size_t size = GetSerializedSize_(response_params_ptr); + size_t size = GetSerializedSize_(*response_params_ptr); ResponseMessageBuilder builder(kRunMessageId, size, message->request_id()); RunResponseMessageParams_Data* response_params = nullptr; - Serialize_(response_params_ptr.Pass(), builder.buffer(), &response_params); + Serialize_(response_params_ptr.get(), builder.buffer(), &response_params); response_params->EncodePointersAndHandles( builder.message()->mutable_handles()); bool ok = responder->Accept(builder.message()); @@ -71,8 +71,8 @@ message->mutable_payload()); params->DecodePointersAndHandles(message->mutable_handles()); - RunOrClosePipeMessageParamsPtr params_ptr; - Deserialize_(params, ¶ms_ptr); + RunOrClosePipeMessageParamsPtr params_ptr(RunOrClosePipeMessageParams::New()); + Deserialize_(params, params_ptr.get()); return interface_version_ >= params_ptr->require_version->version; }
diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/mojo/public/cpp/bindings/lib/control_message_proxy.cc index ad729c5..ee1e695 100644 --- a/mojo/public/cpp/bindings/lib/control_message_proxy.cc +++ b/mojo/public/cpp/bindings/lib/control_message_proxy.cc
@@ -33,8 +33,8 @@ message->mutable_payload()); params->DecodePointersAndHandles(message->mutable_handles()); - RunResponseMessageParamsPtr params_ptr; - Deserialize_(params, ¶ms_ptr); + RunResponseMessageParamsPtr params_ptr(RunResponseMessageParams::New()); + Deserialize_(params, params_ptr.get()); callback_.Run(params_ptr->query_version_result.Pass()); return true; @@ -48,11 +48,11 @@ params_ptr->reserved1 = 0u; params_ptr->query_version = query_version.Pass(); - size_t size = GetSerializedSize_(params_ptr); + size_t size = GetSerializedSize_(*params_ptr); RequestMessageBuilder builder(kRunMessageId, size); RunMessageParams_Data* params = nullptr; - Serialize_(params_ptr.Pass(), builder.buffer(), ¶ms); + Serialize_(params_ptr.get(), builder.buffer(), ¶ms); params->EncodePointersAndHandles(builder.message()->mutable_handles()); MessageReceiver* responder = new RunResponseForwardToCallback(callback); if (!receiver->AcceptWithResponder(builder.message(), responder)) @@ -66,11 +66,11 @@ params_ptr->reserved1 = 0u; params_ptr->require_version = require_version.Pass(); - size_t size = GetSerializedSize_(params_ptr); + size_t size = GetSerializedSize_(*params_ptr); MessageBuilder builder(kRunOrClosePipeMessageId, size); RunOrClosePipeMessageParams_Data* params = nullptr; - Serialize_(params_ptr.Pass(), builder.buffer(), ¶ms); + Serialize_(params_ptr.get(), builder.buffer(), ¶ms); params->EncodePointersAndHandles(builder.message()->mutable_handles()); bool ok = receiver->Accept(builder.message()); MOJO_ALLOW_UNUSED_LOCAL(ok);
diff --git a/mojo/public/cpp/bindings/lib/map_internal.h b/mojo/public/cpp/bindings/lib/map_internal.h index 84f927c..cf3f0d9 100644 --- a/mojo/public/cpp/bindings/lib/map_internal.h +++ b/mojo/public/cpp/bindings/lib/map_internal.h
@@ -40,20 +40,6 @@ for (size_t i = 0; i < keys.size(); ++i) Insert(m, keys[i], values[i]); } - static inline void Decompose(std::map<KeyStorageType, ValueStorageType>* m, - mojo::Array<Key>* keys, - mojo::Array<Value>* values) { - keys->resize(m->size()); - values->resize(m->size()); - int i = 0; - for (typename std::map<KeyStorageType, ValueStorageType>::iterator - it = m->begin(); - it != m->end(); - ++it, ++i) { - (*keys)[i] = it->first; - (*values)[i] = it->second; - } - } static inline void Finalize(std::map<KeyStorageType, ValueStorageType>* m) {} static inline ValueRefType at(std::map<KeyStorageType, ValueStorageType>* m, KeyForwardType key) { @@ -133,20 +119,6 @@ for (size_t i = 0; i < keys.size(); ++i) Insert(m, keys[i], values[i]); } - static inline void Decompose(std::map<KeyStorageType, ValueStorageType>* m, - mojo::Array<Key>* keys, - mojo::Array<Value>* values) { - keys->resize(m->size()); - values->resize(m->size()); - int i = 0; - for (typename std::map<KeyStorageType, ValueStorageType>::iterator - it = m->begin(); - it != m->end(); - ++it, ++i) { - (*keys)[i] = it->first; - (*values)[i] = GetValue(it).Pass(); - } - } static inline void Finalize(std::map<KeyStorageType, ValueStorageType>* m) { for (auto& pair : *m) reinterpret_cast<Value*>(pair.second.buf)->~Value();
diff --git a/mojo/public/cpp/bindings/lib/map_serialization.h b/mojo/public/cpp/bindings/lib/map_serialization.h index 7ca177d..8ef83b3 100644 --- a/mojo/public/cpp/bindings/lib/map_serialization.h +++ b/mojo/public/cpp/bindings/lib/map_serialization.h
@@ -6,23 +6,15 @@ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ #include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/bindings/lib/array_serialization.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/bindings/lib/iterator_util.h" #include "mojo/public/cpp/bindings/lib/map_data_internal.h" #include "mojo/public/cpp/bindings/lib/map_internal.h" #include "mojo/public/cpp/bindings/lib/string_serialization.h" #include "mojo/public/cpp/bindings/map.h" namespace mojo { - -template <typename Key, typename Value> -inline size_t GetSerializedSize_(const Map<Key, Value>& input); - -template <typename ValidateParams, typename E, typename F> -inline void SerializeArray_( - Array<E> input, - internal::Buffer* buf, - internal::Array_Data<F>** output, - const internal::ArrayValidateParams* validate_params); - namespace internal { template <typename MapType, @@ -70,7 +62,9 @@ static size_t GetBaseArraySize(size_t count) { return count * sizeof(StructPointer<S_Data>); } - static size_t GetItemSize(const S& item) { return GetSerializedSize_(item); } + static size_t GetItemSize(const S& item) { + return GetSerializedSize_(*UnwrapConstStructPtr<S>::value(item)); + } }; template <typename U, typename U_Data> @@ -135,22 +129,39 @@ typename DataKey, typename DataValue> inline void SerializeMap_( - Map<MapKey, MapValue> input, + Map<MapKey, MapValue>* input, internal::Buffer* buf, internal::Map_Data<DataKey, DataValue>** output, const internal::ArrayValidateParams* value_validate_params) { - if (input) { + if (input && *input) { internal::Map_Data<DataKey, DataValue>* result = internal::Map_Data<DataKey, DataValue>::New(buf); - if (result) { - Array<MapKey> keys; - Array<MapValue> values; - input.DecomposeMapTo(&keys, &values); + internal::Array_Data<DataKey>* keys_data = + internal::Array_Data<DataKey>::New(input->size(), buf); + + if (result && keys_data) { + result->keys.ptr = keys_data; + + // We *must* serialize the keys before we allocate an Array_Data for the + // values. + internal::MapKeyIterator<MapKey, MapValue> key_iter(input); const internal::ArrayValidateParams* key_validate_params = internal::MapKeyValidateParamsFactory<DataKey>::Get(); - SerializeArray_(keys.Pass(), buf, &result->keys.ptr, key_validate_params); - SerializeArray_(values.Pass(), buf, &result->values.ptr, - value_validate_params); + + internal::ArraySerializer<MapKey, DataKey>::SerializeElements( + key_iter.begin(), input->size(), buf, result->keys.ptr, + key_validate_params); + + // Now we try allocate an Array_Data for the values + internal::Array_Data<DataValue>* values_data = + internal::Array_Data<DataValue>::New(input->size(), buf); + if (values_data) { + result->values.ptr = values_data; + internal::MapValueIterator<MapKey, MapValue> value_iter(input); + internal::ArraySerializer<MapValue, DataValue>::SerializeElements( + value_iter.begin(), input->size(), buf, result->values.ptr, + value_validate_params); + } } *output = result; } else {
diff --git a/mojo/public/cpp/bindings/lib/map_serialization_forward.h b/mojo/public/cpp/bindings/lib/map_serialization_forward.h new file mode 100644 index 0000000..40f6e8e --- /dev/null +++ b/mojo/public/cpp/bindings/lib/map_serialization_forward.h
@@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Headers such as array_serialization.h can include this file to avoid circular +// dependencies on map_serialization.h. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_FORWARD_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_FORWARD_H_ + +namespace mojo { +namespace internal { + +class ArrayValidateParams; +class Buffer; + +template <typename Key, typename Value> +class Map_Data; + +} // namespace internal + +template <typename Key, typename Value> +class Map; + +template <typename MapKey, + typename MapValue, + typename DataKey, + typename DataValue> +void SerializeMap_(Map<MapKey, MapValue>* input, + internal::Buffer* buf, + internal::Map_Data<DataKey, DataValue>** output, + const internal::ArrayValidateParams* value_validate_params); +template <typename MapKey, typename MapValue> +size_t GetSerializedSize_(const Map<MapKey, MapValue>& input); + +template <typename MapKey, + typename MapValue, + typename DataKey, + typename DataValue> +void Deserialize_(internal::Map_Data<DataKey, DataValue>* input, + Map<MapKey, MapValue>* output); + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_FORWARD_H_
diff --git a/mojo/public/cpp/bindings/lib/string_serialization.cc b/mojo/public/cpp/bindings/lib/string_serialization.cc index e29d6f8..11c8e77 100644 --- a/mojo/public/cpp/bindings/lib/string_serialization.cc +++ b/mojo/public/cpp/bindings/lib/string_serialization.cc
@@ -14,9 +14,9 @@ return internal::Align(sizeof(internal::String_Data) + input.size()); } -void Serialize_(const String& input, - internal::Buffer* buf, - internal::String_Data** output) { +void SerializeString_(const String& input, + internal::Buffer* buf, + internal::String_Data** output) { if (input) { internal::String_Data* result = internal::String_Data::New(input.size(), buf);
diff --git a/mojo/public/cpp/bindings/lib/string_serialization.h b/mojo/public/cpp/bindings/lib/string_serialization.h index 0118742..20b53b2 100644 --- a/mojo/public/cpp/bindings/lib/string_serialization.h +++ b/mojo/public/cpp/bindings/lib/string_serialization.h
@@ -11,9 +11,10 @@ namespace mojo { size_t GetSerializedSize_(const String& input); -void Serialize_(const String& input, - internal::Buffer* buffer, - internal::String_Data** output); +void SerializeString_(const String& input, + internal::Buffer* buffer, + internal::String_Data** output); + void Deserialize_(internal::String_Data* input, String* output); } // namespace mojo
diff --git a/mojo/public/cpp/bindings/map.h b/mojo/public/cpp/bindings/map.h index f59f2f4..3a358e6 100644 --- a/mojo/public/cpp/bindings/map.h +++ b/mojo/public/cpp/bindings/map.h
@@ -135,18 +135,6 @@ map_.swap(*other); } - // Removes all contents from the Map and places them into parallel key/value - // arrays. Each key will be copied from the source to the destination, and - // values will be copied unless their type is designated move-only, in which - // case they will be passed by calling their Pass() method. Either way, the - // Map will be left in a null state. - void DecomposeMapTo(mojo::Array<Key>* keys, mojo::Array<Value>* values) { - Traits::Decompose(&map_, keys, values); - Traits::Finalize(&map_); - map_.clear(); - is_null_ = true; - } - // Returns a new Map that contains a copy of the contents of this map. If the // values are of a type that is designated move-only, they will be cloned // using the Clone() method of the type. Please note that calling this method
diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h index 04a8130..b47a1ed 100644 --- a/mojo/public/cpp/bindings/struct_ptr.h +++ b/mojo/public/cpp/bindings/struct_ptr.h
@@ -150,7 +150,7 @@ MOJO_DCHECK(!is_null_); return &value_; } - Struct* get() const { return &value_; } + Struct* get() const { return is_null() ? nullptr : &value_; } void Swap(InlinedStructPtr* other) { std::swap(value_, other->value_);
diff --git a/mojo/public/cpp/bindings/tests/array_unittest.cc b/mojo/public/cpp/bindings/tests/array_unittest.cc index bdfc4a1..ffee9cc 100644 --- a/mojo/public/cpp/bindings/tests/array_unittest.cc +++ b/mojo/public/cpp/bindings/tests/array_unittest.cc
@@ -161,7 +161,7 @@ FixedBufferForTesting buf(size); Array_Data<int32_t>* data; ArrayValidateParams validate_params(0, false, nullptr); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<int32_t> array2; Deserialize_(data, &array2); @@ -179,7 +179,7 @@ FixedBufferForTesting buf(size); Array_Data<int32_t>* data; ArrayValidateParams validate_params(0, false, nullptr); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<int32_t> array2; Deserialize_(data, &array2); @@ -202,7 +202,7 @@ Array_Data<Array_Data<int32_t>*>* data; ArrayValidateParams validate_params( 0, false, new ArrayValidateParams(0, false, nullptr)); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<Array<int32_t>> array2; Deserialize_(data, &array2); @@ -227,7 +227,7 @@ FixedBufferForTesting buf(size); Array_Data<bool>* data; ArrayValidateParams validate_params(0, false, nullptr); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<bool> array2; Deserialize_(data, &array2); @@ -255,7 +255,7 @@ Array_Data<String_Data*>* data; ArrayValidateParams validate_params( 0, false, new ArrayValidateParams(0, false, nullptr)); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<String> array2; Deserialize_(data, &array2);
diff --git a/mojo/public/cpp/bindings/tests/map_unittest.cc b/mojo/public/cpp/bindings/tests/map_unittest.cc index 44100a4..9a15253 100644 --- a/mojo/public/cpp/bindings/tests/map_unittest.cc +++ b/mojo/public/cpp/bindings/tests/map_unittest.cc
@@ -6,6 +6,7 @@ #include "mojo/public/cpp/bindings/lib/array_serialization.h" #include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" +#include "mojo/public/cpp/bindings/lib/map_serialization.h" #include "mojo/public/cpp/bindings/lib/validate_params.h" #include "mojo/public/cpp/bindings/map.h" #include "mojo/public/cpp/bindings/string.h" @@ -115,44 +116,6 @@ } } -TEST_F(MapTest, DecomposeMapTo) { - Array<String> keys(kStringIntDataSize); - Array<int> values(kStringIntDataSize); - for (size_t i = 0; i < kStringIntDataSize; ++i) { - keys[i] = kStringIntData[i].string_data; - values[i] = kStringIntData[i].int_data; - } - - Map<String, int> map(keys.Pass(), values.Pass()); - EXPECT_EQ(kStringIntDataSize, map.size()); - - Array<String> keys2; - Array<int> values2; - map.DecomposeMapTo(&keys2, &values2); - EXPECT_EQ(0u, map.size()); - - EXPECT_EQ(kStringIntDataSize, keys2.size()); - EXPECT_EQ(kStringIntDataSize, values2.size()); - - for (size_t i = 0; i < kStringIntDataSize; ++i) { - // We are not guaranteed that the copies have the same sorting as the - // originals. - String key = kStringIntData[i].string_data; - int value = kStringIntData[i].int_data; - - bool found = false; - for (size_t j = 0; j < keys2.size(); ++j) { - if (keys2[j] == key) { - EXPECT_EQ(value, values2[j]); - found = true; - break; - } - } - - EXPECT_TRUE(found); - } -} - TEST_F(MapTest, Insert_Copyable) { ASSERT_EQ(0u, CopyableType::num_instances()); mojo::Map<mojo::String, CopyableType> map; @@ -283,7 +246,7 @@ Array_Data<Map_Data<int32_t, int8_t>*>* data; ArrayValidateParams validate_params( 0, false, new ArrayValidateParams(0, false, nullptr)); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<Map<int32_t, int8_t>> deserialized_array; Deserialize_(data, &deserialized_array); @@ -306,7 +269,7 @@ ArrayValidateParams validate_params( 0, false, new ArrayValidateParams( 0, false, new ArrayValidateParams(0, false, nullptr))); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<Map<String, Array<bool>>> deserialized_array; Deserialize_(data, &deserialized_array);
diff --git a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc index 43955cb..b61d3bc 100644 --- a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc +++ b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
@@ -59,9 +59,9 @@ mojo::internal::ValidationError expected_warning) { warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE); - mojo::internal::FixedBufferForTesting buf(GetSerializedSize_(obj)); + mojo::internal::FixedBufferForTesting buf(GetSerializedSize_(*obj)); typename T::Data_* data; - Serialize_(obj.Pass(), &buf, &data); + Serialize_(obj.get(), &buf, &data); EXPECT_EQ(expected_warning, warning_observer_.last_warning()); } @@ -74,7 +74,7 @@ mojo::internal::FixedBufferForTesting buf(GetSerializedSize_(obj)); typename T::Data_* data; - SerializeArray_(obj.Pass(), &buf, &data, validate_params); + SerializeArray_(&obj, &buf, &data, validate_params); EXPECT_EQ(expected_warning, warning_observer_.last_warning()); }
diff --git a/mojo/public/cpp/bindings/tests/struct_unittest.cc b/mojo/public/cpp/bindings/tests/struct_unittest.cc index 71069d2..283dd8e 100644 --- a/mojo/public/cpp/bindings/tests/struct_unittest.cc +++ b/mojo/public/cpp/bindings/tests/struct_unittest.cc
@@ -51,10 +51,10 @@ typedef typename mojo::internal::WrapperTraits<T>::DataType InputDataType; typedef typename mojo::internal::WrapperTraits<U>::DataType OutputDataType; - size_t size = GetSerializedSize_(input); + size_t size = GetSerializedSize_(*input); mojo::internal::FixedBufferForTesting buf(size + 32); InputDataType data; - Serialize_(input.Pass(), &buf, &data); + Serialize_(input.get(), &buf, &data); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -67,8 +67,9 @@ OutputDataType output_data = reinterpret_cast<OutputDataType>(data); output_data->DecodePointersAndHandles(&handles); - U output; - Deserialize_(output_data, &output); + using RawUType = typename mojo::internal::RemoveStructPtr<U>::type; + U output(RawUType::New()); + Deserialize_(output_data, output.get()); return output.Pass(); } @@ -138,15 +139,15 @@ TEST_F(StructTest, Serialization_Basic) { RectPtr rect(MakeRect()); - size_t size = GetSerializedSize_(rect); + size_t size = GetSerializedSize_(*rect); EXPECT_EQ(8U + 16U, size); mojo::internal::FixedBufferForTesting buf(size); internal::Rect_Data* data; - Serialize_(rect.Pass(), &buf, &data); + Serialize_(rect.get(), &buf, &data); - RectPtr rect2; - Deserialize_(data, &rect2); + RectPtr rect2(Rect::New()); + Deserialize_(data, rect2.get()); CheckRect(*rect2); } @@ -171,15 +172,15 @@ pair->first = MakeRect(); pair->second = MakeRect(); - size_t size = GetSerializedSize_(pair); + size_t size = GetSerializedSize_(*pair); EXPECT_EQ(8U + 16U + 2 * (8U + 16U), size); mojo::internal::FixedBufferForTesting buf(size); internal::RectPair_Data* data; - Serialize_(pair.Pass(), &buf, &data); + Serialize_(pair.get(), &buf, &data); - RectPairPtr pair2; - Deserialize_(data, &pair2); + RectPairPtr pair2(RectPair::New()); + Deserialize_(data, pair2.get()); CheckRect(*pair2->first); CheckRect(*pair2->second); @@ -193,7 +194,7 @@ for (size_t i = 0; i < region->rects.size(); ++i) region->rects[i] = MakeRect(static_cast<int32_t>(i) + 1); - size_t size = GetSerializedSize_(region); + size_t size = GetSerializedSize_(*region); EXPECT_EQ(8U + // header 8U + // name pointer 8U + // rects pointer @@ -207,10 +208,10 @@ mojo::internal::FixedBufferForTesting buf(size); internal::NamedRegion_Data* data; - Serialize_(region.Pass(), &buf, &data); + Serialize_(region.get(), &buf, &data); - NamedRegionPtr region2; - Deserialize_(data, ®ion2); + NamedRegionPtr region2(NamedRegion::New()); + Deserialize_(data, region2.get()); EXPECT_EQ(String("region"), region2->name); @@ -225,7 +226,7 @@ EXPECT_TRUE(region->name.is_null()); EXPECT_TRUE(region->rects.is_null()); - size_t size = GetSerializedSize_(region); + size_t size = GetSerializedSize_(*region); EXPECT_EQ(8U + // header 8U + // name pointer 8U, // rects pointer @@ -233,10 +234,10 @@ mojo::internal::FixedBufferForTesting buf(size); internal::NamedRegion_Data* data; - Serialize_(region.Pass(), &buf, &data); + Serialize_(region.get(), &buf, &data); - NamedRegionPtr region2; - Deserialize_(data, ®ion2); + NamedRegionPtr region2(NamedRegion::New()); + Deserialize_(data, region2.get()); EXPECT_TRUE(region2->name.is_null()); EXPECT_TRUE(region2->rects.is_null());
diff --git a/mojo/public/cpp/bindings/tests/union_unittest.cc b/mojo/public/cpp/bindings/tests/union_unittest.cc index b09957b..e79ea9f 100644 --- a/mojo/public/cpp/bindings/tests/union_unittest.cc +++ b/mojo/public/cpp/bindings/tests/union_unittest.cc
@@ -9,6 +9,7 @@ #include "mojo/public/cpp/bindings/lib/array_serialization.h" #include "mojo/public/cpp/bindings/lib/bounds_checker.h" #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" +#include "mojo/public/cpp/bindings/lib/map_serialization.h" #include "mojo/public/cpp/bindings/string.h" #include "mojo/public/cpp/environment/environment.h" #include "mojo/public/cpp/test_support/test_utils.h" @@ -122,10 +123,10 @@ mojo::internal::FixedBufferForTesting buf(size); internal::PodUnion_Data* data = nullptr; - SerializeUnion_(pod1.Pass(), &buf, &data, false); + SerializeUnion_(pod1.get(), &buf, &data, false); - PodUnionPtr pod2; - Deserialize_(data, &pod2); + PodUnionPtr pod2(PodUnion::New()); + Deserialize_(data, pod2.get()); EXPECT_EQ(10, pod2->get_f_int8()); EXPECT_TRUE(pod2->is_f_int8()); @@ -141,10 +142,10 @@ mojo::internal::FixedBufferForTesting buf(size); internal::PodUnion_Data* data = nullptr; - SerializeUnion_(pod1.Pass(), &buf, &data, false); + SerializeUnion_(pod1.get(), &buf, &data, false); - PodUnionPtr pod2; - Deserialize_(data, &pod2); + PodUnionPtr pod2 = PodUnion::New(); + Deserialize_(data, pod2.get()); EXPECT_EQ(AN_ENUM_SECOND, pod2->get_f_enum()); EXPECT_TRUE(pod2->is_f_enum()); @@ -160,7 +161,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::PodUnion_Data* data = nullptr; - SerializeUnion_(pod.Pass(), &buf, &data, false); + SerializeUnion_(pod.get(), &buf, &data, false); void* raw_buf = buf.Leak(); mojo::internal::BoundsChecker bounds_checker(data, static_cast<uint32_t>(size), 0); @@ -175,7 +176,7 @@ size_t size = GetSerializedSize_(pod, false); mojo::internal::FixedBufferForTesting buf(size); internal::PodUnion_Data* data = nullptr; - SerializeUnion_(pod.Pass(), &buf, &data, false); + SerializeUnion_(pod.get(), &buf, &data, false); EXPECT_FALSE(data->is_null()); } @@ -191,12 +192,12 @@ data->tag = PodUnion::Tag::F_UINT16; data->data.f_f_int16 = 20; - SerializeUnion_(pod.Pass(), &buf, &data, true); + SerializeUnion_(pod.get(), &buf, &data, true); EXPECT_TRUE(data->is_null()); - PodUnionPtr pod2; - Deserialize_(data, &pod2); - EXPECT_TRUE(pod2.is_null()); + PodUnionPtr pod2 = PodUnion::New(); + Deserialize_(data, pod2.get()); + EXPECT_EQ(pod2->which(), PodUnion::Tag::__UNKNOWN__); } TEST(UnionTest, SerializeIsNullNotInlined) { @@ -205,7 +206,7 @@ EXPECT_EQ(16U, size); mojo::internal::FixedBufferForTesting buf(size); internal::PodUnion_Data* data = nullptr; - SerializeUnion_(pod.Pass(), &buf, &data, false); + SerializeUnion_(pod.get(), &buf, &data, false); EXPECT_EQ(nullptr, data); } @@ -252,8 +253,8 @@ data->size = size; data->tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100); - PodUnionPtr pod2; - Deserialize_(data, &pod2); + PodUnionPtr pod2 = PodUnion::New(); + Deserialize_(data, pod2.get()); EXPECT_TRUE(pod2->has_unknown_tag()); } @@ -315,14 +316,14 @@ size_t size = GetSerializedSize_(pod1, false); mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(pod1.Pass(), &buf, &data, false); + SerializeUnion_(pod1.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); data->DecodePointersAndHandles(&handles); - ObjectUnionPtr pod2; - Deserialize_(data, &pod2); + ObjectUnionPtr pod2 = ObjectUnion::New(); + Deserialize_(data, pod2.get()); EXPECT_EQ(hello, pod2->get_f_string()); EXPECT_TRUE(pod2->is_f_string()); EXPECT_EQ(pod2->which(), ObjectUnion::Tag::F_STRING); @@ -409,7 +410,7 @@ mojo::internal::FixedBufferForTesting buf(size); mojo::internal::Array_Data<internal::PodUnion_Data>* data; mojo::internal::ArrayValidateParams validate_params(0, false, nullptr); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<PodUnionPtr> array2; Deserialize_(data, &array2); @@ -434,7 +435,7 @@ mojo::internal::FixedBufferForTesting buf(size); mojo::internal::Array_Data<internal::PodUnion_Data>* data; mojo::internal::ArrayValidateParams validate_params(0, false, nullptr); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); void* raw_buf = buf.Leak(); mojo::internal::BoundsChecker bounds_checker(data, @@ -458,7 +459,7 @@ mojo::internal::FixedBufferForTesting buf(size); mojo::internal::Array_Data<internal::PodUnion_Data>* data; mojo::internal::ArrayValidateParams validate_params(0, true, nullptr); - SerializeArray_(array.Pass(), &buf, &data, &validate_params); + SerializeArray_(&array, &buf, &data, &validate_params); Array<PodUnionPtr> array2; Deserialize_(data, &array2); @@ -488,14 +489,14 @@ small_struct->pod_union = PodUnion::New(); small_struct->pod_union->set_f_int32(10); - size_t size = GetSerializedSize_(small_struct); + size_t size = GetSerializedSize_(*small_struct); mojo::internal::FixedBufferForTesting buf(size); internal::SmallStruct_Data* data = nullptr; - Serialize_(small_struct.Pass(), &buf, &data); + Serialize_(small_struct.get(), &buf, &data); - SmallStructPtr deserialized; - Deserialize_(data, &deserialized); + SmallStructPtr deserialized(SmallStruct::New()); + Deserialize_(data, deserialized.get()); EXPECT_EQ(10, deserialized->pod_union->get_f_int32()); } @@ -508,18 +509,18 @@ String hello("hello world"); obj_struct->obj_union->set_f_string(hello); - size_t size = GetSerializedSize_(obj_struct); + size_t size = GetSerializedSize_(*obj_struct); mojo::internal::FixedBufferForTesting buf(size); internal::SmallObjStruct_Data* data = nullptr; - Serialize_(obj_struct.Pass(), &buf, &data); + Serialize_(obj_struct.get(), &buf, &data); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); data->DecodePointersAndHandles(&handles); - SmallObjStructPtr deserialized; - Deserialize_(data, &deserialized); + SmallObjStructPtr deserialized(SmallObjStruct::New()); + Deserialize_(data, deserialized.get()); EXPECT_EQ(hello, deserialized->obj_union->get_f_string()); } @@ -531,11 +532,11 @@ small_struct->pod_union = PodUnion::New(); small_struct->pod_union->set_f_int32(10); - size_t size = GetSerializedSize_(small_struct); + size_t size = GetSerializedSize_(*small_struct); mojo::internal::FixedBufferForTesting buf(size); internal::SmallStruct_Data* data = nullptr; - Serialize_(small_struct.Pass(), &buf, &data); + Serialize_(small_struct.get(), &buf, &data); void* raw_buf = buf.Leak(); mojo::internal::BoundsChecker bounds_checker(data, @@ -551,11 +552,11 @@ small_struct->pod_union = PodUnion::New(); small_struct->pod_union->set_f_int32(10); - size_t size = GetSerializedSize_(small_struct); + size_t size = GetSerializedSize_(*small_struct); mojo::internal::FixedBufferForTesting buf(size); internal::SmallStruct_Data* data = nullptr; - Serialize_(small_struct.Pass(), &buf, &data); + Serialize_(small_struct.get(), &buf, &data); data->pod_union.tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100); void* raw_buf = buf.Leak(); @@ -571,7 +572,7 @@ SmallStructNonNullableUnionPtr small_struct( SmallStructNonNullableUnion::New()); - size_t size = GetSerializedSize_(small_struct); + size_t size = GetSerializedSize_(*small_struct); mojo::internal::FixedBufferForTesting buf(size); internal::SmallStructNonNullableUnion_Data* data = @@ -590,11 +591,11 @@ Environment environment; SmallStructPtr small_struct(SmallStruct::New()); - size_t size = GetSerializedSize_(small_struct); + size_t size = GetSerializedSize_(*small_struct); mojo::internal::FixedBufferForTesting buf(size); internal::SmallStruct_Data* data = nullptr; - Serialize_(small_struct.Pass(), &buf, &data); + Serialize_(small_struct.get(), &buf, &data); void* raw_buf = buf.Leak(); mojo::internal::BoundsChecker bounds_checker(data, @@ -634,7 +635,7 @@ mojo::internal::Map_Data<mojo::internal::String_Data*, internal::PodUnion_Data>* data; mojo::internal::ArrayValidateParams validate_params(0, false, nullptr); - SerializeMap_(map.Pass(), &buf, &data, &validate_params); + SerializeMap_(&map, &buf, &data, &validate_params); Map<String, PodUnionPtr> map2; Deserialize_(data, &map2); @@ -658,7 +659,7 @@ mojo::internal::Map_Data<mojo::internal::String_Data*, internal::PodUnion_Data>* data; mojo::internal::ArrayValidateParams validate_params(0, true, nullptr); - SerializeMap_(map.Pass(), &buf, &data, &validate_params); + SerializeMap_(&map, &buf, &data, &validate_params); Map<String, PodUnionPtr> map2; Deserialize_(data, &map2); @@ -690,14 +691,14 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); data->DecodePointersAndHandles(&handles); - ObjectUnionPtr obj2; - Deserialize_(data, &obj2); + ObjectUnionPtr obj2 = ObjectUnion::New(); + Deserialize_(data, obj2.get()); EXPECT_EQ(8, obj2->get_f_dummy()->f_int8); } @@ -713,7 +714,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); void* raw_buf = buf.Leak(); mojo::internal::BoundsChecker bounds_checker(data, @@ -734,7 +735,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); void* raw_buf = buf.Leak(); mojo::internal::BoundsChecker bounds_checker(data, @@ -755,7 +756,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); void* raw_buf = buf.Leak(); mojo::internal::BoundsChecker bounds_checker(data, @@ -794,14 +795,14 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); data->DecodePointersAndHandles(&handles); - ObjectUnionPtr obj2; - Deserialize_(data, &obj2); + ObjectUnionPtr obj2 = ObjectUnion::New(); + Deserialize_(data, obj2.get()); EXPECT_EQ(8, obj2->get_f_array_int8()[0]); EXPECT_EQ(9, obj2->get_f_array_int8()[1]); @@ -820,7 +821,7 @@ size_t size = GetSerializedSize_(obj, false); mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -861,14 +862,14 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); data->DecodePointersAndHandles(&handles); - ObjectUnionPtr obj2; - Deserialize_(data, &obj2); + ObjectUnionPtr obj2 = ObjectUnion::New(); + Deserialize_(data, obj2.get()); EXPECT_EQ(1, obj2->get_f_map_int8()["one"]); EXPECT_EQ(2, obj2->get_f_map_int8()["two"]); @@ -888,7 +889,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -925,14 +926,14 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); data->DecodePointersAndHandles(&handles); - ObjectUnionPtr obj2; - Deserialize_(data, &obj2); + ObjectUnionPtr obj2 = ObjectUnion::New(); + Deserialize_(data, obj2.get()); EXPECT_EQ(10, obj2->get_f_pod_union()->get_f_int8()); } @@ -949,7 +950,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -973,7 +974,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::ObjectUnion_Data* data = nullptr; - SerializeUnion_(obj.Pass(), &buf, &data, false); + SerializeUnion_(obj.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -1017,7 +1018,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::HandleUnion_Data* data = nullptr; - SerializeUnion_(handle.Pass(), &buf, &data, false); + SerializeUnion_(handle.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -1025,7 +1026,7 @@ data->DecodePointersAndHandles(&handles); HandleUnionPtr handle2(HandleUnion::New()); - Deserialize_(data, &handle2); + Deserialize_(data, handle2.get()); std::string golden("hello world"); WriteTextMessage(pipe0.get(), golden); @@ -1051,7 +1052,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::HandleUnion_Data* data = nullptr; - SerializeUnion_(handle.Pass(), &buf, &data, false); + SerializeUnion_(handle.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -1075,7 +1076,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::HandleUnion_Data* data = nullptr; - SerializeUnion_(handle.Pass(), &buf, &data, false); + SerializeUnion_(handle.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -1132,7 +1133,7 @@ mojo::internal::FixedBufferForTesting buf(size); internal::HandleUnion_Data* data = nullptr; - SerializeUnion_(handle.Pass(), &buf, &data, false); + SerializeUnion_(handle.get(), &buf, &data, false); std::vector<Handle> handles; data->EncodePointersAndHandles(&handles); @@ -1140,7 +1141,7 @@ data->DecodePointersAndHandles(&handles); HandleUnionPtr handle2(HandleUnion::New()); - Deserialize_(data, &handle2); + Deserialize_(data, handle2.get()); handle2->get_f_small_cache()->SetIntValue(10); run_loop.RunUntilIdle();
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index a06d849..96e7662 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -8,7 +8,7 @@ {%- macro alloc_params(struct) %} {%- for param in struct.packed.packed_fields_in_ordinal_order %} - {{param.field.kind|cpp_result_type}} p_{{param.field.name}}{}; + {{param.field.kind|cpp_result_type}} p_{{param.field.name}} {}; {%- endfor %} {{struct_macros.deserialize(struct, "params", "p_%s")}} {%- endmacro %}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl index 48b76e5..25a3ee4 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
@@ -16,6 +16,10 @@ {%- for pf in struct.packed.packed_fields_in_ordinal_order if pf.field.kind|is_object_kind %} {%- if pf.field.kind|is_union_kind %} size += GetSerializedSize_({{input_field_pattern|format(pf.field.name)}}, true); +{%- elif pf.field.kind|is_struct_kind %} + size += {{input_field_pattern|format(pf.field.name)}}.is_null() + ? 0 + : GetSerializedSize_(*{{input_field_pattern|format(pf.field.name)}}); {%- else %} size += GetSerializedSize_({{input_field_pattern|format(pf.field.name)}}); {%- endif %} @@ -47,19 +51,21 @@ {%- if kind|is_array_kind %} const mojo::internal::ArrayValidateParams {{name}}_validate_params( {{kind|get_array_validate_params_ctor_args|indent(10)}}); - mojo::SerializeArray_(mojo::internal::Forward({{input_field}}), {{buffer}}, + mojo::SerializeArray_(&{{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr, &{{name}}_validate_params); {%- elif kind|is_map_kind %} const mojo::internal::ArrayValidateParams {{name}}_validate_params( {{kind.value_kind|get_map_validate_params_ctor_args|indent(10)}}); mojo::SerializeMap_( - mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr, + &{{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr, &{{name}}_validate_params); {%- elif kind|is_union_kind %} internal::{{kind.name}}_Data* {{name}}_ptr = &{{output}}->{{name}}; - SerializeUnion_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{name}}_ptr, true); + SerializeUnion_({{input_field}}.get(), {{buffer}}, &{{name}}_ptr, true); +{%- elif kind|is_string_kind %} + SerializeString_({{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr); {%- else %} - Serialize_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr); + Serialize_({{input_field}}.get(), {{buffer}}, &{{output}}->{{name}}.ptr); {%- endif %} {%- if not kind|is_nullable_kind %} MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( @@ -126,8 +132,15 @@ {%- endif %} {%- if kind|is_object_kind %} {%- if kind|is_union_kind %} - Deserialize_(&{{input}}->{{name}}, &{{output_field}}); + {{output_field}} = {{kind|get_name_for_kind}}::New(); + Deserialize_(&{{input}}->{{name}}, {{output_field}}.get()); +{%- elif kind|is_struct_kind %} + if ({{input}}->{{name}}.ptr) { + {{output_field}} = {{kind|get_name_for_kind}}::New(); + Deserialize_({{input}}->{{name}}.ptr, {{output_field}}.get()); + } {%- else %} +{#- Arrays and Maps #} Deserialize_({{input}}->{{name}}.ptr, &{{output_field}}); {%- endif %} {%- elif kind|is_interface_kind %}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl index 604be86..6243372 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
@@ -1,5 +1,5 @@ -size_t GetSerializedSize_(const {{struct.name}}Ptr& input); -void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buffer, +size_t GetSerializedSize_(const {{struct.name}}& input); +void Serialize_({{struct.name}}* input, mojo::internal::Buffer* buffer, internal::{{struct.name}}_Data** output); void Deserialize_(internal::{{struct.name}}_Data* input, - {{struct.name}}Ptr* output); + {{struct.name}}* output); \ No newline at end of file
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl index fe25553..eb6fcec 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
@@ -1,12 +1,10 @@ {%- import "struct_macros.tmpl" as struct_macros %} -size_t GetSerializedSize_(const {{struct.name}}Ptr& input) { - if (!input) - return 0; - {{struct_macros.get_serialized_size(struct, "input->%s")}} +size_t GetSerializedSize_(const {{struct.name}}& input) { + {{struct_macros.get_serialized_size(struct, "input.%s")}} return size; } -void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buf, +void Serialize_({{struct.name}}* input, mojo::internal::Buffer* buf, internal::{{struct.name}}_Data** output) { if (input) { {{struct_macros.serialize(struct, struct.name ~ " struct", "input->%s", "result", "buf")|indent(2)}} @@ -17,12 +15,8 @@ } void Deserialize_(internal::{{struct.name}}_Data* input, - {{struct.name}}Ptr* output) { + {{struct.name}}* result) { if (input) { - {{struct.name}}Ptr result({{struct.name}}::New()); {{struct_macros.deserialize(struct, "input", "result->%s")|indent(2)}} - *output = result.Pass(); - } else { - output->reset(); } }
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl index 404eb83..588e749 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
@@ -1,5 +1,5 @@ size_t GetSerializedSize_(const {{union.name}}Ptr& input, bool inlined); -void SerializeUnion_({{union.name}}Ptr input, mojo::internal::Buffer* buffer, - internal::{{union.name}}_Data** output, bool inlined); +void SerializeUnion_({{union.name}}* input, mojo::internal::Buffer* buffer, + internal::{{union.name}}_Data** output, bool inlined); void Deserialize_(internal::{{union.name}}_Data* input, - {{union.name}}Ptr* output); + {{union.name}}* output); \ No newline at end of file
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl index 918e460..53b2126 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
@@ -14,6 +14,8 @@ case {{union.name}}::Tag::{{field.name|upper}}: {% if field.kind|is_union_kind %} size += GetSerializedSize_(*(input_acc.data()->{{field.name}}), false); +{% elif field.kind|is_struct_kind %} + size += GetSerializedSize_(*(input_acc.data()->{{field.name}}->get())); {% else %} size += GetSerializedSize_(*(input_acc.data()->{{field.name}})); {% endif %} @@ -26,14 +28,14 @@ return size; } -void SerializeUnion_({{union.name}}Ptr input, mojo::internal::Buffer* buf, +void SerializeUnion_({{union.name}}* input, mojo::internal::Buffer* buf, internal::{{union.name}}_Data** output, bool inlined) { internal::{{union.name}}_Data* result = *output; if (input) { if (!inlined) { result = internal::{{union.name}}_Data::New(buf); } - mojo::internal::UnionAccessor<{{union.name}}> input_acc(input.get()); + mojo::internal::UnionAccessor<{{union.name}}> input_acc(input); // TODO(azani): Handle unknown and objects. // Set the not-null flag. result->size = 16; @@ -43,28 +45,28 @@ case {{union.name}}::Tag::{{field.name|upper}}: { {% if field.kind|is_object_kind %} {% if field.kind|is_string_kind %} - Serialize_( - *(input_acc.data()->{{field.name}}), + SerializeString_( + *input_acc.data()->{{field.name}}, buf, &result->data.f_{{field.name}}.ptr); {% elif field.kind|is_struct_kind %} Serialize_( - mojo::internal::Forward(*(input_acc.data()->{{field.name}})), + input_acc.data()->{{field.name}}->get(), buf, &result->data.f_{{field.name}}.ptr); {% elif field.kind|is_union_kind %} SerializeUnion_( - mojo::internal::Forward(*(input_acc.data()->{{field.name}})), + input_acc.data()->{{field.name}}->get(), buf, &result->data.f_{{field.name}}.ptr, false); {% elif field.kind|is_array_kind %} const mojo::internal::ArrayValidateParams {{field.name}}_validate_params( {{field.kind|get_array_validate_params_ctor_args|indent(16)}}); SerializeArray_( - mojo::internal::Forward(*(input_acc.data()->{{field.name}})), + input_acc.data()->{{field.name}}, buf, &result->data.f_{{field.name}}.ptr, &{{field.name}}_validate_params); {% elif field.kind|is_map_kind %} const mojo::internal::ArrayValidateParams {{field.name}}_validate_params( {{field.kind.value_kind|get_map_validate_params_ctor_args|indent(16)}}); SerializeMap_( - mojo::internal::Forward(*(input_acc.data()->{{field.name}})), + input_acc.data()->{{field.name}}, buf, &result->data.f_{{field.name}}.ptr, &{{field.name}}_validate_params); {%- endif %} {% elif field.kind|is_any_handle_kind %} @@ -95,20 +97,28 @@ } void Deserialize_(internal::{{union.name}}_Data* input, - {{union.name}}Ptr* output) { + {{union.name}}* output) { if (input && !input->is_null()) { - {{union.name}}Ptr result({{union.name}}::New()); - mojo::internal::UnionAccessor<{{union.name}}> result_acc(result.get()); + mojo::internal::UnionAccessor<{{union.name}}> result_acc(output); switch (input->tag) { +{#- TODO(vardhan): There is a lot of overlap with struct_macros.deserialize() + here, is it possible to merge? (currently looks very hairy) #} {% for field in union.fields %} case {{union.name}}::Tag::{{field.name|upper}}: { {% if field.kind|is_object_kind %} result_acc.SwitchActive({{union.name}}::Tag::{{field.name|upper}}); +{% if field.kind|is_struct_kind or field.kind|is_union_kind %} + *result_acc.data()->{{field.name}} = + {{field.kind|get_name_for_kind}}::New(); + Deserialize_(input->data.f_{{field.name}}.ptr, + result_acc.data()->{{field.name}}->get()); +{% else %} Deserialize_(input->data.f_{{field.name}}.ptr, result_acc.data()->{{field.name}}); +{% endif %} {% elif field.kind|is_any_handle_kind %} {{field.kind|cpp_wrapper_type}}* {{field.name}} = reinterpret_cast<{{field.kind|cpp_wrapper_type}}*>(&input->data.f_{{field.name}}); - result->set_{{field.name}}({{field.name}}->Pass()); + output->set_{{field.name}}({{field.name}}->Pass()); {% elif field.kind|is_interface_kind %} {{field.kind|cpp_wrapper_type}} {{field.name}}_out; mojo::internal::Interface_Data* {{field.name}}_in = @@ -116,11 +126,11 @@ &input->data.f_{{field.name}}); mojo::internal::InterfaceDataToPointer( {{field.name}}_in, &{{field.name}}_out); - result->set_{{field.name}}({{field.name}}_out.Pass()); + output->set_{{field.name}}({{field.name}}_out.Pass()); {% elif field.kind|is_enum_kind %} - result->set_{{field.name}}(static_cast<{{field.kind|cpp_wrapper_type}}>(input->data.f_{{field.name}})); + output->set_{{field.name}}(static_cast<{{field.kind|cpp_wrapper_type}}>(input->data.f_{{field.name}})); {% else %} - result->set_{{field.name}}(input->data.f_{{field.name}}); + output->set_{{field.name}}(input->data.f_{{field.name}}); {%- endif %} break; } @@ -130,8 +140,5 @@ // No way to deserialize the data when we encounter an unknown tag. break; } - *output = result.Pass(); - } else { - output->reset(); } -} +} \ No newline at end of file
diff --git a/services/url_response_disk_cache/url_response_disk_cache_db.cc b/services/url_response_disk_cache/url_response_disk_cache_db.cc index 1991b62..f7eb587 100644 --- a/services/url_response_disk_cache/url_response_disk_cache_db.cc +++ b/services/url_response_disk_cache/url_response_disk_cache_db.cc
@@ -28,7 +28,7 @@ template <typename T> void Serialize(T input, std::string* output) { typedef typename mojo::internal::WrapperTraits<T>::DataType DataType; - size_t size = GetSerializedSize_(input); + size_t size = GetSerializedSize_(*input); output->clear(); output->resize(size); @@ -37,7 +37,7 @@ buf.Initialize(&output->at(0), size); DataType data_type; - Serialize_(input.Pass(), &buf, &data_type); + Serialize_(input.get(), &buf, &data_type); std::vector<Handle> handles; data_type->EncodePointersAndHandles(&handles); } @@ -52,7 +52,8 @@ DataType data_type = reinterpret_cast<DataType>(data); std::vector<Handle> handles; data_type->DecodePointersAndHandles(&handles); - Deserialize_(data_type, output); + *output = mojo::internal::RemoveStructPtr<T>::type::New(); + Deserialize_(data_type, output->get()); return true; }