Skip to content

Commit

Permalink
[WK2] Further simplify ArgumentCoder decoding for std::tuple<>, std::…
Browse files Browse the repository at this point in the history
…array<>

https://bugs.webkit.org/show_bug.cgi?id=247227

Reviewed by Kimmo Kinnunen.

Have the std::tuple<> decoding in ArgumentCoders.h avoid constructing tuples of
forwarding references by instead passing the rvalue references to the decoded
elements through a parameter pack. Recursion is still used, and the rvalue
references are passed on until the size of the parameter pack matches the size
of the tuple, at which point said tuple is constructed and returned as the result
of the decoding.

Identical approach is adopted for the std::array<> decoder.

The change incorporates a MSCV++ workaround for a compiler bug which breaks
builds due to the constexpr if-statement checking the current index against the
number of the already-decoded elements. Workaround moves the result of this check
into a separate constexpr boolean. Tracking is set up in bug #247226.

* Source/WebKit/Platform/IPC/ArgumentCoders.h:

Canonical link: https://commits.webkit.org/256231@main
  • Loading branch information
zdobersek committed Nov 2, 2022
1 parent 91bc630 commit 22987c3
Showing 1 changed file with 22 additions and 35 deletions.
57 changes: 22 additions & 35 deletions Source/WebKit/Platform/IPC/ArgumentCoders.h
Expand Up @@ -319,26 +319,21 @@ template<typename... Elements> struct ArgumentCoder<std::tuple<Elements...>> {
(encoder << ... << std::get<Indices>(tuple));
}

template<typename Decoder>
static std::optional<std::tuple<Elements...>> decode(Decoder& decoder)
{
return decode(decoder, std::tuple<> { }, std::index_sequence_for<> { });
}

template<typename Decoder, typename OptionalTuple, size_t... Indices>
static std::optional<std::tuple<Elements...>> decode(Decoder& decoder, OptionalTuple&& optionalTuple, std::index_sequence<Indices...>)
template<typename Decoder, typename... DecodedTypes>
static std::optional<std::tuple<Elements...>> decode(Decoder& decoder, std::optional<DecodedTypes>&&... decodedObjects)
{
constexpr size_t Index = sizeof...(Indices);
static_assert(Index == std::tuple_size_v<OptionalTuple>);
constexpr size_t index = sizeof...(DecodedTypes);
static_assert(index <= sizeof...(Elements));
constexpr bool shouldHandleElement = index < sizeof...(Elements); // MSVC++ workaround (https://webkit.org/b/247226)

if constexpr (Index < sizeof...(Elements)) {
auto optional = decoder.template decode<std::tuple_element_t<Index, std::tuple<Elements...>>>();
if constexpr (shouldHandleElement) {
auto optional = decoder.template decode<std::tuple_element_t<index, std::tuple<Elements...>>>();
if (!optional)
return std::nullopt;
return decode(decoder, std::forward_as_tuple(std::get<Indices>(WTFMove(optionalTuple))..., WTFMove(optional)), std::make_index_sequence<Index + 1> { });
return decode(decoder, WTFMove(decodedObjects)..., WTFMove(optional));
} else {
static_assert(Index == sizeof...(Elements));
return std::make_tuple(*std::get<Indices>(WTFMove(optionalTuple))...);
static_assert((std::is_same_v<DecodedTypes, Elements> && ...));
return std::make_tuple(*WTFMove(decodedObjects)...);
}
}
};
Expand Down Expand Up @@ -375,30 +370,22 @@ template<typename T, size_t size> struct ArgumentCoder<std::array<T, size>> {
encoder << item;
}

template<typename Decoder>
static std::optional<std::array<T, size>> decode(Decoder& decoder)
template<typename Decoder, typename... DecodedTypes>
static std::optional<std::array<T, size>> decode(Decoder& decoder, std::optional<DecodedTypes>&&... decodedObjects)
{
std::array<std::optional<T>, size> items;
constexpr size_t index = sizeof...(DecodedTypes);
static_assert(index <= size);
constexpr bool shouldHandleElement = index < size; // MSVC++ workaround (https://webkit.org/b/247226)

for (auto& item : items) {
decoder >> item;
if (!item)
if constexpr (shouldHandleElement) {
auto optional = decoder.template decode<T>();
if (!optional)
return std::nullopt;
return decode(decoder, WTFMove(decodedObjects)..., WTFMove(optional));
} else {
static_assert((std::is_same_v<DecodedTypes, T> && ...));
return std::array<T, size> { *WTFMove(decodedObjects)... };
}

return unwrapArray(WTFMove(items));
}

private:
static std::array<T, size> unwrapArray(std::array<std::optional<T>, size>&& array)
{
return unwrapArrayHelper(WTFMove(array), std::make_index_sequence<size>());
}

template<size_t... index>
static std::array<T, size> unwrapArrayHelper(std::array<std::optional<T>, size>&& array, std::index_sequence<index...>)
{
return { WTFMove(*array[index])... };
}
};

Expand Down

0 comments on commit 22987c3

Please sign in to comment.