Update std::expected to match libc++ coding style
[WebKit-https.git] / Source / WebKit / Platform / IPC / ArgumentCoders.h
index 86166c8..8384525 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include "Decoder.h"
 #include "Encoder.h"
+#include <chrono>
 #include <utility>
 #include <wtf/Forward.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/HashMap.h>
-#include <wtf/HashSet.h>
-#include <wtf/OptionSet.h>
-#include <wtf/Optional.h>
 #include <wtf/SHA1.h>
-#include <wtf/Variant.h>
-#include <wtf/Vector.h>
 
 namespace IPC {
 
@@ -68,6 +62,15 @@ template<typename T> struct ArgumentCoder<OptionSet<T>> {
         optionSet = OptionSet<T>::fromRaw(value);
         return true;
     }
+
+    static std::optional<OptionSet<T>> decode(Decoder& decoder)
+    {
+        std::optional<uint64_t> value;
+        decoder >> value;
+        if (!value)
+            return std::nullopt;
+        return OptionSet<T>::fromRaw(*value);
+    }
 };
 
 template<typename T> struct ArgumentCoder<std::optional<T>> {
@@ -100,6 +103,22 @@ template<typename T> struct ArgumentCoder<std::optional<T>> {
         optional = WTFMove(value);
         return true;
     }
+    
+    static std::optional<std::optional<T>> decode(Decoder& decoder)
+    {
+        std::optional<bool> isEngaged;
+        decoder >> isEngaged;
+        if (!isEngaged)
+            return std::nullopt;
+        if (*isEngaged) {
+            std::optional<T> value;
+            decoder >> value;
+            if (!value)
+                return std::nullopt;
+            return std::optional<std::optional<T>>(WTFMove(*value));
+        }
+        return std::optional<std::optional<T>>(std::optional<T>(std::nullopt));
+    }
 };
 
 template<typename T, typename U> struct ArgumentCoder<std::pair<T, U>> {
@@ -122,6 +141,21 @@ template<typename T, typename U> struct ArgumentCoder<std::pair<T, U>> {
         pair.second = second;
         return true;
     }
+
+    static std::optional<std::pair<T, U>> decode(Decoder& decoder)
+    {
+        std::optional<T> first;
+        decoder >> first;
+        if (!first)
+            return std::nullopt;
+        
+        std::optional<U> second;
+        decoder >> second;
+        if (!second)
+            return std::nullopt;
+        
+        return {{ WTFMove(*first), WTFMove(*second) }};
+    }
 };
 
 template<size_t index, typename... Elements>
@@ -132,12 +166,24 @@ struct TupleCoder {
         TupleCoder<index - 1, Elements...>::encode(encoder, tuple);
     }
 
+    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>
     static bool decode(Decoder& decoder, std::tuple<Elements...>& tuple)
     {
         if (!decoder.decode(std::get<sizeof...(Elements) - index>(tuple)))
             return false;
         return TupleCoder<index - 1, Elements...>::decode(decoder, tuple);
     }
+    
+    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>
+    static bool decode(Decoder& decoder, std::tuple<Elements...>& tuple)
+    {
+        std::optional<U> optional;
+        decoder >> optional;
+        if (!optional)
+            return false;
+        std::get<sizeof...(Elements) - index>(tuple) = WTFMove(*optional);
+        return TupleCoder<index - 1, Elements...>::decode(decoder, tuple);
+    }
 };
 
 template<typename... Elements>
@@ -216,22 +262,30 @@ template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<false, T,
 
     static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector)
     {
+        std::optional<Vector<T, inlineCapacity>> optional;
+        decoder >> optional;
+        if (!optional)
+            return false;
+        vector = WTFMove(*optional);
+        return true;
+    }
+
+    static std::optional<Vector<T, inlineCapacity>> decode(Decoder& decoder)
+    {
         uint64_t size;
         if (!decoder.decode(size))
-            return false;
+            return std::nullopt;
 
-        Vector<T, inlineCapacity> tmp;
+        Vector<T, inlineCapacity> vector;
         for (size_t i = 0; i < size; ++i) {
-            T element;
-            if (!decoder.decode(element))
-                return false;
-            
-            tmp.append(WTFMove(element));
+            std::optional<T> element;
+            decoder >> element;
+            if (!element)
+                return std::nullopt;
+            vector.append(WTFMove(*element));
         }
-
-        tmp.shrinkToFit();
-        vector.swap(tmp);
-        return true;
+        vector.shrinkToFit();
+        return WTFMove(vector);
     }
 };
 
