Chromium Code Reviews| 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 |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..00e7e6f7ecc010cf760e04051705283baee38ac7 |
| --- /dev/null |
| +++ b/mojo/public/cpp/bindings/lib/map_serialization.h |
| @@ -0,0 +1,197 @@ |
| +// 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 <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); |
| + |
| +namespace internal { |
| + |
| +template <typename MapType, |
| + typename DataType, |
| + bool kValueIsMoveOnlyType = IsMoveOnlyType<MapType>::value> |
| +struct MapSerializer; |
| + |
| +template <typename MapType, typename DataType> |
| +struct MapSerializer<MapType, DataType, false> { |
| + static size_t GetHeaderSize() { return sizeof(Array_Data<DataType>); } |
|
yzshen1
2014/10/08 21:58:33
- Comments about the methods of MapSerializer woul
|
| + static size_t GetBaseArraySize(size_t count) { |
| + return Align(count * sizeof(DataType)); |
| + } |
| + static size_t GetItemSize(const MapType& item) { return 0; } |
| +}; |
| + |
| +template <> |
| +struct MapSerializer<bool, bool, false> { |
| + static size_t GetHeaderSize() { return sizeof(Array_Data<bool>); } |
| + static size_t GetBaseArraySize(size_t count) { |
| + return Align((count + 7) / 8); |
| + } |
| + static size_t GetItemSize(bool item) { return 0; } |
| +}; |
| + |
| +template <typename H> |
| +struct MapSerializer<ScopedHandleBase<H>, H, true> { |
| + static size_t GetHeaderSize() { return sizeof(Array_Data<H>); } |
| + static size_t GetBaseArraySize(size_t count) { |
| + return Align(count * sizeof(H)); |
| + } |
| + static size_t GetItemSize(const H& item) { return 0; } |
| +}; |
| + |
| +template <typename S> |
| +struct MapSerializer<S, typename S::Data_*, true> { |
| + static size_t GetHeaderSize() { |
| + return sizeof(Array_Data<typename S::Data_*>); |
| + } |
| + static size_t GetBaseArraySize(size_t count) { |
| + return count * sizeof(internal::StructPointer<typename S::Data_>); |
| + } |
| + static size_t GetItemSize(const S& item) { return GetSerializedSize_(item); } |
| +}; |
| + |
| +template <> |
| +struct MapSerializer<String, String_Data*, false> { |
| + static size_t GetHeaderSize() { return sizeof(Array_Data<String_Data*>); } |
| + static size_t GetBaseArraySize(size_t count) { |
| + return count * sizeof(internal::StringPointer); |
| + } |
| + static size_t GetItemSize(const String& item) { |
| + return GetSerializedSize_(item); |
| + } |
| +}; |
| + |
| +template <typename MapKey, |
| + typename MapValue, |
| + typename DataKey, |
| + typename DataValue> |
| +struct SizeAccumulator { |
| + SizeAccumulator(size_t* data_size) : size(data_size) {} |
| + size_t* size; |
| + |
| + void operator()(const MapKey& key, const MapValue& value) { |
| + *size += internal::MapSerializer<MapKey, DataKey>::GetItemSize(key); |
| + *size += internal::MapSerializer<MapValue, DataValue>::GetItemSize(value); |
| + } |
| +}; |
| + |
| +template <typename MapKey> |
| +struct MapKeyValidateParams { |
|
yzshen1
2014/10/08 21:58:33
I think you have defined these types in map_data_i
Elliot Glaysher
2014/10/08 23:40:49
The ones in map_data_internal.h are different then
|
| + public: |
| + typedef NoValidateParams ElementValidateParams; |
| + static const uint32_t expected_num_elements = 0; |
| + static const bool element_is_nullable = false; |
| +}; |
| + |
| +template <> |
| +struct MapKeyValidateParams<String> { |
| + public: |
| + typedef ArrayValidateParams<0, false, NoValidateParams> ElementValidateParams; |
| + static const uint32_t expected_num_elements = 0; |
| + static const bool element_is_nullable = false; |
| +}; |
| + |
| +} // 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) { |
| + if (!input) |
| + return 0; |
| + typedef typename internal::WrapperTraits<MapKey>::DataType DataKey; |
| + typedef typename internal::WrapperTraits<MapValue>::DataType DataValue; |
| + |
| + size_t count = input.size(); |
| + size_t struct_overhead = sizeof(mojo::internal::Map_Data<DataKey, DataValue>); |
| + size_t key_base_size = |
| + internal::MapSerializer<MapKey, DataKey>::GetHeaderSize() + |
| + internal::MapSerializer<MapKey, DataKey>::GetBaseArraySize(count); |
| + size_t value_base_size = |
| + internal::MapSerializer<MapValue, DataValue>::GetHeaderSize() + |
| + 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.GetKey()); |
| + value_data_size += |
| + internal::MapSerializer<MapValue, DataValue>::GetItemSize( |
| + it.GetValue()); |
| + } |
| + |
| + return struct_overhead + key_base_size + key_data_size + |
| + // SOME SORT OF ALIGNMENT GOES HERE? |
|
yzshen1
2014/10/08 21:58:33
I think you have considered all alignment properly
|
| + value_base_size + value_data_size; |
| +} |
| + |
| +// We don't need a KeyValidateParams, because we konw exactly what params are |
| +// needed. (Keys are primitive types or non-nullable strings.) |
| +template <typename ValueValidateParams, |
| + typename KeyWrapperType, |
|
yzshen1
2014/10/08 21:58:33
nit: it might be better to use consistent names fo
|
| + typename ValueWrapperType, |
| + typename KeySerializationType, |
| + typename ValueSerializationType> |
| +inline void SerializeMap_( |
| + Map<KeyWrapperType, ValueWrapperType> input, |
| + internal::Buffer* buf, |
| + internal::Map_Data<KeySerializationType, ValueSerializationType>** output) { |
| + if (input) { |
| + internal::Map_Data<KeySerializationType, ValueSerializationType>* result = |
| + internal::Map_Data<KeySerializationType, ValueSerializationType>::New( |
| + buf); |
| + if (result) { |
| + Array<KeyWrapperType> keys; |
| + Array<ValueWrapperType> values; |
| + input.DecomposeMapTo(&keys, &values); |
| + SerializeArray_<internal::MapKeyValidateParams<KeyWrapperType>>( |
| + keys.Pass(), buf, &result->first.ptr); |
| + SerializeArray_<ValueValidateParams>( |
| + values.Pass(), buf, &result->second.ptr); |
| + } |
| + *output = result; |
| + } else { |
| + *output = nullptr; |
| + } |
| +} |
| + |
| +template <typename KeyWrapperType, |
| + typename ValueWrapperType, |
| + typename KeySerializationType, |
| + typename ValueSerializationType> |
| +inline void Deserialize_( |
| + internal::Map_Data<KeySerializationType, ValueSerializationType>* input, |
| + Map<KeyWrapperType, ValueWrapperType>* output) { |
| + if (input) { |
| + Array<KeyWrapperType> keys; |
| + Array<ValueWrapperType> values; |
| + |
| + Deserialize_(input->first.ptr, &keys); |
| + Deserialize_(input->second.ptr, &values); |
| + |
| + *output = Map<KeyWrapperType, ValueWrapperType>(keys.Pass(), values.Pass()); |
| + } else { |
| + output->reset(); |
| + } |
| +} |
| + |
| +} // namespace mojo |
| + |
| +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ |