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* 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_ |
OLD | NEW |