Unreviewed, rolling out r187812.
[WebKit-https.git] / Source / WebKit2 / Platform / IPC / ArgumentCoders.h
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef ArgumentCoders_h
27 #define ArgumentCoders_h
28
29 #include "ArgumentDecoder.h"
30 #include "ArgumentEncoder.h"
31 #include <utility>
32 #include <wtf/Forward.h>
33 #include <wtf/HashMap.h>
34 #include <wtf/HashSet.h>
35 #include <wtf/Optional.h>
36 #include <wtf/Vector.h>
37
38 #if HAVE(DTRACE)
39 #include <uuid/uuid.h>
40 #endif
41
42 namespace IPC {
43
44 // An argument coder works on POD types
45 template<typename T> struct SimpleArgumentCoder {
46     static void encode(ArgumentEncoder& encoder, const T& t)
47     {
48         encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(&t), sizeof(T), alignof(T));
49     }
50
51     static bool decode(ArgumentDecoder& decoder, T& t)
52     {
53         return decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(&t), sizeof(T), alignof(T));
54     }
55 };
56
57 template<typename T> struct ArgumentCoder<WTF::Optional<T>> {
58     static void encode(ArgumentEncoder& encoder, const WTF::Optional<T>& optional)
59     {
60         if (!optional) {
61             encoder << false;
62             return;
63         }
64
65         encoder << true;
66         encoder << optional.value();
67     }
68
69     static bool decode(ArgumentDecoder& decoder, WTF::Optional<T>& optional)
70     {
71         bool isEngaged;
72         if (!decoder.decode(isEngaged))
73             return false;
74
75         if (!isEngaged) {
76             optional = Nullopt;
77             return true;
78         }
79
80         T value;
81         if (!decoder.decode(value))
82             return false;
83
84         optional = WTF::move(value);
85         return true;
86     }
87 };
88
89 template<typename T, typename U> struct ArgumentCoder<std::pair<T, U>> {
90     static void encode(ArgumentEncoder& encoder, const std::pair<T, U>& pair)
91     {
92         encoder << pair.first << pair.second;
93     }
94
95     static bool decode(ArgumentDecoder& decoder, std::pair<T, U>& pair)
96     {
97         T first;
98         if (!decoder.decode(first))
99             return false;
100
101         U second;
102         if (!decoder.decode(second))
103             return false;
104
105         pair.first = first;
106         pair.second = second;
107         return true;
108     }
109 };
110
111 template<typename Rep, typename Period> struct ArgumentCoder<std::chrono::duration<Rep, Period>> {
112     static void encode(ArgumentEncoder& encoder, const std::chrono::duration<Rep, Period>& duration)
113     {
114         static_assert(std::is_integral<Rep>::value && std::is_signed<Rep>::value && sizeof(Rep) <= sizeof(int64_t), "Serialization of this Rep type is not supported yet. Only signed integer type which can be fit in an int64_t is currently supported.");
115         encoder << static_cast<int64_t>(duration.count());
116     }
117
118     static bool decode(ArgumentDecoder& decoder, std::chrono::duration<Rep, Period>& result)
119     {
120         int64_t count;
121         if (!decoder.decode(count))
122             return false;
123         result = std::chrono::duration<Rep, Period>(static_cast<Rep>(count));
124         return true;
125     }
126 };
127
128 template<typename KeyType, typename ValueType> struct ArgumentCoder<WTF::KeyValuePair<KeyType, ValueType>> {
129     static void encode(ArgumentEncoder& encoder, const WTF::KeyValuePair<KeyType, ValueType>& pair)
130     {
131         encoder << pair.key << pair.value;
132     }
133
134     static bool decode(ArgumentDecoder& decoder, WTF::KeyValuePair<KeyType, ValueType>& pair)
135     {
136         KeyType key;
137         if (!decoder.decode(key))
138             return false;
139
140         ValueType value;
141         if (!decoder.decode(value))
142             return false;
143
144         pair.key = key;
145         pair.value = value;
146         return true;
147     }
148 };
149
150 template<bool fixedSizeElements, typename T, size_t inlineCapacity> struct VectorArgumentCoder;
151
152 template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<false, T, inlineCapacity> {
153     static void encode(ArgumentEncoder& encoder, const Vector<T, inlineCapacity>& vector)
154     {
155         encoder << static_cast<uint64_t>(vector.size());
156         for (size_t i = 0; i < vector.size(); ++i)
157             encoder << vector[i];
158     }
159
160     static bool decode(ArgumentDecoder& decoder, Vector<T, inlineCapacity>& vector)
161     {
162         uint64_t size;
163         if (!decoder.decode(size))
164             return false;
165
166         Vector<T, inlineCapacity> tmp;
167         for (size_t i = 0; i < size; ++i) {
168             T element;
169             if (!decoder.decode(element))
170                 return false;
171             
172             tmp.append(WTF::move(element));
173         }
174
175         tmp.shrinkToFit();
176         vector.swap(tmp);
177         return true;
178     }
179 };
180
181 template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<true, T, inlineCapacity> {
182     static void encode(ArgumentEncoder& encoder, const Vector<T, inlineCapacity>& vector)
183     {
184         encoder << static_cast<uint64_t>(vector.size());
185         encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T), alignof(T));
186     }
187     
188     static bool decode(ArgumentDecoder& decoder, Vector<T, inlineCapacity>& vector)
189     {
190         uint64_t size;
191         if (!decoder.decode(size))
192             return false;
193
194         // Since we know the total size of the elements, we can allocate the vector in
195         // one fell swoop. Before allocating we must however make sure that the decoder buffer
196         // is big enough.
197         if (!decoder.bufferIsLargeEnoughToContain<T>(size)) {
198             decoder.markInvalid();
199             return false;
200         }
201
202         Vector<T, inlineCapacity> temp;
203         temp.resize(size);
204
205         decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(temp.data()), size * sizeof(T), alignof(T));
206
207         vector.swap(temp);
208         return true;
209     }
210 };
211
212 template<typename T, size_t inlineCapacity> struct ArgumentCoder<Vector<T, inlineCapacity>> : VectorArgumentCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { };
213
214 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct ArgumentCoder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> {
215     typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
216
217     static void encode(ArgumentEncoder& encoder, const HashMapType& hashMap)
218     {
219         encoder << static_cast<uint64_t>(hashMap.size());
220         for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it)
221             encoder << *it;
222     }
223
224     static bool decode(ArgumentDecoder& decoder, HashMapType& hashMap)
225     {
226         uint64_t hashMapSize;
227         if (!decoder.decode(hashMapSize))
228             return false;
229
230         HashMapType tempHashMap;
231         for (uint64_t i = 0; i < hashMapSize; ++i) {
232             KeyArg key;
233             MappedArg value;
234             if (!decoder.decode(key))
235                 return false;
236             if (!decoder.decode(value))
237                 return false;
238
239             if (!tempHashMap.add(key, value).isNewEntry) {
240                 // The hash map already has the specified key, bail.
241                 decoder.markInvalid();
242                 return false;
243             }
244         }
245
246         hashMap.swap(tempHashMap);
247         return true;
248     }
249 };
250
251 template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct ArgumentCoder<HashSet<KeyArg, HashArg, KeyTraitsArg>> {
252     typedef HashSet<KeyArg, HashArg, KeyTraitsArg> HashSetType;
253
254     static void encode(ArgumentEncoder& encoder, const HashSetType& hashSet)
255     {
256         encoder << static_cast<uint64_t>(hashSet.size());
257         for (typename HashSetType::const_iterator it = hashSet.begin(), end = hashSet.end(); it != end; ++it)
258             encoder << *it;
259     }
260
261     static bool decode(ArgumentDecoder& decoder, HashSetType& hashSet)
262     {
263         uint64_t hashSetSize;
264         if (!decoder.decode(hashSetSize))
265             return false;
266
267         HashSetType tempHashSet;
268         for (uint64_t i = 0; i < hashSetSize; ++i) {
269             KeyArg key;
270             if (!decoder.decode(key))
271                 return false;
272
273             if (!tempHashSet.add(key).isNewEntry) {
274                 // The hash map already has the specified key, bail.
275                 decoder.markInvalid();
276                 return false;
277             }
278         }
279
280         hashSet.swap(tempHashSet);
281         return true;
282     }
283 };
284
285 template<> struct ArgumentCoder<std::chrono::system_clock::time_point> {
286     static void encode(ArgumentEncoder&, const std::chrono::system_clock::time_point&);
287     static bool decode(ArgumentDecoder&, std::chrono::system_clock::time_point&);
288 };
289
290 template<> struct ArgumentCoder<AtomicString> {
291     static void encode(ArgumentEncoder&, const AtomicString&);
292     static bool decode(ArgumentDecoder&, AtomicString&);
293 };
294
295 template<> struct ArgumentCoder<CString> {
296     static void encode(ArgumentEncoder&, const CString&);
297     static bool decode(ArgumentDecoder&, CString&);
298 };
299
300 template<> struct ArgumentCoder<String> {
301     static void encode(ArgumentEncoder&, const String&);
302     static bool decode(ArgumentDecoder&, String&);
303 };
304
305 #if HAVE(DTRACE)
306 template<> struct ArgumentCoder<uuid_t> {
307     static void encode(ArgumentEncoder&, const uuid_t&);
308     static bool decode(ArgumentDecoder&, uuid_t&);
309 };
310 #endif
311
312 } // namespace IPC
313
314 #endif // ArgumentCoders_h