From 9b483625e653d2ea89533c99b501a2e296c4d366 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Thu, 22 Dec 2022 20:40:33 -0500 Subject: [PATCH] LibIPC+Everywhere: Change IPC decoders to construct values in-place Currently, the generated IPC decoders will default-construct the type to be decoded, then pass that value by reference to the concrete decoder. This, of course, requires that the type is default-constructible. This was an issue for decoding Variants, which had to require the first type in the Variant list is Empty, to ensure it is default constructible. Further, this made it possible for values to become uninitialized in user-defined decoders. This patch makes the decoder interface such that the concrete decoders themselves contruct the decoded type upon return from the decoder. To do so, the default decoders in IPC::Decoder had to be moved to the IPC namespace scope, as these decoders are now specializations instead of overloaded methods (C++ requires specializations to be in a namespace scope). --- .../Tools/CodeGenerators/IPCCompiler/main.cpp | 3 +- .../HackStudio/AutoCompleteResponse.h | 69 ++--- Userland/Libraries/LibCore/AnonymousBuffer.h | 2 +- Userland/Libraries/LibCore/DateTime.h | 2 +- Userland/Libraries/LibCore/Proxy.h | 2 +- Userland/Libraries/LibDNS/Answer.cpp | 23 +- Userland/Libraries/LibDNS/Answer.h | 2 +- Userland/Libraries/LibGfx/Color.cpp | 8 +- Userland/Libraries/LibGfx/Color.h | 2 +- Userland/Libraries/LibGfx/Point.cpp | 11 +- Userland/Libraries/LibGfx/Point.h | 2 +- Userland/Libraries/LibGfx/Rect.cpp | 11 +- Userland/Libraries/LibGfx/Rect.h | 2 +- Userland/Libraries/LibGfx/ShareableBitmap.cpp | 39 ++- Userland/Libraries/LibGfx/ShareableBitmap.h | 3 +- Userland/Libraries/LibGfx/Size.cpp | 11 +- Userland/Libraries/LibGfx/Size.h | 2 +- Userland/Libraries/LibIPC/Concepts.h | 72 +++++ Userland/Libraries/LibIPC/Decoder.cpp | 222 +++++---------- Userland/Libraries/LibIPC/Decoder.h | 267 +++++++++--------- Userland/Libraries/LibIPC/Forward.h | 2 +- Userland/Libraries/LibSQL/Value.cpp | 68 ++--- Userland/Libraries/LibSQL/Value.h | 2 +- Userland/Libraries/LibWeb/Cookie/Cookie.cpp | 29 +- Userland/Libraries/LibWeb/Cookie/Cookie.h | 2 +- .../Libraries/LibWeb/Cookie/ParsedCookie.cpp | 23 +- .../Libraries/LibWeb/Cookie/ParsedCookie.h | 2 +- .../Libraries/LibWeb/WebDriver/Response.cpp | 28 +- .../Libraries/LibWeb/WebDriver/Response.h | 2 +- Userland/Services/WindowServer/ScreenLayout.h | 4 +- .../Services/WindowServer/ScreenLayout.ipp | 39 ++- 31 files changed, 437 insertions(+), 519 deletions(-) create mode 100644 Userland/Libraries/LibIPC/Concepts.h diff --git a/Meta/Lagom/Tools/CodeGenerators/IPCCompiler/main.cpp b/Meta/Lagom/Tools/CodeGenerators/IPCCompiler/main.cpp index 61b60ea63e..5c6dabe4f7 100644 --- a/Meta/Lagom/Tools/CodeGenerators/IPCCompiler/main.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/IPCCompiler/main.cpp @@ -369,8 +369,7 @@ public:)~~~"); parameter_generator.set("parameter.initial_value", "{}"); parameter_generator.appendln(R"~~~( - @parameter.type@ @parameter.name@ = @parameter.initial_value@; - TRY(decoder.decode(@parameter.name@));)~~~"); + auto @parameter.name@ = TRY((decoder.decode<@parameter.type@>()));)~~~"); if (parameter.attributes.contains_slow("UTF8")) { parameter_generator.appendln(R"~~~( diff --git a/Userland/DevTools/HackStudio/AutoCompleteResponse.h b/Userland/DevTools/HackStudio/AutoCompleteResponse.h index bee9dd9045..fb612b294d 100644 --- a/Userland/DevTools/HackStudio/AutoCompleteResponse.h +++ b/Userland/DevTools/HackStudio/AutoCompleteResponse.h @@ -27,14 +27,15 @@ inline bool encode(Encoder& encoder, CodeComprehension::AutocompleteResultEntry } template<> -inline ErrorOr decode(Decoder& decoder, CodeComprehension::AutocompleteResultEntry& response) +inline ErrorOr decode(Decoder& decoder) { - TRY(decoder.decode(response.completion)); - TRY(decoder.decode(response.partial_input_length)); - TRY(decoder.decode(response.language)); - TRY(decoder.decode(response.display_text)); - TRY(decoder.decode(response.hide_autocomplete_after_applying)); - return {}; + auto completion = TRY(decoder.decode()); + auto partial_input_length = TRY(decoder.decode()); + auto language = TRY(decoder.decode()); + auto display_text = TRY(decoder.decode()); + auto hide_autocomplete_after_applying = TRY(decoder.decode()); + + return CodeComprehension::AutocompleteResultEntry { move(completion), partial_input_length, language, move(display_text), hide_autocomplete_after_applying }; } template<> @@ -47,12 +48,13 @@ inline bool encode(Encoder& encoder, CodeComprehension::ProjectLocation const& l } template<> -inline ErrorOr decode(Decoder& decoder, CodeComprehension::ProjectLocation& location) +inline ErrorOr decode(Decoder& decoder) { - TRY(decoder.decode(location.file)); - TRY(decoder.decode(location.line)); - TRY(decoder.decode(location.column)); - return {}; + auto file = TRY(decoder.decode()); + auto line = TRY(decoder.decode()); + auto column = TRY(decoder.decode()); + + return CodeComprehension::ProjectLocation { move(file), line, column }; } template<> @@ -67,13 +69,14 @@ inline bool encode(Encoder& encoder, CodeComprehension::Declaration const& decla } template<> -inline ErrorOr decode(Decoder& decoder, CodeComprehension::Declaration& declaration) +inline ErrorOr decode(Decoder& decoder) { - TRY(decoder.decode(declaration.name)); - TRY(decoder.decode(declaration.position)); - TRY(decoder.decode(declaration.type)); - TRY(decoder.decode(declaration.scope)); - return {}; + auto name = TRY(decoder.decode()); + auto position = TRY(decoder.decode()); + auto type = TRY(decoder.decode()); + auto scope = TRY(decoder.decode()); + + return CodeComprehension::Declaration { move(name), position, type, move(scope) }; } template<> @@ -87,13 +90,14 @@ inline bool encode(Encoder& encoder, CodeComprehension::TodoEntry const& entry) } template<> -inline ErrorOr decode(Decoder& decoder, CodeComprehension::TodoEntry& entry) +inline ErrorOr decode(Decoder& decoder) { - TRY(decoder.decode(entry.content)); - TRY(decoder.decode(entry.filename)); - TRY(decoder.decode(entry.line)); - TRY(decoder.decode(entry.column)); - return {}; + auto content = TRY(decoder.decode()); + auto filename = TRY(decoder.decode()); + auto line = TRY(decoder.decode()); + auto column = TRY(decoder.decode()); + + return CodeComprehension::TodoEntry { move(content), move(filename), line, column }; } template<> @@ -109,18 +113,15 @@ inline bool encode(Encoder& encoder, CodeComprehension::TokenInfo const& locatio } template<> -inline ErrorOr decode(Decoder& decoder, CodeComprehension::TokenInfo& entry) +inline ErrorOr decode(Decoder& decoder) { - u32 semantic_type { 0 }; - static_assert(sizeof(semantic_type) == sizeof(entry.type)); + auto type = TRY(decoder.decode()); + auto start_line = TRY(decoder.decode()); + auto start_column = TRY(decoder.decode()); + auto end_line = TRY(decoder.decode()); + auto end_column = TRY(decoder.decode()); - TRY(decoder.decode(semantic_type)); - entry.type = static_cast(semantic_type); - TRY(decoder.decode(entry.start_line)); - TRY(decoder.decode(entry.start_column)); - TRY(decoder.decode(entry.end_line)); - TRY(decoder.decode(entry.end_column)); - return {}; + return CodeComprehension::TokenInfo { type, start_line, start_column, end_line, end_column }; } } diff --git a/Userland/Libraries/LibCore/AnonymousBuffer.h b/Userland/Libraries/LibCore/AnonymousBuffer.h index 4855b74078..e4784281f2 100644 --- a/Userland/Libraries/LibCore/AnonymousBuffer.h +++ b/Userland/Libraries/LibCore/AnonymousBuffer.h @@ -78,6 +78,6 @@ template<> bool encode(Encoder&, Core::AnonymousBuffer const&); template<> -ErrorOr decode(Decoder&, Core::AnonymousBuffer&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibCore/DateTime.h b/Userland/Libraries/LibCore/DateTime.h index fe050a2df3..e605d1f1d9 100644 --- a/Userland/Libraries/LibCore/DateTime.h +++ b/Userland/Libraries/LibCore/DateTime.h @@ -58,6 +58,6 @@ template<> bool encode(Encoder&, Core::DateTime const&); template<> -ErrorOr decode(Decoder&, Core::DateTime&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibCore/Proxy.h b/Userland/Libraries/LibCore/Proxy.h index 66e1d432b0..780114c3fb 100644 --- a/Userland/Libraries/LibCore/Proxy.h +++ b/Userland/Libraries/LibCore/Proxy.h @@ -57,6 +57,6 @@ template<> bool encode(Encoder&, Core::ProxyData const&); template<> -ErrorOr decode(Decoder&, Core::ProxyData&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibDNS/Answer.cpp b/Userland/Libraries/LibDNS/Answer.cpp index 35fa89b3aa..c8112755de 100644 --- a/Userland/Libraries/LibDNS/Answer.cpp +++ b/Userland/Libraries/LibDNS/Answer.cpp @@ -108,21 +108,16 @@ bool encode(Encoder& encoder, DNS::Answer const& answer) } template<> -ErrorOr decode(Decoder& decoder, DNS::Answer& answer) +ErrorOr decode(Decoder& decoder) { - DeprecatedString name; - TRY(decoder.decode(name)); - u16 record_type, class_code; - TRY(decoder.decode(record_type)); - TRY(decoder.decode(class_code)); - u32 ttl; - TRY(decoder.decode(ttl)); - DeprecatedString record_data; - TRY(decoder.decode(record_data)); - bool cache_flush; - TRY(decoder.decode(cache_flush)); - answer = { { name }, (DNS::RecordType)record_type, (DNS::RecordClass)class_code, ttl, record_data, cache_flush }; - return {}; + auto name = TRY(decoder.decode()); + auto record_type = TRY(decoder.decode()); + auto class_code = TRY(decoder.decode()); + auto ttl = TRY(decoder.decode()); + auto record_data = TRY(decoder.decode()); + auto cache_flush = TRY(decoder.decode()); + + return DNS::Answer { name, record_type, class_code, ttl, record_data, cache_flush }; } } diff --git a/Userland/Libraries/LibDNS/Answer.h b/Userland/Libraries/LibDNS/Answer.h index a064013d00..d666562fb0 100644 --- a/Userland/Libraries/LibDNS/Answer.h +++ b/Userland/Libraries/LibDNS/Answer.h @@ -98,6 +98,6 @@ template<> bool encode(Encoder&, DNS::Answer const&); template<> -ErrorOr decode(Decoder&, DNS::Answer&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibGfx/Color.cpp b/Userland/Libraries/LibGfx/Color.cpp index 2438ae3c7f..b8e8da487b 100644 --- a/Userland/Libraries/LibGfx/Color.cpp +++ b/Userland/Libraries/LibGfx/Color.cpp @@ -374,12 +374,10 @@ bool IPC::encode(Encoder& encoder, Color const& color) } template<> -ErrorOr IPC::decode(Decoder& decoder, Color& color) +ErrorOr IPC::decode(Decoder& decoder) { - u32 rgba; - TRY(decoder.decode(rgba)); - color = Color::from_argb(rgba); - return {}; + auto rgba = TRY(decoder.decode()); + return Gfx::Color::from_argb(rgba); } ErrorOr AK::Formatter::format(FormatBuilder& builder, Gfx::Color value) diff --git a/Userland/Libraries/LibGfx/Color.h b/Userland/Libraries/LibGfx/Color.h index 9458d97036..9fe5b7e5ab 100644 --- a/Userland/Libraries/LibGfx/Color.h +++ b/Userland/Libraries/LibGfx/Color.h @@ -577,6 +577,6 @@ template<> bool encode(Encoder&, Gfx::Color const&); template<> -ErrorOr decode(Decoder&, Gfx::Color&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibGfx/Point.cpp b/Userland/Libraries/LibGfx/Point.cpp index f5a99bf82e..8dd484ca19 100644 --- a/Userland/Libraries/LibGfx/Point.cpp +++ b/Userland/Libraries/LibGfx/Point.cpp @@ -59,14 +59,11 @@ bool encode(Encoder& encoder, Gfx::IntPoint const& point) } template<> -ErrorOr decode(Decoder& decoder, Gfx::IntPoint& point) +ErrorOr decode(Decoder& decoder) { - int x = 0; - int y = 0; - TRY(decoder.decode(x)); - TRY(decoder.decode(y)); - point = { x, y }; - return {}; + auto x = TRY(decoder.decode()); + auto y = TRY(decoder.decode()); + return Gfx::IntPoint { x, y }; } } diff --git a/Userland/Libraries/LibGfx/Point.h b/Userland/Libraries/LibGfx/Point.h index 452bc605dc..ea601edc5e 100644 --- a/Userland/Libraries/LibGfx/Point.h +++ b/Userland/Libraries/LibGfx/Point.h @@ -295,7 +295,7 @@ template<> bool encode(Encoder&, Gfx::IntPoint const&); template<> -ErrorOr decode(Decoder&, Gfx::IntPoint&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibGfx/Rect.cpp b/Userland/Libraries/LibGfx/Rect.cpp index 6c85b50fac..68bbfd4ead 100644 --- a/Userland/Libraries/LibGfx/Rect.cpp +++ b/Userland/Libraries/LibGfx/Rect.cpp @@ -38,14 +38,11 @@ bool encode(Encoder& encoder, Gfx::IntRect const& rect) } template<> -ErrorOr decode(Decoder& decoder, Gfx::IntRect& rect) +ErrorOr decode(Decoder& decoder) { - Gfx::IntPoint point; - Gfx::IntSize size; - TRY(decoder.decode(point)); - TRY(decoder.decode(size)); - rect = { point, size }; - return {}; + auto point = TRY(decoder.decode()); + auto size = TRY(decoder.decode()); + return Gfx::IntRect { point, size }; } } diff --git a/Userland/Libraries/LibGfx/Rect.h b/Userland/Libraries/LibGfx/Rect.h index a848b73edc..440f4bb885 100644 --- a/Userland/Libraries/LibGfx/Rect.h +++ b/Userland/Libraries/LibGfx/Rect.h @@ -1036,6 +1036,6 @@ template<> bool encode(Encoder&, Gfx::IntRect const&); template<> -ErrorOr decode(Decoder&, Gfx::IntRect&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibGfx/ShareableBitmap.cpp b/Userland/Libraries/LibGfx/ShareableBitmap.cpp index 97bc55fd94..a741c3d7e5 100644 --- a/Userland/Libraries/LibGfx/ShareableBitmap.cpp +++ b/Userland/Libraries/LibGfx/ShareableBitmap.cpp @@ -32,7 +32,7 @@ bool encode(Encoder& encoder, Gfx::ShareableBitmap const& shareable_bitmap) encoder << IPC::File(bitmap.anonymous_buffer().fd()); encoder << bitmap.size(); encoder << static_cast(bitmap.scale()); - encoder << (u32)bitmap.format(); + encoder << static_cast(bitmap.format()); if (bitmap.is_indexed()) { auto palette = bitmap.palette_to_vector(); encoder << palette; @@ -41,33 +41,28 @@ bool encode(Encoder& encoder, Gfx::ShareableBitmap const& shareable_bitmap) } template<> -ErrorOr decode(Decoder& decoder, Gfx::ShareableBitmap& shareable_bitmap) +ErrorOr decode(Decoder& decoder) { - bool valid = false; - TRY(decoder.decode(valid)); - if (!valid) { - shareable_bitmap = {}; - return {}; - } - IPC::File anon_file; - TRY(decoder.decode(anon_file)); - Gfx::IntSize size; - TRY(decoder.decode(size)); - u32 scale; - TRY(decoder.decode(scale)); - u32 raw_bitmap_format; - TRY(decoder.decode(raw_bitmap_format)); + if (auto valid = TRY(decoder.decode()); !valid) + return Gfx::ShareableBitmap {}; + + auto anon_file = TRY(decoder.decode()); + auto size = TRY(decoder.decode()); + auto scale = TRY(decoder.decode()); + auto raw_bitmap_format = TRY(decoder.decode()); if (!Gfx::is_valid_bitmap_format(raw_bitmap_format)) return Error::from_string_literal("IPC: Invalid Gfx::ShareableBitmap format"); - auto bitmap_format = (Gfx::BitmapFormat)raw_bitmap_format; + + auto bitmap_format = static_cast(raw_bitmap_format); + Vector palette; - if (Gfx::Bitmap::is_indexed(bitmap_format)) { - TRY(decoder.decode(palette)); - } + if (Gfx::Bitmap::is_indexed(bitmap_format)) + palette = TRY(decoder.decode()); + auto buffer = TRY(Core::AnonymousBuffer::create_from_anon_fd(anon_file.take_fd(), Gfx::Bitmap::size_in_bytes(Gfx::Bitmap::minimum_pitch(size.width() * scale, bitmap_format), size.height() * scale))); auto bitmap = TRY(Gfx::Bitmap::try_create_with_anonymous_buffer(bitmap_format, move(buffer), size, scale, palette)); - shareable_bitmap = Gfx::ShareableBitmap { move(bitmap), Gfx::ShareableBitmap::ConstructWithKnownGoodBitmap }; - return {}; + + return Gfx::ShareableBitmap { move(bitmap), Gfx::ShareableBitmap::ConstructWithKnownGoodBitmap }; } } diff --git a/Userland/Libraries/LibGfx/ShareableBitmap.h b/Userland/Libraries/LibGfx/ShareableBitmap.h index 26c074a297..16e8df9c13 100644 --- a/Userland/Libraries/LibGfx/ShareableBitmap.h +++ b/Userland/Libraries/LibGfx/ShareableBitmap.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace Gfx { @@ -38,6 +39,6 @@ template<> bool encode(Encoder&, Gfx::ShareableBitmap const&); template<> -ErrorOr decode(Decoder&, Gfx::ShareableBitmap&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibGfx/Size.cpp b/Userland/Libraries/LibGfx/Size.cpp index 718312d052..b737e7af15 100644 --- a/Userland/Libraries/LibGfx/Size.cpp +++ b/Userland/Libraries/LibGfx/Size.cpp @@ -35,14 +35,11 @@ bool encode(Encoder& encoder, Gfx::IntSize const& size) } template<> -ErrorOr decode(Decoder& decoder, Gfx::IntSize& size) +ErrorOr decode(Decoder& decoder) { - int width = 0; - int height = 0; - TRY(decoder.decode(width)); - TRY(decoder.decode(height)); - size = { width, height }; - return {}; + auto width = TRY(decoder.decode()); + auto height = TRY(decoder.decode()); + return Gfx::IntSize { width, height }; } } diff --git a/Userland/Libraries/LibGfx/Size.h b/Userland/Libraries/LibGfx/Size.h index ec461de9c2..ff71e7d16a 100644 --- a/Userland/Libraries/LibGfx/Size.h +++ b/Userland/Libraries/LibGfx/Size.h @@ -218,6 +218,6 @@ template<> bool encode(Encoder&, Gfx::IntSize const&); template<> -ErrorOr decode(Decoder&, Gfx::IntSize&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibIPC/Concepts.h b/Userland/Libraries/LibIPC/Concepts.h new file mode 100644 index 0000000000..99746e00c8 --- /dev/null +++ b/Userland/Libraries/LibIPC/Concepts.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +#pragma once + +// These concepts are used to help the compiler distinguish between specializations that would be +// ambiguous otherwise. For example, if the specializations for int and Vector were declared as +// follows: +// +// template<> ErrorOr decode(Decoder& decoder); +// template ErrorOr> decode(Decoder& decoder); +// +// Then decode() would be ambiguous because either declaration could work (the compiler would +// not be able to distinguish if you wanted to decode an int or a Vector of int). +namespace IPC::Concepts { + +namespace Detail { + +template +constexpr inline bool IsHashMap = false; +template +constexpr inline bool IsHashMap> = true; +template +constexpr inline bool IsHashMap> = true; + +template +constexpr inline bool IsOptional = false; +template +constexpr inline bool IsOptional> = true; + +template +constexpr inline bool IsSharedSingleProducerCircularQueue = false; +template +constexpr inline bool IsSharedSingleProducerCircularQueue> = true; + +template +constexpr inline bool IsVariant = false; +template +constexpr inline bool IsVariant> = true; + +template +constexpr inline bool IsVector = false; +template +constexpr inline bool IsVector> = true; + +} + +template +concept HashMap = Detail::IsHashMap; + +template +concept Optional = Detail::IsOptional; + +template +concept SharedSingleProducerCircularQueue = Detail::IsSharedSingleProducerCircularQueue; + +template +concept Variant = Detail::IsVariant; + +template +concept Vector = Detail::IsVector; + +} diff --git a/Userland/Libraries/LibIPC/Decoder.cpp b/Userland/Libraries/LibIPC/Decoder.cpp index 04ef566e99..50decffea4 100644 --- a/Userland/Libraries/LibIPC/Decoder.cpp +++ b/Userland/Libraries/LibIPC/Decoder.cpp @@ -5,7 +5,6 @@ */ #include -#include #include #include #include @@ -17,201 +16,110 @@ namespace IPC { -ErrorOr Decoder::decode(bool& value) +template<> +ErrorOr decode(Decoder& decoder) { - m_stream >> value; - return m_stream.try_handle_any_error(); -} + auto length = TRY(decoder.decode()); + if (length < 0) + return DeprecatedString {}; + if (length == 0) + return DeprecatedString::empty(); -ErrorOr Decoder::decode(u8& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(u16& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(unsigned& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(unsigned long& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(unsigned long long& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(i8& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(i16& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(i32& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(i64& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(float& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(double& value) -{ - m_stream >> value; - return m_stream.try_handle_any_error(); -} - -ErrorOr Decoder::decode(DeprecatedString& value) -{ - i32 length; - TRY(decode(length)); - - if (length < 0) { - value = {}; - return {}; - } - if (length == 0) { - value = DeprecatedString::empty(); - return {}; - } char* text_buffer = nullptr; auto text_impl = StringImpl::create_uninitialized(static_cast(length), text_buffer); - m_stream >> Bytes { text_buffer, static_cast(length) }; - value = *text_impl; - return m_stream.try_handle_any_error(); + + Bytes bytes { text_buffer, static_cast(length) }; + TRY(decoder.decode_into(bytes)); + + return DeprecatedString { *text_impl }; } -ErrorOr Decoder::decode(ByteBuffer& value) +template<> +ErrorOr decode(Decoder& decoder) { - i32 length; - TRY(decode(length)); + auto length = TRY(decoder.decode()); + if (length <= 0) + return ByteBuffer {}; - if (length < 0) { - value = {}; - return {}; - } - if (length == 0) { - value = {}; - return {}; - } + auto buffer = TRY(ByteBuffer::create_uninitialized(length)); + auto bytes = buffer.bytes(); - value = TRY(ByteBuffer::create_uninitialized(length)); - - m_stream >> value.bytes(); - return m_stream.try_handle_any_error(); + TRY(decoder.decode_into(bytes)); + return buffer; } -ErrorOr Decoder::decode(JsonValue& value) +template<> +ErrorOr decode(Decoder& decoder) { - DeprecatedString string; - TRY(decode(string)); - value = TRY(JsonValue::from_string(string)); - return {}; + auto json = TRY(decoder.decode()); + return JsonValue::from_string(json); } -ErrorOr Decoder::decode(URL& value) +template<> +ErrorOr decode(Decoder& decoder) { - DeprecatedString string; - TRY(decode(string)); - value = URL(string); - return {}; + auto url = TRY(decoder.decode()); + return URL { url }; } -ErrorOr Decoder::decode(Dictionary& dictionary) +template<> +ErrorOr decode(Decoder& decoder) { - u64 size; - TRY(decode(size)); - if (size >= (size_t)NumericLimits::max()) + auto size = TRY(decoder.decode()); + if (size >= NumericLimits::max()) VERIFY_NOT_REACHED(); + Dictionary dictionary {}; + for (size_t i = 0; i < size; ++i) { - DeprecatedString key; - TRY(decode(key)); - DeprecatedString value; - TRY(decode(value)); + auto key = TRY(decoder.decode()); + auto value = TRY(decoder.decode()); dictionary.add(move(key), move(value)); } - return {}; -} - -ErrorOr Decoder::decode([[maybe_unused]] File& file) -{ - int fd = TRY(m_socket.receive_fd(O_CLOEXEC)); - file = File(fd, File::ConstructWithReceivedFileDescriptor); - return {}; + return dictionary; } template<> -ErrorOr decode(Decoder& decoder, Core::AnonymousBuffer& buffer) +ErrorOr decode(Decoder& decoder) { - bool valid; - TRY(decoder.decode(valid)); - if (!valid) { - buffer = {}; - return {}; - } - u32 size; - TRY(decoder.decode(size)); - IPC::File anon_file; - TRY(decoder.decode(anon_file)); - - buffer = TRY(Core::AnonymousBuffer::create_from_anon_fd(anon_file.take_fd(), size)); - return {}; + int fd = TRY(decoder.socket().receive_fd(O_CLOEXEC)); + return File { fd, File::ConstructWithReceivedFileDescriptor }; } template<> -ErrorOr decode(Decoder& decoder, Core::DateTime& datetime) +ErrorOr decode(Decoder&) { - i64 timestamp; - TRY(decoder.decode(timestamp)); - datetime = Core::DateTime::from_timestamp(static_cast(timestamp)); - return {}; + return Empty {}; } template<> -ErrorOr decode(Decoder& decoder, Core::ProxyData& data) +ErrorOr decode(Decoder& decoder) { - UnderlyingType type; - TRY(decoder.decode(type)); - data.type = static_cast(type); - TRY(decoder.decode(data.host_ipv4)); - TRY(decoder.decode(data.port)); - return {}; + if (auto valid = TRY(decoder.decode()); !valid) + return Core::AnonymousBuffer {}; + + auto size = TRY(decoder.decode()); + auto anon_file = TRY(decoder.decode()); + + return Core::AnonymousBuffer::create_from_anon_fd(anon_file.take_fd(), size); } -// No-op. -ErrorOr Decoder::decode(AK::Empty&) +template<> +ErrorOr decode(Decoder& decoder) { - return {}; + auto timestamp = TRY(decoder.decode()); + return Core::DateTime::from_timestamp(static_cast(timestamp)); +} + +template<> +ErrorOr decode(Decoder& decoder) +{ + auto type = TRY(decoder.decode()); + auto host_ipv4 = TRY(decoder.decode()); + auto port = TRY(decoder.decode()); + + return Core::ProxyData { type, host_ipv4, port }; } } diff --git a/Userland/Libraries/LibIPC/Decoder.h b/Userland/Libraries/LibIPC/Decoder.h index 1cc3902a58..ad636f1b8c 100644 --- a/Userland/Libraries/LibIPC/Decoder.h +++ b/Userland/Libraries/LibIPC/Decoder.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -23,7 +25,7 @@ namespace IPC { template -inline ErrorOr decode(Decoder&, T&) +inline ErrorOr decode(Decoder&) { static_assert(DependentFalse, "Base IPC::decoder() instantiated"); VERIFY_NOT_REACHED(); @@ -37,151 +39,144 @@ public: { } - ErrorOr decode(bool&); - ErrorOr decode(u8&); - ErrorOr decode(u16&); - ErrorOr decode(unsigned&); - ErrorOr decode(unsigned long&); - ErrorOr decode(unsigned long long&); - ErrorOr decode(i8&); - ErrorOr decode(i16&); - ErrorOr decode(i32&); - ErrorOr decode(i64&); - ErrorOr decode(float&); - ErrorOr decode(double&); - ErrorOr decode(DeprecatedString&); - ErrorOr decode(ByteBuffer&); - ErrorOr decode(JsonValue&); - ErrorOr decode(URL&); - ErrorOr decode(Dictionary&); - ErrorOr decode(File&); - ErrorOr decode(AK::Empty&); - template - ErrorOr decode(HashMap& hashmap) - { - u32 size; - TRY(decode(size)); - if (size > NumericLimits::max()) - return Error::from_string_literal("IPC: Invalid HashMap size"); - - for (size_t i = 0; i < size; ++i) { - K key; - TRY(decode(key)); - V value; - TRY(decode(value)); - TRY(hashmap.try_set(move(key), move(value))); - } - return {}; - } - - template - ErrorOr decode(OrderedHashMap& hashmap) - { - u32 size; - TRY(decode(size)); - if (size > NumericLimits::max()) - return Error::from_string_literal("IPC: Invalid HashMap size"); - - for (size_t i = 0; i < size; ++i) { - K key; - TRY(decode(key)); - V value; - TRY(decode(value)); - TRY(hashmap.try_set(move(key), move(value))); - } - return {}; - } - - template - ErrorOr decode(T& enum_value) - { - UnderlyingType inner_value; - TRY(decode(inner_value)); - enum_value = T(inner_value); - return {}; - } + template + ErrorOr decode(); template - ErrorOr decode(T& value) + ErrorOr decode_into(T& value) { - return IPC::decode(*this, value); - } - - template - ErrorOr decode(Vector& vector) - { - u64 size; - TRY(decode(size)); - if (size > NumericLimits::max()) - return Error::from_string_literal("IPC: Invalid Vector size"); - VERIFY(vector.is_empty()); - TRY(vector.try_ensure_capacity(size)); - for (size_t i = 0; i < size; ++i) { - T value; - TRY(decode(value)); - vector.template unchecked_append(move(value)); - } + m_stream >> value; + TRY(m_stream.try_handle_any_error()); return {}; } - template - ErrorOr decode(Core::SharedSingleProducerCircularQueue& queue) - { - // FIXME: We don't support decoding into valid queues. - VERIFY(!queue.is_valid()); - - IPC::File anon_file; - TRY(decode(anon_file)); - queue = TRY((Core::SharedSingleProducerCircularQueue::try_create(anon_file.take_fd()))); - return {}; - } - - template - ErrorOr decode(Variant& variant) - { - typename AK::Variant::IndexType type_index; - TRY(decode(type_index)); - if (type_index >= sizeof...(VariantTypes)) - return Error::from_string_literal("IPC: Invalid variant index"); - - TRY((decode_variant<0, sizeof...(VariantTypes), VariantTypes...>(type_index, variant))); - return {}; - } - - template - ErrorOr decode(Optional& optional) - { - bool has_value; - TRY(decode(has_value)); - if (!has_value) { - optional = {}; - return {}; - } - T value; - TRY(decode(value)); - optional = move(value); - return {}; - } + Core::Stream::LocalSocket& socket() { return m_socket; } private: - template - ErrorOr decode_variant(size_t index, Variant& variant) - { - if constexpr (CurrentIndex < Max) { - if (index == CurrentIndex) { - typename TypeList::template Type element; - TRY(decode(element)); - variant.set(move(element)); - return {}; - } - return decode_variant(index, variant); - } else { - VERIFY_NOT_REACHED(); - } - } - InputMemoryStream& m_stream; Core::Stream::LocalSocket& m_socket; }; +template +ErrorOr decode(Decoder& decoder) +{ + T value { 0 }; + TRY(decoder.decode_into(value)); + return value; +} + +template +ErrorOr decode(Decoder& decoder) +{ + auto value = TRY(decoder.decode>()); + return static_cast(value); +} + +template<> +ErrorOr decode(Decoder&); + +template<> +ErrorOr decode(Decoder&); + +template<> +ErrorOr decode(Decoder&); + +template<> +ErrorOr decode(Decoder&); + +template<> +ErrorOr decode(Decoder&); + +template<> +ErrorOr decode(Decoder&); + +template<> +ErrorOr decode(Decoder&); + +template +ErrorOr decode(Decoder& decoder) +{ + auto size = TRY(decoder.decode()); + if (size > NumericLimits::max()) + return Error::from_string_literal("IPC: Invalid Vector size"); + + T vector; + TRY(vector.try_ensure_capacity(size)); + + for (size_t i = 0; i < size; ++i) { + auto value = TRY(decoder.decode()); + vector.template unchecked_append(move(value)); + } + + return vector; +} + +template +ErrorOr decode(Decoder& decoder) +{ + auto size = TRY(decoder.decode()); + if (size > NumericLimits::max()) + return Error::from_string_literal("IPC: Invalid HashMap size"); + + T hashmap; + + for (size_t i = 0; i < size; ++i) { + auto key = TRY(decoder.decode()); + auto value = TRY(decoder.decode()); + TRY(hashmap.try_set(move(key), move(value))); + } + + return hashmap; +} + +template +ErrorOr decode(Decoder& decoder) +{ + auto anon_file = TRY(decoder.decode()); + return T::try_create(anon_file.take_fd()); +} + +template +ErrorOr decode(Decoder& decoder) +{ + if (auto has_value = TRY(decoder.decode()); !has_value) + return T {}; + return T { TRY(decoder.decode()) }; +} + +namespace Detail { + +template +ErrorOr decode_variant(Decoder& decoder, size_t index) +{ + using ElementList = TypeList; + + if constexpr (Index < ElementList::size) { + if (index == Index) { + using ElementType = typename ElementList::template Type; + return T { TRY(decoder.decode()) }; + } + + return decode_variant(decoder, index); + } else { + VERIFY_NOT_REACHED(); + } +} + +} + +template +ErrorOr decode(Decoder& decoder) +{ + auto index = TRY(decoder.decode()); + return Detail::decode_variant(decoder, index); +} + +// This must be last so that it knows about the above specializations. +template +ErrorOr Decoder::decode() +{ + return IPC::decode(*this); +} + } diff --git a/Userland/Libraries/LibIPC/Forward.h b/Userland/Libraries/LibIPC/Forward.h index c59cca64d3..c16e57a271 100644 --- a/Userland/Libraries/LibIPC/Forward.h +++ b/Userland/Libraries/LibIPC/Forward.h @@ -19,6 +19,6 @@ template bool encode(Encoder&, T const&); template -ErrorOr decode(Decoder&, T&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibSQL/Value.cpp b/Userland/Libraries/LibSQL/Value.cpp index 884d465cbe..ee85e3e9a4 100644 --- a/Userland/Libraries/LibSQL/Value.cpp +++ b/Userland/Libraries/LibSQL/Value.cpp @@ -847,82 +847,58 @@ bool IPC::encode(Encoder& encoder, SQL::Value const& value) return true; } -template -static ErrorOr decode_scalar(IPC::Decoder& decoder, SQL::Value& value) -{ - T decoded {}; - TRY(decoder.decode(decoded)); - value = move(decoded); - return {}; -} - template<> -ErrorOr IPC::decode(Decoder& decoder, SQL::Value& value) +ErrorOr IPC::decode(Decoder& decoder) { - u8 type_flags { 0 }; - TRY(decoder.decode(type_flags)); + auto type_flags = TRY(decoder.decode()); auto type_data = static_cast(type_flags & 0xf0); auto type = static_cast(type_flags & 0x0f); - if (type_data == SQL::TypeData::Null) { - value = SQL::Value(type); - return {}; - } + if (type_data == SQL::TypeData::Null) + return SQL::Value { type }; switch (type) { case SQL::SQLType::Null: - break; + return SQL::Value {}; case SQL::SQLType::Text: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::SQLType::Integer: switch (type_data) { case SQL::TypeData::Int8: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::TypeData::Int16: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::TypeData::Int32: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::TypeData::Int64: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::TypeData::Uint8: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::TypeData::Uint16: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::TypeData::Uint32: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::TypeData::Uint64: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; default: - VERIFY_NOT_REACHED(); break; } break; case SQL::SQLType::Float: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::SQLType::Boolean: - TRY(decode_scalar(decoder, value)); - break; + return SQL::Value { TRY(decoder.decode()) }; case SQL::SQLType::Tuple: { - Vector tuple; - TRY(decoder.decode(tuple)); + auto tuple = TRY(decoder.decode>()); + auto value = SQL::Value::create_tuple(move(tuple)); - if (auto result = value.assign_tuple(move(tuple)); result.is_error()) - return Error::from_errno(to_underlying(result.error().error())); + if (value.is_error()) + return Error::from_errno(to_underlying(value.error().error())); - break; + return value.release_value(); } } - return {}; + VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibSQL/Value.h b/Userland/Libraries/LibSQL/Value.h index e7568192b6..475e963dc0 100644 --- a/Userland/Libraries/LibSQL/Value.h +++ b/Userland/Libraries/LibSQL/Value.h @@ -194,6 +194,6 @@ template<> bool encode(Encoder&, SQL::Value const&); template<> -ErrorOr decode(Decoder&, SQL::Value&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibWeb/Cookie/Cookie.cpp b/Userland/Libraries/LibWeb/Cookie/Cookie.cpp index 2a43385e64..6ddaa79c05 100644 --- a/Userland/Libraries/LibWeb/Cookie/Cookie.cpp +++ b/Userland/Libraries/LibWeb/Cookie/Cookie.cpp @@ -58,19 +58,20 @@ bool IPC::encode(Encoder& encoder, Web::Cookie::Cookie const& cookie) } template<> -ErrorOr IPC::decode(Decoder& decoder, Web::Cookie::Cookie& cookie) +ErrorOr IPC::decode(Decoder& decoder) { - TRY(decoder.decode(cookie.name)); - TRY(decoder.decode(cookie.value)); - TRY(decoder.decode(cookie.domain)); - TRY(decoder.decode(cookie.path)); - TRY(decoder.decode(cookie.creation_time)); - TRY(decoder.decode(cookie.expiry_time)); - TRY(decoder.decode(cookie.host_only)); - TRY(decoder.decode(cookie.http_only)); - TRY(decoder.decode(cookie.last_access_time)); - TRY(decoder.decode(cookie.persistent)); - TRY(decoder.decode(cookie.secure)); - TRY(decoder.decode(cookie.same_site)); - return {}; + auto name = TRY(decoder.decode()); + auto value = TRY(decoder.decode()); + auto domain = TRY(decoder.decode()); + auto path = TRY(decoder.decode()); + auto creation_time = TRY(decoder.decode()); + auto expiry_time = TRY(decoder.decode()); + auto host_only = TRY(decoder.decode()); + auto http_only = TRY(decoder.decode()); + auto last_access_time = TRY(decoder.decode()); + auto persistent = TRY(decoder.decode()); + auto secure = TRY(decoder.decode()); + auto same_site = TRY(decoder.decode()); + + return Web::Cookie::Cookie { move(name), move(value), same_site, move(creation_time), move(last_access_time), move(expiry_time), move(domain), move(path), secure, http_only, host_only, persistent }; } diff --git a/Userland/Libraries/LibWeb/Cookie/Cookie.h b/Userland/Libraries/LibWeb/Cookie/Cookie.h index e16352305e..429a90f6d0 100644 --- a/Userland/Libraries/LibWeb/Cookie/Cookie.h +++ b/Userland/Libraries/LibWeb/Cookie/Cookie.h @@ -50,6 +50,6 @@ template<> bool encode(Encoder&, Web::Cookie::Cookie const&); template<> -ErrorOr decode(Decoder&, Web::Cookie::Cookie&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp b/Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp index 774240ca73..69ceeb4050 100644 --- a/Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp +++ b/Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp @@ -364,16 +364,17 @@ bool IPC::encode(Encoder& encoder, Web::Cookie::ParsedCookie const& cookie) } template<> -ErrorOr IPC::decode(Decoder& decoder, Web::Cookie::ParsedCookie& cookie) +ErrorOr IPC::decode(Decoder& decoder) { - TRY(decoder.decode(cookie.name)); - TRY(decoder.decode(cookie.value)); - TRY(decoder.decode(cookie.expiry_time_from_expires_attribute)); - TRY(decoder.decode(cookie.expiry_time_from_max_age_attribute)); - TRY(decoder.decode(cookie.domain)); - TRY(decoder.decode(cookie.path)); - TRY(decoder.decode(cookie.secure_attribute_present)); - TRY(decoder.decode(cookie.http_only_attribute_present)); - TRY(decoder.decode(cookie.same_site_attribute)); - return {}; + auto name = TRY(decoder.decode()); + auto value = TRY(decoder.decode()); + auto expiry_time_from_expires_attribute = TRY(decoder.decode>()); + auto expiry_time_from_max_age_attribute = TRY(decoder.decode>()); + auto domain = TRY(decoder.decode>()); + auto path = TRY(decoder.decode>()); + auto secure_attribute_present = TRY(decoder.decode()); + auto http_only_attribute_present = TRY(decoder.decode()); + auto same_site_attribute = TRY(decoder.decode()); + + return Web::Cookie::ParsedCookie { move(name), move(value), same_site_attribute, move(expiry_time_from_expires_attribute), move(expiry_time_from_max_age_attribute), move(domain), move(path), secure_attribute_present, http_only_attribute_present }; } diff --git a/Userland/Libraries/LibWeb/Cookie/ParsedCookie.h b/Userland/Libraries/LibWeb/Cookie/ParsedCookie.h index ebe38b46ab..31b6b5b15f 100644 --- a/Userland/Libraries/LibWeb/Cookie/ParsedCookie.h +++ b/Userland/Libraries/LibWeb/Cookie/ParsedCookie.h @@ -36,6 +36,6 @@ template<> bool encode(Encoder&, Web::Cookie::ParsedCookie const&); template<> -ErrorOr decode(Decoder&, Web::Cookie::ParsedCookie&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Libraries/LibWeb/WebDriver/Response.cpp b/Userland/Libraries/LibWeb/WebDriver/Response.cpp index a44e17f578..c2ed16cdb4 100644 --- a/Userland/Libraries/LibWeb/WebDriver/Response.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/Response.cpp @@ -48,31 +48,23 @@ bool IPC::encode(Encoder& encoder, Web::WebDriver::Response const& response) } template<> -ErrorOr IPC::decode(Decoder& decoder, Web::WebDriver::Response& response) +ErrorOr IPC::decode(Decoder& decoder) { - ResponseType type {}; - TRY(decoder.decode(type)); + auto type = TRY(decoder.decode()); switch (type) { - case ResponseType::Success: { - JsonValue value; - TRY(decoder.decode(value)); - - response = move(value); - break; - } + case ResponseType::Success: + return TRY(decoder.decode()); case ResponseType::Error: { - Web::WebDriver::Error error {}; - TRY(decoder.decode(error.http_status)); - TRY(decoder.decode(error.error)); - TRY(decoder.decode(error.message)); - TRY(decoder.decode(error.data)); + auto http_status = TRY(decoder.decode()); + auto error = TRY(decoder.decode()); + auto message = TRY(decoder.decode()); + auto data = TRY(decoder.decode>()); - response = move(error); - break; + return Web::WebDriver::Error { http_status, move(error), move(message), move(data) }; } } - return {}; + VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibWeb/WebDriver/Response.h b/Userland/Libraries/LibWeb/WebDriver/Response.h index 1a6663746e..dc8b570441 100644 --- a/Userland/Libraries/LibWeb/WebDriver/Response.h +++ b/Userland/Libraries/LibWeb/WebDriver/Response.h @@ -50,6 +50,6 @@ template<> bool encode(Encoder&, Web::WebDriver::Response const&); template<> -ErrorOr decode(Decoder&, Web::WebDriver::Response&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Services/WindowServer/ScreenLayout.h b/Userland/Services/WindowServer/ScreenLayout.h index ceb70c88de..6a5c5b0571 100644 --- a/Userland/Services/WindowServer/ScreenLayout.h +++ b/Userland/Services/WindowServer/ScreenLayout.h @@ -77,12 +77,12 @@ template<> bool encode(Encoder&, WindowServer::ScreenLayout::Screen const&); template<> -ErrorOr decode(Decoder&, WindowServer::ScreenLayout::Screen&); +ErrorOr decode(Decoder&); template<> bool encode(Encoder&, WindowServer::ScreenLayout const&); template<> -ErrorOr decode(Decoder&, WindowServer::ScreenLayout&); +ErrorOr decode(Decoder&); } diff --git a/Userland/Services/WindowServer/ScreenLayout.ipp b/Userland/Services/WindowServer/ScreenLayout.ipp index 592a67cbbf..77b4b04497 100644 --- a/Userland/Services/WindowServer/ScreenLayout.ipp +++ b/Userland/Services/WindowServer/ScreenLayout.ipp @@ -76,7 +76,7 @@ bool ScreenLayout::is_valid(DeprecatedString* error_msg) const *error_msg = "Screen layout has not been normalized"; return false; } - Vector reachable_screens { &screens[main_screen_index] }; + Vector reachable_screens { &screens[main_screen_index] }; bool did_reach_another_screen; do { did_reach_another_screen = false; @@ -225,7 +225,7 @@ bool ScreenLayout::normalize() return did_change; } -bool ScreenLayout::load_config(const Core::ConfigFile& config_file, DeprecatedString* error_msg) +bool ScreenLayout::load_config(Core::ConfigFile const& config_file, DeprecatedString* error_msg) { screens.clear_with_capacity(); main_screen_index = config_file.read_num_entry("Screens", "MainScreen", 0); @@ -290,7 +290,7 @@ bool ScreenLayout::save_config(Core::ConfigFile& config_file, bool sync) const return true; } -bool ScreenLayout::operator!=(const ScreenLayout& other) const +bool ScreenLayout::operator!=(ScreenLayout const& other) const { if (this == &other) return false; @@ -400,20 +400,15 @@ bool encode(Encoder& encoder, WindowServer::ScreenLayout::Screen const& screen) } template<> -ErrorOr decode(Decoder& decoder, WindowServer::ScreenLayout::Screen& screen) +ErrorOr decode(Decoder& decoder) { - WindowServer::ScreenLayout::Screen::Mode mode; - TRY(decoder.decode(mode)); - Optional device; - TRY(decoder.decode(device)); - Gfx::IntPoint location; - TRY(decoder.decode(location)); - Gfx::IntSize resolution; - TRY(decoder.decode(resolution)); - int scale_factor = 0; - TRY(decoder.decode(scale_factor)); - screen = { mode, device, location, resolution, scale_factor }; - return {}; + auto mode = TRY(decoder.decode()); + auto device = TRY(decoder.decode>()); + auto location = TRY(decoder.decode()); + auto resolution = TRY(decoder.decode()); + auto scale_factor = TRY(decoder.decode()); + + return WindowServer::ScreenLayout::Screen { mode, device, location, resolution, scale_factor }; } template<> @@ -424,14 +419,12 @@ bool encode(Encoder& encoder, WindowServer::ScreenLayout const& screen_layout) } template<> -ErrorOr decode(Decoder& decoder, WindowServer::ScreenLayout& screen_layout) +ErrorOr decode(Decoder& decoder) { - Vector screens; - TRY(decoder.decode(screens)); - unsigned main_screen_index = 0; - TRY(decoder.decode(main_screen_index)); - screen_layout = { move(screens), main_screen_index }; - return {}; + auto screens = TRY(decoder.decode>()); + auto main_screen_index = TRY(decoder.decode()); + + return WindowServer::ScreenLayout { move(screens), main_screen_index }; } }