Allow modern decoding of std::optional<T>
[WebKit-https.git] / Source / WebKit / Platform / IPC / ArgumentCoders.h
1 /*
2  * Copyright (C) 2010-2016 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 #pragma once
27
28 #include "Decoder.h"
29 #include "Encoder.h"
30 #include <utility>
31 #include <wtf/Expected.h>
32 #include <wtf/Forward.h>
33 #include <wtf/HashCountedSet.h>
34 #include <wtf/HashMap.h>
35 #include <wtf/HashSet.h>
36 #include <wtf/OptionSet.h>
37 #include <wtf/Optional.h>
38 #include <wtf/SHA1.h>
39 #include <wtf/Variant.h>
40 #include <wtf/Vector.h>
41
42 namespace IPC {
43
44 // An argument coder works on POD types
45 template<typename T> struct SimpleArgumentCoder {
46     static void encode(Encoder& encoder, const T& t)
47     {
48         encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(&t), sizeof(T), alignof(T));
49     }
50
51     static bool decode(Decoder& 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<OptionSet<T>> {
58     static void encode(Encoder& encoder, const OptionSet<T>& optionSet)
59     {
60         encoder << (static_cast<uint64_t>(optionSet.toRaw()));
61     }
62
63     static bool decode(Decoder& decoder, OptionSet<T>& optionSet)
64     {
65         uint64_t value;
66         if (!decoder.decode(value))
67             return false;
68
69         optionSet = OptionSet<T>::fromRaw(value);
70         return true;
71     }
72
73     static std::optional<OptionSet<T>> decode(Decoder& decoder)
74     {
75         std::optional<uint64_t> value;
76         decoder >> value;
77         if (!value)
78             return std::nullopt;
79         return OptionSet<T>::fromRaw(*value);
80     }
81 };
82
83 template<typename T> struct ArgumentCoder<std::optional<T>> {
84     static void encode(Encoder& encoder, const std::optional<T>& optional)
85     {
86         if (!optional) {
87             encoder << false;
88             return;
89         }
90
91         encoder << true;
92         encoder << optional.value();
93     }
94
95     static bool decode(Decoder& decoder, std::optional<T>& optional)
96     {
97         bool isEngaged;
98         if (!decoder.decode(isEngaged))
99             return false;
100
101         if (!isEngaged) {
102             optional = std::nullopt;
103             return true;
104         }
105
106         T value;
107         if (!decoder.decode(value))
108             return false;
109
110         optional = WTFMove(value);
111         return true;
112     }
113     
114     static std::optional<std::optional<T>> decode(Decoder& decoder)
115     {
116         std::optional<bool> isEngaged;
117         decoder >> isEngaged;
118         if (!isEngaged)
119             return std::nullopt;
120         if (*isEngaged) {
121             std::optional<T> value;
122             decoder >> value;
123             if (!value)
124                 return std::nullopt;
125             return std::optional<std::optional<T>>(WTFMove(*value));
126         }
127         return std::optional<std::optional<T>>(std::optional<T>(std::nullopt));
128     }
129 };
130
131 template<typename T, typename U> struct ArgumentCoder<std::pair<T, U>> {
132     static void encode(Encoder& encoder, const std::pair<T, U>& pair)
133     {
134         encoder << pair.first << pair.second;
135     }
136
137     static bool decode(Decoder& decoder, std::pair<T, U>& pair)
138     {
139         T first;
140         if (!decoder.decode(first))
141             return false;
142
143         U second;
144         if (!decoder.decode(second))
145             return false;
146
147         pair.first = first;
148         pair.second = second;
149         return true;
150     }
151
152     static std::optional<std::pair<T, U>> decode(Decoder& decoder)
153     {
154         std::optional<T> first;
155         decoder >> first;
156         if (!first)
157             return std::nullopt;
158         
159         std::optional<U> second;
160         decoder >> second;
161         if (!second)
162             return std::nullopt;
163         
164         return {{ WTFMove(*first), WTFMove(*second) }};
165     }
166 };
167
168 template<size_t index, typename... Elements>
169 struct TupleCoder {
170     static void encode(Encoder& encoder, const std::tuple<Elements...>& tuple)
171     {
172         encoder << std::get<sizeof...(Elements) - index>(tuple);
173         TupleCoder<index - 1, Elements...>::encode(encoder, tuple);
174     }
175
176     template<typename U = typename std::remove_reference<typename std::tuple_element<sizeof...(Elements) - index, std::tuple<Elements...>>::type>::type, std::enable_if_t<!UsesModernDecoder<U>::value>* = nullptr>
177     static bool decode(Decoder& decoder, std::tuple<Elements...>& tuple)
178     {
179         if (!decoder.decode(std::get<sizeof...(Elements) - index>(tuple)))
180             return false;
181         return TupleCoder<index - 1, Elements...>::decode(decoder, tuple);
182     }
183     
184     template<typename U = typename std::remove_reference<typename std::tuple_element<sizeof...(Elements) - index, std::tuple<Elements...>>::type>::type, std::enable_if_t<UsesModernDecoder<U>::value>* = nullptr>
185     static bool decode(Decoder& decoder, std::tuple<Elements...>& tuple)
186     {
187         std::optional<U> optional;
188         decoder >> optional;
189         if (!optional)
190             return false;
191         std::get<sizeof...(Elements) - index>(tuple) = WTFMove(*optional);
192         return TupleCoder<index - 1, Elements...>::decode(decoder, tuple);
193     }
194 };
195
196 template<typename... Elements>
197 struct TupleCoder<0, Elements...> {
198     static void encode(Encoder&, const std::tuple<Elements...>&)
199     {
200     }
201
202     static bool decode(Decoder&, std::tuple<Elements...>&)
203     {
204         return true;
205     }
206 };
207
208 template<typename... Elements> struct ArgumentCoder<std::tuple<Elements...>> {
209     static void encode(Encoder& encoder, const std::tuple<Elements...>& tuple)
210     {
211         TupleCoder<sizeof...(Elements), Elements...>::encode(encoder, tuple);
212     }
213
214     static bool decode(Decoder& decoder, std::tuple<Elements...>& tuple)
215     {
216         return TupleCoder<sizeof...(Elements), Elements...>::decode(decoder, tuple);
217     }
218 };
219
220
221 template<typename Rep, typename Period> struct ArgumentCoder<std::chrono::duration<Rep, Period>> {
222     static void encode(Encoder& encoder, const std::chrono::duration<Rep, Period>& duration)
223     {
224         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.");
225         encoder << static_cast<int64_t>(duration.count());
226     }
227
228     static bool decode(Decoder& decoder, std::chrono::duration<Rep, Period>& result)
229     {
230         int64_t count;
231         if (!decoder.decode(count))
232             return false;
233         result = std::chrono::duration<Rep, Period>(static_cast<Rep>(count));
234         return true;
235     }
236 };
237
238 template<typename KeyType, typename ValueType> struct ArgumentCoder<WTF::KeyValuePair<KeyType, ValueType>> {
239     static void encode(Encoder& encoder, const WTF::KeyValuePair<KeyType, ValueType>& pair)
240     {
241         encoder << pair.key << pair.value;
242     }
243
244     static bool decode(Decoder& decoder, WTF::KeyValuePair<KeyType, ValueType>& pair)
245     {
246         KeyType key;
247         if (!decoder.decode(key))
248             return false;
249
250         ValueType value;
251         if (!decoder.decode(value))
252             return false;
253
254         pair.key = key;
255         pair.value = value;
256         return true;
257     }
258 };
259
260 template<bool fixedSizeElements, typename T, size_t inlineCapacity> struct VectorArgumentCoder;
261
262 template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<false, T, inlineCapacity> {
263     static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector)
264     {
265         encoder << static_cast<uint64_t>(vector.size());
266         for (size_t i = 0; i < vector.size(); ++i)
267             encoder << vector[i];
268     }
269
270     static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector)
271     {
272         std::optional<Vector<T, inlineCapacity>> optional;
273         decoder >> optional;
274         if (!optional)
275             return false;
276         vector = WTFMove(*optional);
277         return true;
278     }
279
280     static std::optional<Vector<T, inlineCapacity>> decode(Decoder& decoder)
281     {
282         uint64_t size;
283         if (!decoder.decode(size))
284             return std::nullopt;
285
286         Vector<T, inlineCapacity> vector;
287         for (size_t i = 0; i < size; ++i) {
288             std::optional<T> element;
289             decoder >> element;
290             if (!element)
291                 return std::nullopt;
292             vector.append(WTFMove(*element));
293         }
294         vector.shrinkToFit();
295         return WTFMove(vector);
296     }
297 };
298
299 template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<true, T, inlineCapacity> {
300     static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector)
301     {
302         encoder << static_cast<uint64_t>(vector.size());
303         encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T), alignof(T));
304     }
305     
306     static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector)
307     {
308         uint64_t size;
309         if (!decoder.decode(size))
310             return false;
311
312         // Since we know the total size of the elements, we can allocate the vector in
313         // one fell swoop. Before allocating we must however make sure that the decoder buffer
314         // is big enough.
315         if (!decoder.bufferIsLargeEnoughToContain<T>(size)) {
316             decoder.markInvalid();
317             return false;
318         }
319
320         Vector<T, inlineCapacity> temp;
321         temp.grow(size);
322
323         decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(temp.data()), size * sizeof(T), alignof(T));
324
325         vector.swap(temp);
326         return true;
327     }
328     
329     static std::optional<Vector<T, inlineCapacity>> decode(Decoder& decoder)
330     {
331         uint64_t size;
332         if (!decoder.decode(size))
333             return std::nullopt;
334         
335         // Since we know the total size of the elements, we can allocate the vector in
336         // one fell swoop. Before allocating we must however make sure that the decoder buffer
337         // is big enough.
338         if (!decoder.bufferIsLargeEnoughToContain<T>(size)) {
339             decoder.markInvalid();
340             return std::nullopt;
341         }
342         
343         Vector<T, inlineCapacity> vector;
344         vector.grow(size);
345         
346         decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(vector.data()), size * sizeof(T), alignof(T));
347         
348         return vector;
349     }
350 };
351
352 template<typename T, size_t inlineCapacity> struct ArgumentCoder<Vector<T, inlineCapacity>> : VectorArgumentCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { };
353
354 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct ArgumentCoder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> {
355     typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
356
357     static void encode(Encoder& encoder, const HashMapType& hashMap)
358     {
359         encoder << static_cast<uint64_t>(hashMap.size());
360         for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it)
361             encoder << *it;
362     }
363
364     static bool decode(Decoder& decoder, HashMapType& hashMap)
365     {
366         uint64_t hashMapSize;
367         if (!decoder.decode(hashMapSize))
368             return false;
369
370         HashMapType tempHashMap;
371         for (uint64_t i = 0; i < hashMapSize; ++i) {
372             KeyArg key;
373             MappedArg value;
374             if (!decoder.decode(key))
375                 return false;
376             if (!decoder.decode(value))
377                 return false;
378
379             if (!tempHashMap.add(key, value).isNewEntry) {
380                 // The hash map already has the specified key, bail.
381                 decoder.markInvalid();
382                 return false;
383             }
384         }
385
386         hashMap.swap(tempHashMap);
387         return true;
388     }
389
390     static std::optional<HashMapType> decode(Decoder& decoder)
391     {
392         uint64_t hashMapSize;
393         if (!decoder.decode(hashMapSize))
394             return std::nullopt;
395         
396         HashMapType hashMap;
397         for (uint64_t i = 0; i < hashMapSize; ++i) {
398             KeyArg key;
399             MappedArg value;
400             if (!decoder.decode(key))
401                 return std::nullopt;
402             if (!decoder.decode(value))
403                 return std::nullopt;
404             
405             if (!hashMap.add(key, value).isNewEntry) {
406                 // The hash map already has the specified key, bail.
407                 decoder.markInvalid();
408                 return std::nullopt;
409             }
410         }
411         
412         return WTFMove(hashMap);
413     }
414 };
415
416 template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct ArgumentCoder<HashSet<KeyArg, HashArg, KeyTraitsArg>> {
417     typedef HashSet<KeyArg, HashArg, KeyTraitsArg> HashSetType;
418
419     static void encode(Encoder& encoder, const HashSetType& hashSet)
420     {
421         encoder << static_cast<uint64_t>(hashSet.size());
422         for (typename HashSetType::const_iterator it = hashSet.begin(), end = hashSet.end(); it != end; ++it)
423             encoder << *it;
424     }
425
426     static bool decode(Decoder& decoder, HashSetType& hashSet)
427     {
428         uint64_t hashSetSize;
429         if (!decoder.decode(hashSetSize))
430             return false;
431
432         HashSetType tempHashSet;
433         for (uint64_t i = 0; i < hashSetSize; ++i) {
434             KeyArg key;
435             if (!decoder.decode(key))
436                 return false;
437
438             if (!tempHashSet.add(key).isNewEntry) {
439                 // The hash map already has the specified key, bail.
440                 decoder.markInvalid();
441                 return false;
442             }
443         }
444
445         hashSet.swap(tempHashSet);
446         return true;
447     }
448 };
449
450 template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct ArgumentCoder<HashCountedSet<KeyArg, HashArg, KeyTraitsArg>> {
451     typedef HashCountedSet<KeyArg, HashArg, KeyTraitsArg> HashCountedSetType;
452     
453     static void encode(Encoder& encoder, const HashCountedSetType& hashCountedSet)
454     {
455         encoder << static_cast<uint64_t>(hashCountedSet.size());
456         
457         for (auto entry : hashCountedSet) {
458             encoder << entry.key;
459             encoder << entry.value;
460         }
461     }
462     
463     static bool decode(Decoder& decoder, HashCountedSetType& hashCountedSet)
464     {
465         uint64_t hashCountedSetSize;
466         if (!decoder.decode(hashCountedSetSize))
467             return false;
468         
469         HashCountedSetType tempHashCountedSet;
470         for (uint64_t i = 0; i < hashCountedSetSize; ++i) {
471             KeyArg key;
472             if (!decoder.decode(key))
473                 return false;
474             
475             unsigned count;
476             if (!decoder.decode(count))
477                 return false;
478             
479             if (!tempHashCountedSet.add(key, count).isNewEntry) {
480                 // The hash counted set already has the specified key, bail.
481                 decoder.markInvalid();
482                 return false;
483             }
484         }
485         
486         hashCountedSet.swap(tempHashCountedSet);
487         return true;
488     }
489 };
490
491 template<typename ValueType, typename ErrorType> struct ArgumentCoder<WTF::Expected<ValueType, ErrorType>> {
492     static void encode(Encoder& encoder, const WTF::Expected<ValueType, ErrorType>& expected)
493     {
494         if (!expected.hasValue()) {
495             encoder << false;
496             encoder << expected.error();
497             return;
498         }
499         encoder << true;
500         encoder << expected.value();
501     }
502
503     static std::optional<WTF::Expected<ValueType, ErrorType>> decode(Decoder& decoder)
504     {
505         std::optional<bool> hasValue;
506         decoder >> hasValue;
507         if (!hasValue)
508             return std::nullopt;
509         
510         if (*hasValue) {
511             std::optional<ValueType> value;
512             decoder >> value;
513             if (!value)
514                 return std::nullopt;
515             
516             WTF::Expected<ValueType, ErrorType> expected(WTFMove(*value));
517             return WTFMove(expected);
518         }
519         std::optional<ErrorType> error;
520         decoder >> error;
521         if (!error)
522             return std::nullopt;
523         return { makeUnexpected(WTFMove(*error)) };
524     }
525 };
526
527 template<> struct ArgumentCoder<std::chrono::system_clock::time_point> {
528     static void encode(Encoder&, const std::chrono::system_clock::time_point&);
529     static bool decode(Decoder&, std::chrono::system_clock::time_point&);
530     static std::optional<std::chrono::system_clock::time_point> decode(Decoder&);
531 };
532
533 template<> struct ArgumentCoder<AtomicString> {
534     static void encode(Encoder&, const AtomicString&);
535     static bool decode(Decoder&, AtomicString&);
536 };
537
538 template<> struct ArgumentCoder<CString> {
539     static void encode(Encoder&, const CString&);
540     static bool decode(Decoder&, CString&);
541 };
542
543 template<> struct ArgumentCoder<String> {
544     static void encode(Encoder&, const String&);
545     static bool decode(Decoder&, String&);
546     static std::optional<String> decode(Decoder&);
547 };
548
549 template<> struct ArgumentCoder<SHA1::Digest> {
550     static void encode(Encoder&, const SHA1::Digest&);
551     static bool decode(Decoder&, SHA1::Digest&);
552 };
553
554 } // namespace IPC