// Copyright 2014 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. #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ #include "mojo/public/cpp/bindings/lib/array_internal.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 inline size_t GetSerializedSize_(const Map& input); template inline void SerializeArray_( Array input, internal::Buffer* buf, internal::Array_Data** output, const internal::ArrayValidateParams* validate_params); namespace internal { template ::value, bool is_union = IsUnionDataType::type>::value> struct MapSerializer; template struct MapSerializer { static size_t GetBaseArraySize(size_t count) { return Align(count * sizeof(DataType)); } static size_t GetItemSize(const MapType& item) { return 0; } }; template <> struct MapSerializer { static size_t GetBaseArraySize(size_t count) { return Align((count + 7) / 8); } static size_t GetItemSize(bool item) { return 0; } }; template struct MapSerializer, H, true, false> { static size_t GetBaseArraySize(size_t count) { return Align(count * sizeof(H)); } static size_t GetItemSize(const ScopedHandleBase& item) { return 0; } }; // This template must only apply to pointer mojo entity (structs and arrays). // This is done by ensuring that WrapperTraits::DataType is a pointer. template struct MapSerializer< S, typename EnableIf::DataType>::value, typename WrapperTraits::DataType>::type, true, false> { typedef typename RemovePointer::DataType>::type S_Data; static size_t GetBaseArraySize(size_t count) { return count * sizeof(StructPointer); } static size_t GetItemSize(const S& item) { return GetSerializedSize_(item); } }; template struct MapSerializer { static size_t GetBaseArraySize(size_t count) { return count * sizeof(U_Data); } static size_t GetItemSize(const U& item) { return GetSerializedSize_(item, true); } }; template <> struct MapSerializer { static size_t GetBaseArraySize(size_t count) { return count * sizeof(StringPointer); } static size_t GetItemSize(const String& item) { return GetSerializedSize_(item); } }; } // 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 inline size_t GetSerializedSize_(const Map& input) { if (!input) return 0; typedef typename internal::WrapperTraits::DataType DataKey; typedef typename internal::WrapperTraits::DataType DataValue; size_t count = input.size(); size_t struct_overhead = sizeof(mojo::internal::Map_Data); size_t key_base_size = sizeof(internal::ArrayHeader) + internal::MapSerializer::GetBaseArraySize(count); size_t value_base_size = sizeof(internal::ArrayHeader) + internal::MapSerializer::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::GetItemSize(it.GetKey()); value_data_size += internal::MapSerializer::GetItemSize( it.GetValue()); } 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 inline void SerializeMap_( Map input, internal::Buffer* buf, internal::Map_Data** output, const internal::ArrayValidateParams* value_validate_params) { if (input) { internal::Map_Data* result = internal::Map_Data::New(buf); if (result) { Array keys; Array values; input.DecomposeMapTo(&keys, &values); const internal::ArrayValidateParams* key_validate_params = internal::MapKeyValidateParamsFactory::Get(); SerializeArray_(keys.Pass(), buf, &result->keys.ptr, key_validate_params); SerializeArray_(values.Pass(), buf, &result->values.ptr, value_validate_params); } *output = result; } else { *output = nullptr; } } template inline void Deserialize_(internal::Map_Data* input, Map* output) { if (input) { Array keys; Array values; Deserialize_(input->keys.ptr, &keys); Deserialize_(input->values.ptr, &values); *output = Map(keys.Pass(), values.Pass()); } else { output->reset(); } } } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_