Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: mojo/public/cpp/bindings/lib/map_serialization.h

Issue 2014403002: Mojo C++ bindings: custom type mapping of map (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/lib/map_internal.h ('k') | mojo/public/cpp/bindings/lib/serialization.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698