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 }; } }