/* * Copyright (c) 2020, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include namespace IPC { template inline ErrorOr decode(Decoder&, T&) { static_assert(DependentFalse, "Base IPC::decoder() instantiated"); VERIFY_NOT_REACHED(); } class Decoder { public: Decoder(InputMemoryStream& stream, Core::Stream::LocalSocket& socket) : m_stream(stream) , m_socket(socket) { } 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(String&); ErrorOr decode(ByteBuffer&); ErrorOr decode(URL&); ErrorOr decode(Dictionary&); ErrorOr decode(File&); 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(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)); } 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(Optional& optional) { bool has_value; TRY(decode(has_value)); if (!has_value) { optional = {}; return {}; } T value; TRY(decode(value)); optional = move(value); return {}; } private: InputMemoryStream& m_stream; Core::Stream::LocalSocket& m_socket; }; }