| Index: mojo/public/cpp/bindings/lib/map_serialization.h
|
| diff --git a/mojo/public/cpp/bindings/lib/map_serialization.h b/mojo/public/cpp/bindings/lib/map_serialization.h
|
| index 05062b6ac6cce7dc976f902d9881b64ee8be8ddf..56ef68d3162f90f0ff73707fbb23e92f35ba6ae8 100644
|
| --- a/mojo/public/cpp/bindings/lib/map_serialization.h
|
| +++ b/mojo/public/cpp/bindings/lib/map_serialization.h
|
| @@ -5,195 +5,115 @@
|
| #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_
|
| #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_
|
|
|
| -#include <stddef.h>
|
| -#include <utility>
|
| -
|
| -#include "mojo/public/cpp/bindings/lib/array_internal.h"
|
| +#include "mojo/public/cpp/bindings/array.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/serialization_forward.h"
|
| #include "mojo/public/cpp/bindings/map.h"
|
|
|
| namespace mojo {
|
| namespace internal {
|
|
|
| -template <typename MapType,
|
| - typename DataType,
|
| - bool value_is_move_only_type = IsMoveOnlyType<MapType>::value,
|
| - bool is_union =
|
| - IsUnionDataType<typename RemovePointer<DataType>::type>::value>
|
| -struct MapSerializer;
|
| -
|
| -template <typename MapType, typename DataType>
|
| -struct MapSerializer<MapType, DataType, false, false> {
|
| - static size_t GetBaseArraySize(size_t count) {
|
| - return Align(count * sizeof(DataType));
|
| - }
|
| - static size_t GetItemSize(const MapType& item,
|
| - SerializationContext* context) {
|
| - return 0;
|
| - }
|
| -};
|
| -
|
| -template <>
|
| -struct MapSerializer<bool, bool, false, false> {
|
| - static size_t GetBaseArraySize(size_t count) {
|
| - return Align((count + 7) / 8);
|
| - }
|
| - static size_t GetItemSize(bool item, SerializationContext* context) {
|
| - return 0;
|
| - }
|
| -};
|
| -
|
| -template <typename H>
|
| -struct MapSerializer<ScopedHandleBase<H>, Handle_Data, true, false> {
|
| - static size_t GetBaseArraySize(size_t count) {
|
| - return Align(count * sizeof(Handle_Data));
|
| - }
|
| - static size_t GetItemSize(const ScopedHandleBase<H>& item,
|
| - SerializationContext* context) {
|
| - return 0;
|
| - }
|
| -};
|
| -
|
| -// This template must only apply to pointer mojo entity (structs and arrays).
|
| -// This is done by ensuring that GetDataTypeAsArrayElement<S>::Data is a
|
| -// pointer.
|
| -template <typename S>
|
| -struct MapSerializer<
|
| - S,
|
| - typename EnableIf<
|
| - IsPointer<typename GetDataTypeAsArrayElement<S>::Data>::value,
|
| - typename GetDataTypeAsArrayElement<S>::Data>::type,
|
| - true,
|
| - false> {
|
| - typedef
|
| - typename RemovePointer<typename GetDataTypeAsArrayElement<S>::Data>::type
|
| - S_Data;
|
| - static size_t GetBaseArraySize(size_t count) {
|
| - return count * sizeof(Pointer<S_Data>);
|
| - }
|
| - static size_t GetItemSize(const S& item, SerializationContext* context) {
|
| - return GetSerializedSize_(item, context);
|
| - }
|
| -};
|
| +template <typename Key, typename Value>
|
| +struct MapContext {
|
| + explicit MapContext(bool in_is_null) : is_null(in_is_null) {}
|
|
|
| -template <typename U, typename U_Data>
|
| -struct MapSerializer<U, U_Data, true, true> {
|
| - static size_t GetBaseArraySize(size_t count) {
|
| - return count * sizeof(U_Data);
|
| - }
|
| - static size_t GetItemSize(const U& item, SerializationContext* context) {
|
| - return GetSerializedSize_(item, true, context);
|
| - }
|
| + bool is_null;
|
| + Array<Key> keys;
|
| + Array<Value> values;
|
| };
|
|
|
| -template <>
|
| -struct MapSerializer<String, String_Data*, false, false> {
|
| - static size_t GetBaseArraySize(size_t count) {
|
| - return count * sizeof(Pointer<String_Data>);
|
| +template <typename Key, typename Value, typename MaybeConstUserType>
|
| +struct Serializer<Map<Key, Value>, MaybeConstUserType> {
|
| + using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
| + using UserKey = typename UserType::Key;
|
| + using UserValue = typename UserType::Value;
|
| + using Data = typename Map<Key, Value>::Data_;
|
| +
|
| + static_assert(std::is_same<MaybeConstUserType, UserType>::value,
|
| + "Only support serialization of non-const Maps.");
|
| + static_assert(IsSpecializationOf<Map, UserType>::value,
|
| + "Custom mapping of mojom map is not supported yet.");
|
| +
|
| + static size_t PrepareToSerialize(UserType& input,
|
| + SerializationContext* context) {
|
| + auto map_context = new MapContext<UserKey, UserValue>(input.is_null());
|
| + if (!context->custom_contexts)
|
| + context->custom_contexts.reset(new std::queue<void*>());
|
| + context->custom_contexts->push(map_context);
|
| +
|
| + if (!input)
|
| + return 0;
|
| +
|
| + input.DecomposeMapTo(&map_context->keys, &map_context->values);
|
| +
|
| + size_t struct_overhead = sizeof(Data);
|
| + size_t keys_size =
|
| + internal::PrepareToSerialize<Array<Key>>(map_context->keys, context);
|
| + size_t values_size = internal::PrepareToSerialize<Array<Value>>(
|
| + map_context->values, context);
|
| +
|
| + return struct_overhead + keys_size + values_size;
|
| }
|
| - static size_t GetItemSize(const String& item, SerializationContext* context) {
|
| - return GetSerializedSize_(item, context);
|
| - }
|
| -};
|
| -
|
| -} // namespace internal
|
|
|
| -// TODO(erg): This can't go away yet. We still need to calculate out the size
|
| -// of a struct header, and two arrays.
|
| -template <typename MapKey, typename MapValue>
|
| -inline size_t GetSerializedSize_(const Map<MapKey, MapValue>& input,
|
| - internal::SerializationContext* context) {
|
| - if (!input)
|
| - return 0;
|
| - typedef typename internal::GetDataTypeAsArrayElement<MapKey>::Data DataKey;
|
| - typedef
|
| - typename internal::GetDataTypeAsArrayElement<MapValue>::Data DataValue;
|
| -
|
| - size_t count = input.size();
|
| - size_t struct_overhead = sizeof(mojo::internal::Map_Data<DataKey, DataValue>);
|
| - size_t key_base_size =
|
| - sizeof(internal::ArrayHeader) +
|
| - internal::MapSerializer<MapKey, DataKey>::GetBaseArraySize(count);
|
| - size_t value_base_size =
|
| - sizeof(internal::ArrayHeader) +
|
| - internal::MapSerializer<MapValue, DataValue>::GetBaseArraySize(count);
|
| -
|
| - size_t key_data_size = 0;
|
| - size_t value_data_size = 0;
|
| - for (auto it = input.begin(); it != input.end(); ++it) {
|
| - key_data_size += internal::MapSerializer<MapKey, DataKey>::GetItemSize(
|
| - it->first, context);
|
| - value_data_size +=
|
| - internal::MapSerializer<MapValue, DataValue>::GetItemSize(it->second,
|
| - context);
|
| - }
|
| + // We don't need an ArrayValidateParams instance for key validation since
|
| + // we can deduce it from the Key type. (which can only be primitive types or
|
| + // non-nullable strings.)
|
| + static void Serialize(UserType& input,
|
| + Buffer* buf,
|
| + Data** output,
|
| + const ArrayValidateParams* value_validate_params,
|
| + SerializationContext* context) {
|
| + std::unique_ptr<MapContext<UserKey, UserValue>> map_context(
|
| + static_cast<MapContext<UserKey, UserValue>*>(
|
| + context->custom_contexts->front()));
|
| + context->custom_contexts->pop();
|
| +
|
| + if (map_context->is_null) {
|
| + *output = nullptr;
|
| + return;
|
| + }
|
|
|
| - return struct_overhead + key_base_size + key_data_size + value_base_size +
|
| - value_data_size;
|
| -}
|
| -
|
| -// We don't need an ArrayValidateParams instance for key validation since
|
| -// we can deduce it from the Key type. (which can only be primitive types or
|
| -// non-nullable strings.)
|
| -template <typename MapKey,
|
| - typename MapValue,
|
| - typename DataKey,
|
| - typename DataValue>
|
| -inline void SerializeMap_(
|
| - Map<MapKey, MapValue> input,
|
| - internal::Buffer* buf,
|
| - internal::Map_Data<DataKey, DataValue>** output,
|
| - const internal::ArrayValidateParams* value_validate_params,
|
| - internal::SerializationContext* context) {
|
| - if (input) {
|
| - internal::Map_Data<DataKey, DataValue>* result =
|
| - internal::Map_Data<DataKey, DataValue>::New(buf);
|
| + auto result = Data::New(buf);
|
| if (result) {
|
| - Array<MapKey> keys;
|
| - Array<MapValue> values;
|
| - input.DecomposeMapTo(&keys, &values);
|
| - const internal::ArrayValidateParams* key_validate_params =
|
| - internal::MapKeyValidateParamsFactory<DataKey>::Get();
|
| - SerializeArray_(std::move(keys), buf, &result->keys.ptr,
|
| - key_validate_params, context);
|
| - SerializeArray_(std::move(values), buf, &result->values.ptr,
|
| - value_validate_params, context);
|
| + const ArrayValidateParams* key_validate_params =
|
| + MapKeyValidateParamsFactory<
|
| + typename GetDataTypeAsArrayElement<Key>::Data>::Get();
|
| + internal::Serialize<Array<Key>>(map_context->keys, buf, &result->keys.ptr,
|
| + key_validate_params, context);
|
| + internal::Serialize<Array<Value>>(map_context->values, buf,
|
| + &result->values.ptr,
|
| + value_validate_params, context);
|
| }
|
| *output = result;
|
| - } else {
|
| - *output = nullptr;
|
| }
|
| -}
|
| -
|
| -template <typename MapKey,
|
| - typename MapValue,
|
| - typename DataKey,
|
| - typename DataValue>
|
| -inline bool Deserialize_(internal::Map_Data<DataKey, DataValue>* input,
|
| - Map<MapKey, MapValue>* output,
|
| - internal::SerializationContext* context) {
|
| - bool success = true;
|
| - if (input) {
|
| - Array<MapKey> keys;
|
| - Array<MapValue> values;
|
| -
|
| - // 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->keys.ptr, &keys, context))
|
| - success = false;
|
| - if (!Deserialize_(input->values.ptr, &values, context))
|
| - success = false;
|
| -
|
| - *output = Map<MapKey, MapValue>(std::move(keys), std::move(values));
|
| - } else {
|
| - *output = nullptr;
|
| +
|
| + static bool Deserialize(Data* input,
|
| + UserType* output,
|
| + SerializationContext* context) {
|
| + bool success = true;
|
| + if (input) {
|
| + Array<UserKey> keys;
|
| + Array<UserValue> values;
|
| +
|
| + // 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 (!internal::Deserialize<Array<Key>>(input->keys.ptr, &keys, context))
|
| + success = false;
|
| + if (!internal::Deserialize<Array<Value>>(input->values.ptr, &values,
|
| + context)) {
|
| + success = false;
|
| + }
|
| +
|
| + *output = UserType(std::move(keys), std::move(values));
|
| + } else {
|
| + *output = nullptr;
|
| + }
|
| + return success;
|
| }
|
| - return success;
|
| -}
|
| +};
|
|
|
| +} // namespace internal
|
| } // namespace mojo
|
|
|
| #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_
|
|
|