@@ -257,13 +311,35 @@ template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<true, T,
         }
 
         Vector<T, inlineCapacity> temp;
-        temp.resize(size);
+        temp.grow(size);
 
         decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(temp.data()), size * sizeof(T), alignof(T));
 
         vector.swap(temp);
         return true;
     }
+    
+    static std::optional<Vector<T, inlineCapacity>> decode(Decoder& decoder)
+    {
+        uint64_t size;
+        if (!decoder.decode(size))
+            return std::nullopt;
+        
+        // Since we know the total size of the elements, we can allocate the vector in
+        // one fell swoop. Before allocating we must however make sure that the decoder buffer
+        // is big enough.
+        if (!decoder.bufferIsLargeEnoughToContain<T>(size)) {
+            decoder.markInvalid();
+            return std::nullopt;
+        }
+        
+        Vector<T, inlineCapacity> vector;
+        vector.grow(size);
+        
+        decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(vector.data()), size * sizeof(T), alignof(T));
+        
+        return vector;
+    }
 };
 
 template<typename T, size_t inlineCapacity> struct ArgumentCoder<Vector<T, inlineCapacity>> : VectorArgumentCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { };
@@ -303,6 +379,31 @@ template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTrai
         hashMap.swap(tempHashMap);
         return true;
     }
+
+    static std::optional<HashMapType> decode(Decoder& decoder)
+    {
+        uint64_t hashMapSize;
+        if (!decoder.decode(hashMapSize))
+            return std::nullopt;
+        
+        HashMapType hashMap;
+        for (uint64_t i = 0; i < hashMapSize; ++i) {
+            KeyArg key;
+            MappedArg value;
+            if (!decoder.decode(key))
+                return std::nullopt;
+            if (!decoder.decode(value))
+                return std::nullopt;
+            
+            if (!hashMap.add(key, value).isNewEntry) {
+                // The hash map already has the specified key, bail.
+                decoder.markInvalid();
+                return std::nullopt;
+            }
+        }
+        
+        return WTFMove(hashMap);
+    }
 };
 
 template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct ArgumentCoder<HashSet<KeyArg, HashArg, KeyTraitsArg>> {
@@ -323,11 +424,12 @@ template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct Argume
 
         HashSetType tempHashSet;
         for (uint64_t i = 0; i < hashSetSize; ++i) {
-            KeyArg key;
-            if (!decoder.decode(key))
+            std::optional<KeyArg> key;
+            decoder >> key;
+            if (!key)
                 return false;
 
-            if (!tempHashSet.add(key).isNewEntry) {
+            if (!tempHashSet.add(*key).isNewEntry) {
                 // The hash map already has the specified key, bail.
                 decoder.markInvalid();
                 return false;
@@ -380,9 +482,46 @@ template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct Argume
     }
 };
 
+template<typename ValueType, typename ErrorType> struct ArgumentCoder<Expected<ValueType, ErrorType>> {
+    static void encode(Encoder& encoder, const Expected<ValueType, ErrorType>& expected)
+    {
+        if (!expected.has_value()) {
+            encoder << false;
+            encoder << expected.error();
+            return;
+        }
+        encoder << true;
+        encoder << expected.value();
+    }
+
+    static std::optional<Expected<ValueType, ErrorType>> decode(Decoder& decoder)
+    {
+        std::optional<bool> hasValue;
+        decoder >> hasValue;
+        if (!hasValue)
+            return std::nullopt;
+        
+        if (*hasValue) {
+            std::optional<ValueType> value;
+            decoder >> value;
+            if (!value)
+                return std::nullopt;
+            
+            Expected<ValueType, ErrorType> expected(WTFMove(*value));
+            return WTFMove(expected);
+        }
+        std::optional<ErrorType> error;
+        decoder >> error;
+        if (!error)
+            return std::nullopt;
+        return { makeUnexpected(WTFMove(*error)) };
+    }
+};
+
 template<> struct ArgumentCoder<std::chrono::system_clock::time_point> {
     static void encode(Encoder&, const std::chrono::system_clock::time_point&);
     static bool decode(Decoder&, std::chrono::system_clock::time_point&);
+    static std::optional<std::chrono::system_clock::time_point> decode(Decoder&);
 };
 
 template<> struct ArgumentCoder<AtomicString> {
@@ -398,6 +537,7 @@ template<> struct ArgumentCoder<CString> {
 template<> struct ArgumentCoder<String> {
     static void encode(Encoder&, const String&);
     static bool decode(Decoder&, String&);
+    static std::optional<String> decode(Decoder&);
 };
 
 template<> struct ArgumentCoder<SHA1::Digest> {