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

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* GetDataIfAvailable() { 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 explicit MapKeyReader(MaybeConstUserType& input) : MapReaderBase(input) {}
47 ~MapKeyReader() {}
48
49 const typename Traits::Key& GetNext() {
Ken Rockot(use gerrit already) 2016/05/27 16:07:39 Seems a lot of compiles don't like this use of Tra
yzshen1 2016/05/28 00:23:07 Done.
50 const typename Traits::Key& key = Traits::GetKey(iter_);
51 Traits::AdvanceIterator(iter_);
52 return key;
53 }
54 };
55
56 // Used as the UserTypeReader template parameter of ArraySerializer.
57 template <typename MaybeConstUserType>
58 class MapValueReader : public MapReaderBase<MaybeConstUserType> {
59 public:
60 explicit MapValueReader(MaybeConstUserType& input) : MapReaderBase(input) {}
61 ~MapValueReader() {}
62
63 using GetNextResult =
64 decltype(Traits::GetValue(std::declval<MaybeConstIterator&>()));
65 GetNextResult GetNext() {
66 GetNextResult value = Traits::GetValue(iter_);
67 Traits::AdvanceIterator(iter_);
68 return value;
69 }
23 }; 70 };
24 71
25 template <typename Key, typename Value, typename MaybeConstUserType> 72 template <typename Key, typename Value, typename MaybeConstUserType>
26 struct Serializer<Map<Key, Value>, MaybeConstUserType> { 73 struct Serializer<Map<Key, Value>, MaybeConstUserType> {
27 using UserType = typename std::remove_const<MaybeConstUserType>::type; 74 using UserType = typename std::remove_const<MaybeConstUserType>::type;
28 using UserKey = typename UserType::Key; 75 using Traits = MapTraits<UserType>;
29 using UserValue = typename UserType::Value; 76 using UserKey = typename Traits::Key;
77 using UserValue = typename Traits::Value;
30 using Data = typename Map<Key, Value>::Data_; 78 using Data = typename Map<Key, Value>::Data_;
79 using KeyArraySerializer = ArraySerializer<Array<Key>,
80 Array<UserKey>,
81 MapKeyReader<MaybeConstUserType>>;
82 using ValueArraySerializer =
83 ArraySerializer<Array<Value>,
84 Array<UserValue>,
85 MapValueReader<MaybeConstUserType>>;
31 86
32 static_assert(std::is_same<MaybeConstUserType, UserType>::value, 87 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) { 88 SerializationContext* context) {
39 auto map_context = new MapContext<UserKey, UserValue>(input.is_null()); 89 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; 90 return 0;
46 91
47 input.DecomposeMapTo(&map_context->keys, &map_context->values);
48
49 size_t struct_overhead = sizeof(Data); 92 size_t struct_overhead = sizeof(Data);
93 MapKeyReader<MaybeConstUserType> key_reader(input);
50 size_t keys_size = 94 size_t keys_size =
51 internal::PrepareToSerialize<Array<Key>>(map_context->keys, context); 95 KeyArraySerializer::GetSerializedSize(&key_reader, context);
52 size_t values_size = internal::PrepareToSerialize<Array<Value>>( 96 MapValueReader<MaybeConstUserType> value_reader(input);
53 map_context->values, context); 97 size_t values_size =
98 ValueArraySerializer::GetSerializedSize(&value_reader, context);
54 99
55 return struct_overhead + keys_size + values_size; 100 return struct_overhead + keys_size + values_size;
56 } 101 }
57 102
58 // We don't need an ArrayValidateParams instance for key validation since 103 // 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 104 // we can deduce it from the Key type. (which can only be primitive types or
60 // non-nullable strings.) 105 // non-nullable strings.)
61 static void Serialize(UserType& input, 106 static void Serialize(MaybeConstUserType& input,
62 Buffer* buf, 107 Buffer* buf,
63 Data** output, 108 Data** output,
64 const ArrayValidateParams* value_validate_params, 109 const ArrayValidateParams* value_validate_params,
65 SerializationContext* context) { 110 SerializationContext* context) {
66 std::unique_ptr<MapContext<UserKey, UserValue>> map_context( 111 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; 112 *output = nullptr;
73 return; 113 return;
74 } 114 }
75 115
76 auto result = Data::New(buf); 116 auto result = Data::New(buf);
77 if (result) { 117 if (result) {
78 const ArrayValidateParams* key_validate_params = 118 result->keys.ptr =
79 MapKeyValidateParamsFactory< 119 typename Array<Key>::Data_::New(Traits::GetSize(input), buf);
80 typename GetDataTypeAsArrayElement<Key>::Data>::Get(); 120 if (result->keys.ptr) {
81 internal::Serialize<Array<Key>>(map_context->keys, buf, &result->keys.ptr, 121 const ArrayValidateParams* key_validate_params =
82 key_validate_params, context); 122 MapKeyValidateParamsFactory<
83 internal::Serialize<Array<Value>>(map_context->values, buf, 123 typename GetDataTypeAsArrayElement<Key>::Data>::Get();
84 &result->values.ptr, 124 MapKeyReader<MaybeConstUserType> key_reader(input);
85 value_validate_params, context); 125 KeyArraySerializer::SerializeElements(
126 &key_reader, buf, result->keys.ptr, key_validate_params, context);
127 }
128
129 result->values.ptr =
130 typename Array<Value>::Data_::New(Traits::GetSize(input), buf);
131 if (result->values.ptr) {
132 MapValueReader<MaybeConstUserType> value_reader(input);
133 ValueArraySerializer::SerializeElements(&value_reader, buf,
134 result->values.ptr,
135 value_validate_params, context);
136 }
86 } 137 }
87 *output = result; 138 *output = result;
88 } 139 }
89 140
90 static bool Deserialize(Data* input, 141 static bool Deserialize(Data* input,
91 UserType* output, 142 UserType* output,
92 SerializationContext* context) { 143 SerializationContext* context) {
93 bool success = true; 144 if (!input)
94 if (input) { 145 return CallSetToNullIfExists<Traits>(output);
95 Array<UserKey> keys;
96 Array<UserValue> values;
97 146
98 // Note that we rely on complete deserialization taking place in order to 147 Array<UserKey> keys;
99 // transfer ownership of all encoded handles. Therefore we don't 148 Array<UserValue> values;
100 // short-circuit on failure here.
yzshen1 2016/05/26 21:58:30 (I think we can short-circuit now because of your
Ken Rockot(use gerrit already) 2016/05/27 16:07:39 Woohoo!
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 149
108 *output = UserType(std::move(keys), std::move(values)); 150 if (!KeyArraySerializer::DeserializeElements(input->keys.ptr, &keys,
109 } else { 151 context) ||
110 *output = nullptr; 152 !ValueArraySerializer::DeserializeElements(input->values.ptr, &values,
153 context)) {
154 return false;
111 } 155 }
112 return success; 156
157 DCHECK_EQ(keys.size(), values.size());
158 size_t size = keys.size();
159 Traits::SetToEmpty(output);
160
161 for (size_t i = 0; i < size; ++i)
162 Traits::Insert(*output, std::move(keys[i]), std::move(values[i]));
163 return true;
113 } 164 }
114 }; 165 };
115 166
116 } // namespace internal 167 } // namespace internal
117 } // namespace mojo 168 } // namespace mojo
118 169
119 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ 170 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698