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 |