OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ | |
7 | |
8 #include <type_traits> | |
9 | |
10 #include "mojo/public/cpp/bindings/lib/array_internal.h" | |
11 #include "mojo/public/cpp/bindings/lib/array_serialization.h" | |
12 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" | |
13 #include "mojo/public/cpp/bindings/lib/iterator_util.h" | |
14 #include "mojo/public/cpp/bindings/lib/map_data_internal.h" | |
15 #include "mojo/public/cpp/bindings/lib/map_internal.h" | |
16 #include "mojo/public/cpp/bindings/lib/string_serialization.h" | |
17 #include "mojo/public/cpp/bindings/lib/template_util.h" | |
18 #include "mojo/public/cpp/bindings/map.h" | |
19 | |
20 namespace mojo { | |
21 namespace internal { | |
22 | |
23 template <typename MapType, | |
24 typename DataType, | |
25 bool value_is_move_only_type = IsMoveOnlyType<MapType>::value, | |
26 bool is_union = IsUnionDataType< | |
27 typename std::remove_pointer<DataType>::type>::value> | |
28 struct MapSerializer; | |
29 | |
30 template <typename MapType, typename DataType> | |
31 struct MapSerializer<MapType, DataType, false, false> { | |
32 static size_t GetBaseArraySize(size_t count) { | |
33 return Align(count * sizeof(DataType)); | |
34 } | |
35 static size_t GetItemSize(const MapType& item) { return 0; } | |
36 }; | |
37 | |
38 template <> | |
39 struct MapSerializer<bool, bool, false, false> { | |
40 static size_t GetBaseArraySize(size_t count) { | |
41 return Align((count + 7) / 8); | |
42 } | |
43 static size_t GetItemSize(bool item) { return 0; } | |
44 }; | |
45 | |
46 template <typename H> | |
47 struct MapSerializer<ScopedHandleBase<H>, H, true, false> { | |
48 static size_t GetBaseArraySize(size_t count) { | |
49 return Align(count * sizeof(H)); | |
50 } | |
51 static size_t GetItemSize(const ScopedHandleBase<H>& item) { return 0; } | |
52 }; | |
53 | |
54 // This template must only apply to pointer mojo entity (structs and arrays). | |
55 // This is done by ensuring that WrapperTraits<S>::DataType is a pointer. | |
56 template <typename S> | |
57 struct MapSerializer< | |
58 S, | |
59 typename std::enable_if< | |
60 std::is_pointer<typename WrapperTraits<S>::DataType>::value, | |
61 typename WrapperTraits<S>::DataType>::type, | |
62 true, | |
63 false> { | |
64 typedef | |
65 typename std::remove_pointer<typename WrapperTraits<S>::DataType>::type | |
66 S_Data; | |
67 static size_t GetBaseArraySize(size_t count) { | |
68 return count * sizeof(StructPointer<S_Data>); | |
69 } | |
70 static size_t GetItemSize(const S& item) { | |
71 return item ? GetSerializedSize_(*UnwrapConstStructPtr<S>::value(item)) : 0; | |
72 } | |
73 }; | |
74 | |
75 template <typename U, typename U_Data> | |
76 struct MapSerializer<U, U_Data, true, true> { | |
77 static size_t GetBaseArraySize(size_t count) { | |
78 // GetSerializedSize_ (called in GetItemSize()) will account for | |
79 // sizeof(U_Data), so prevent double counting by having this count be 0. | |
80 return 0; | |
81 } | |
82 static size_t GetItemSize(const U& item) { return GetSerializedSize_(item); } | |
83 }; | |
84 | |
85 template <> | |
86 struct MapSerializer<String, String_Data*, false, false> { | |
87 static size_t GetBaseArraySize(size_t count) { | |
88 return count * sizeof(StringPointer); | |
89 } | |
90 static size_t GetItemSize(const String& item) { | |
91 return GetSerializedSize_(item); | |
92 } | |
93 }; | |
94 | |
95 } // namespace internal | |
96 | |
97 // TODO(erg): This can't go away yet. We still need to calculate out the size | |
98 // of a struct header, and two arrays. | |
99 template <typename MapKey, typename MapValue> | |
100 inline size_t GetSerializedSize_(const Map<MapKey, MapValue>& input) { | |
101 if (!input) | |
102 return 0; | |
103 typedef typename internal::WrapperTraits<MapKey>::DataType DataKey; | |
104 typedef typename internal::WrapperTraits<MapValue>::DataType DataValue; | |
105 | |
106 size_t count = input.size(); | |
107 size_t struct_overhead = sizeof(mojo::internal::Map_Data<DataKey, DataValue>); | |
108 size_t key_base_size = | |
109 sizeof(internal::ArrayHeader) + | |
110 internal::MapSerializer<MapKey, DataKey>::GetBaseArraySize(count); | |
111 size_t value_base_size = | |
112 sizeof(internal::ArrayHeader) + | |
113 internal::MapSerializer<MapValue, DataValue>::GetBaseArraySize(count); | |
114 | |
115 size_t key_data_size = 0; | |
116 size_t value_data_size = 0; | |
117 for (auto it = input.cbegin(); it != input.cend(); ++it) { | |
118 key_data_size += | |
119 internal::MapSerializer<MapKey, DataKey>::GetItemSize(it.GetKey()); | |
120 value_data_size += | |
121 internal::MapSerializer<MapValue, DataValue>::GetItemSize( | |
122 it.GetValue()); | |
123 } | |
124 | |
125 return struct_overhead + key_base_size + key_data_size + value_base_size + | |
126 value_data_size; | |
127 } | |
128 | |
129 // SerializeMap_ will return ValidationError::NONE on success and set | |
130 // |output| accordingly. On failure, |input| will be partially serialized into | |
131 // |output| up until an error occurs (which is propagated up and returned by | |
132 // SerializeMap_), in which case |buf| is also partially consumed. | |
133 // | |
134 // We don't need an ArrayValidateParams instance for key validation since | |
135 // we can deduce it from the Key type. (which can only be primitive types or | |
136 // non-nullable strings.) | |
137 template <typename MapKey, | |
138 typename MapValue, | |
139 typename DataKey, | |
140 typename DataValue> | |
141 inline internal::ValidationError SerializeMap_( | |
142 Map<MapKey, MapValue>* input, | |
143 internal::Buffer* buf, | |
144 internal::Map_Data<DataKey, DataValue>** output, | |
145 const internal::ArrayValidateParams* value_validate_params) { | |
146 if (input->is_null()) { | |
147 // |input| could be a nullable map, in which case |output| is serialized as | |
148 // null, which is valid. | |
149 *output = nullptr; | |
150 return internal::ValidationError::NONE; | |
151 } | |
152 | |
153 internal::Map_Data<DataKey, DataValue>* result = | |
154 internal::Map_Data<DataKey, DataValue>::New(buf); | |
155 | |
156 // We *must* serialize the keys before we allocate an Array_Data for the | |
157 // values. | |
158 internal::Array_Data<DataKey>* keys_data = | |
159 internal::Array_Data<DataKey>::New(input->size(), buf); | |
160 result->keys.ptr = keys_data; | |
161 | |
162 internal::MapKeyIterator<MapKey, MapValue> key_iter(input); | |
163 const internal::ArrayValidateParams* key_validate_params = | |
164 internal::MapKeyValidateParamsFactory<DataKey>::Get(); | |
165 | |
166 auto keys_retval = | |
167 internal::ArraySerializer<MapKey, DataKey>::SerializeElements( | |
168 key_iter.begin(), input->size(), buf, result->keys.ptr, | |
169 key_validate_params); | |
170 if (keys_retval != internal::ValidationError::NONE) | |
171 return keys_retval; | |
172 | |
173 // Now we try allocate an Array_Data for the values | |
174 internal::Array_Data<DataValue>* values_data = | |
175 internal::Array_Data<DataValue>::New(input->size(), buf); | |
176 result->values.ptr = values_data; | |
177 | |
178 internal::MapValueIterator<MapKey, MapValue> value_iter(input); | |
179 | |
180 auto values_retval = | |
181 internal::ArraySerializer<MapValue, DataValue>::SerializeElements( | |
182 value_iter.begin(), input->size(), buf, result->values.ptr, | |
183 value_validate_params); | |
184 if (values_retval != internal::ValidationError::NONE) | |
185 return values_retval; | |
186 | |
187 *output = result; | |
188 return internal::ValidationError::NONE; | |
189 } | |
190 | |
191 template <typename MapKey, | |
192 typename MapValue, | |
193 typename DataKey, | |
194 typename DataValue> | |
195 inline void Deserialize_(internal::Map_Data<DataKey, DataValue>* input, | |
196 Map<MapKey, MapValue>* output) { | |
197 if (input) { | |
198 Array<MapKey> keys; | |
199 Array<MapValue> values; | |
200 | |
201 Deserialize_(input->keys.ptr, &keys); | |
202 Deserialize_(input->values.ptr, &values); | |
203 | |
204 *output = Map<MapKey, MapValue>(keys.Pass(), values.Pass()); | |
205 } else { | |
206 output->reset(); | |
207 } | |
208 } | |
209 | |
210 } // namespace mojo | |
211 | |
212 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ | |
OLD | NEW |