| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ | 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ |
| 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ | 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ |
| 7 | 7 |
| 8 #include <type_traits> |
| 9 |
| 8 #include "mojo/public/cpp/bindings/array.h" | 10 #include "mojo/public/cpp/bindings/array.h" |
| 11 #include "mojo/public/cpp/bindings/lib/array_serialization.h" |
| 9 #include "mojo/public/cpp/bindings/lib/map_data_internal.h" | 12 #include "mojo/public/cpp/bindings/lib/map_data_internal.h" |
| 10 #include "mojo/public/cpp/bindings/lib/serialization_forward.h" | 13 #include "mojo/public/cpp/bindings/lib/serialization_forward.h" |
| 11 #include "mojo/public/cpp/bindings/map.h" | 14 #include "mojo/public/cpp/bindings/map.h" |
| 12 | 15 |
| 13 namespace mojo { | 16 namespace mojo { |
| 14 namespace internal { | 17 namespace internal { |
| 15 | 18 |
| 16 template <typename Key, typename Value> | 19 template <typename MaybeConstUserType> |
| 17 struct MapContext { | 20 class MapReaderBase { |
| 18 explicit MapContext(bool in_is_null) : is_null(in_is_null) {} | 21 public: |
| 22 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| 23 using Traits = MapTraits<UserType>; |
| 24 using MaybeConstIterator = |
| 25 decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>())); |
| 19 | 26 |
| 20 bool is_null; | 27 explicit MapReaderBase(MaybeConstUserType& input) |
| 21 Array<Key> keys; | 28 : input_(input), iter_(Traits::GetBegin(input_)) {} |
| 22 Array<Value> values; | 29 ~MapReaderBase() {} |
| 30 |
| 31 size_t GetSize() const { return Traits::GetSize(input_); } |
| 32 |
| 33 // Return null because key or value elements are not stored continuously in |
| 34 // memory. |
| 35 void* GetDataIfExists() { return nullptr; } |
| 36 |
| 37 protected: |
| 38 MaybeConstUserType& input_; |
| 39 MaybeConstIterator iter_; |
| 40 }; |
| 41 |
| 42 // Used as the UserTypeReader template parameter of ArraySerializer. |
| 43 template <typename MaybeConstUserType> |
| 44 class MapKeyReader : public MapReaderBase<MaybeConstUserType> { |
| 45 public: |
| 46 using Base = MapReaderBase<MaybeConstUserType>; |
| 47 using Traits = typename Base::Traits; |
| 48 |
| 49 explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {} |
| 50 ~MapKeyReader() {} |
| 51 |
| 52 const typename Traits::Key& GetNext() { |
| 53 const typename Traits::Key& key = Traits::GetKey(this->iter_); |
| 54 Traits::AdvanceIterator(this->iter_); |
| 55 return key; |
| 56 } |
| 57 }; |
| 58 |
| 59 // Used as the UserTypeReader template parameter of ArraySerializer. |
| 60 template <typename MaybeConstUserType> |
| 61 class MapValueReader : public MapReaderBase<MaybeConstUserType> { |
| 62 public: |
| 63 using Base = MapReaderBase<MaybeConstUserType>; |
| 64 using Traits = typename Base::Traits; |
| 65 using MaybeConstIterator = typename Base::MaybeConstIterator; |
| 66 |
| 67 explicit MapValueReader(MaybeConstUserType& input) : Base(input) {} |
| 68 ~MapValueReader() {} |
| 69 |
| 70 using GetNextResult = |
| 71 decltype(Traits::GetValue(std::declval<MaybeConstIterator&>())); |
| 72 GetNextResult GetNext() { |
| 73 GetNextResult value = Traits::GetValue(this->iter_); |
| 74 Traits::AdvanceIterator(this->iter_); |
| 75 return value; |
| 76 } |
| 23 }; | 77 }; |
| 24 | 78 |
| 25 template <typename Key, typename Value, typename MaybeConstUserType> | 79 template <typename Key, typename Value, typename MaybeConstUserType> |
| 26 struct Serializer<Map<Key, Value>, MaybeConstUserType> { | 80 struct Serializer<Map<Key, Value>, MaybeConstUserType> { |
| 27 using UserType = typename std::remove_const<MaybeConstUserType>::type; | 81 using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| 28 using UserKey = typename UserType::Key; | 82 using Traits = MapTraits<UserType>; |
| 29 using UserValue = typename UserType::Value; | 83 using UserKey = typename Traits::Key; |
| 84 using UserValue = typename Traits::Value; |
| 30 using Data = typename Map<Key, Value>::Data_; | 85 using Data = typename Map<Key, Value>::Data_; |
| 86 using KeyArraySerializer = ArraySerializer<Array<Key>, |
| 87 Array<UserKey>, |
| 88 MapKeyReader<MaybeConstUserType>>; |
| 89 using ValueArraySerializer = |
| 90 ArraySerializer<Array<Value>, |
| 91 Array<UserValue>, |
| 92 MapValueReader<MaybeConstUserType>>; |
| 31 | 93 |
| 32 static_assert(std::is_same<MaybeConstUserType, UserType>::value, | 94 static size_t PrepareToSerialize(MaybeConstUserType& input, |
| 33 "Only support serialization of non-const Maps."); | |
| 34 static_assert(IsSpecializationOf<Map, UserType>::value, | |
| 35 "Custom mapping of mojom map is not supported yet."); | |
| 36 | |
| 37 static size_t PrepareToSerialize(UserType& input, | |
| 38 SerializationContext* context) { | 95 SerializationContext* context) { |
| 39 auto map_context = new MapContext<UserKey, UserValue>(input.is_null()); | 96 if (CallIsNullIfExists<Traits>(input)) |
| 40 if (!context->custom_contexts) | |
| 41 context->custom_contexts.reset(new std::queue<void*>()); | |
| 42 context->custom_contexts->push(map_context); | |
| 43 | |
| 44 if (!input) | |
| 45 return 0; | 97 return 0; |
| 46 | 98 |
| 47 input.DecomposeMapTo(&map_context->keys, &map_context->values); | |
| 48 | |
| 49 size_t struct_overhead = sizeof(Data); | 99 size_t struct_overhead = sizeof(Data); |
| 100 MapKeyReader<MaybeConstUserType> key_reader(input); |
| 50 size_t keys_size = | 101 size_t keys_size = |
| 51 internal::PrepareToSerialize<Array<Key>>(map_context->keys, context); | 102 KeyArraySerializer::GetSerializedSize(&key_reader, context); |
| 52 size_t values_size = internal::PrepareToSerialize<Array<Value>>( | 103 MapValueReader<MaybeConstUserType> value_reader(input); |
| 53 map_context->values, context); | 104 size_t values_size = |
| 105 ValueArraySerializer::GetSerializedSize(&value_reader, context); |
| 54 | 106 |
| 55 return struct_overhead + keys_size + values_size; | 107 return struct_overhead + keys_size + values_size; |
| 56 } | 108 } |
| 57 | 109 |
| 58 // We don't need an ArrayValidateParams instance for key validation since | 110 // We don't need an ArrayValidateParams instance for key validation since |
| 59 // we can deduce it from the Key type. (which can only be primitive types or | 111 // we can deduce it from the Key type. (which can only be primitive types or |
| 60 // non-nullable strings.) | 112 // non-nullable strings.) |
| 61 static void Serialize(UserType& input, | 113 static void Serialize(MaybeConstUserType& input, |
| 62 Buffer* buf, | 114 Buffer* buf, |
| 63 Data** output, | 115 Data** output, |
| 64 const ArrayValidateParams* value_validate_params, | 116 const ArrayValidateParams* value_validate_params, |
| 65 SerializationContext* context) { | 117 SerializationContext* context) { |
| 66 std::unique_ptr<MapContext<UserKey, UserValue>> map_context( | 118 if (CallIsNullIfExists<Traits>(input)) { |
| 67 static_cast<MapContext<UserKey, UserValue>*>( | |
| 68 context->custom_contexts->front())); | |
| 69 context->custom_contexts->pop(); | |
| 70 | |
| 71 if (map_context->is_null) { | |
| 72 *output = nullptr; | 119 *output = nullptr; |
| 73 return; | 120 return; |
| 74 } | 121 } |
| 75 | 122 |
| 76 auto result = Data::New(buf); | 123 auto result = Data::New(buf); |
| 77 if (result) { | 124 if (result) { |
| 78 const ArrayValidateParams* key_validate_params = | 125 result->keys.ptr = Array<Key>::Data_::New(Traits::GetSize(input), buf); |
| 79 MapKeyValidateParamsFactory< | 126 if (result->keys.ptr) { |
| 80 typename GetDataTypeAsArrayElement<Key>::Data>::Get(); | 127 const ArrayValidateParams* key_validate_params = |
| 81 internal::Serialize<Array<Key>>(map_context->keys, buf, &result->keys.ptr, | 128 MapKeyValidateParamsFactory< |
| 82 key_validate_params, context); | 129 typename GetDataTypeAsArrayElement<Key>::Data>::Get(); |
| 83 internal::Serialize<Array<Value>>(map_context->values, buf, | 130 MapKeyReader<MaybeConstUserType> key_reader(input); |
| 84 &result->values.ptr, | 131 KeyArraySerializer::SerializeElements( |
| 85 value_validate_params, context); | 132 &key_reader, buf, result->keys.ptr, key_validate_params, context); |
| 133 } |
| 134 |
| 135 result->values.ptr = |
| 136 Array<Value>::Data_::New(Traits::GetSize(input), buf); |
| 137 if (result->values.ptr) { |
| 138 MapValueReader<MaybeConstUserType> value_reader(input); |
| 139 ValueArraySerializer::SerializeElements(&value_reader, buf, |
| 140 result->values.ptr, |
| 141 value_validate_params, context); |
| 142 } |
| 86 } | 143 } |
| 87 *output = result; | 144 *output = result; |
| 88 } | 145 } |
| 89 | 146 |
| 90 static bool Deserialize(Data* input, | 147 static bool Deserialize(Data* input, |
| 91 UserType* output, | 148 UserType* output, |
| 92 SerializationContext* context) { | 149 SerializationContext* context) { |
| 93 bool success = true; | 150 if (!input) |
| 94 if (input) { | 151 return CallSetToNullIfExists<Traits>(output); |
| 95 Array<UserKey> keys; | |
| 96 Array<UserValue> values; | |
| 97 | 152 |
| 98 // Note that we rely on complete deserialization taking place in order to | 153 Array<UserKey> keys; |
| 99 // transfer ownership of all encoded handles. Therefore we don't | 154 Array<UserValue> values; |
| 100 // short-circuit on failure here. | |
| 101 if (!internal::Deserialize<Array<Key>>(input->keys.ptr, &keys, context)) | |
| 102 success = false; | |
| 103 if (!internal::Deserialize<Array<Value>>(input->values.ptr, &values, | |
| 104 context)) { | |
| 105 success = false; | |
| 106 } | |
| 107 | 155 |
| 108 *output = UserType(std::move(keys), std::move(values)); | 156 if (!KeyArraySerializer::DeserializeElements(input->keys.ptr, &keys, |
| 109 } else { | 157 context) || |
| 110 *output = nullptr; | 158 !ValueArraySerializer::DeserializeElements(input->values.ptr, &values, |
| 159 context)) { |
| 160 return false; |
| 111 } | 161 } |
| 112 return success; | 162 |
| 163 DCHECK_EQ(keys.size(), values.size()); |
| 164 size_t size = keys.size(); |
| 165 Traits::SetToEmpty(output); |
| 166 |
| 167 for (size_t i = 0; i < size; ++i) |
| 168 Traits::Insert(*output, std::move(keys[i]), std::move(values[i])); |
| 169 return true; |
| 113 } | 170 } |
| 114 }; | 171 }; |
| 115 | 172 |
| 116 } // namespace internal | 173 } // namespace internal |
| 117 } // namespace mojo | 174 } // namespace mojo |
| 118 | 175 |
| 119 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ | 176 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ |
| OLD | NEW |