/* * Copyright (c) 2018-2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include namespace IPC { template bool encode(Encoder&, T const&) { static_assert(DependentFalse, "Base IPC::encode() was instantiated"); VERIFY_NOT_REACHED(); } class Encoder { public: explicit Encoder(MessageBuffer& buffer) : m_buffer(buffer) { } Encoder& operator<<(bool); Encoder& operator<<(u8); Encoder& operator<<(u16); Encoder& operator<<(unsigned); Encoder& operator<<(unsigned long); Encoder& operator<<(unsigned long long); Encoder& operator<<(i8); Encoder& operator<<(i16); Encoder& operator<<(i32); Encoder& operator<<(i64); Encoder& operator<<(float); Encoder& operator<<(double); Encoder& operator<<(char const*); Encoder& operator<<(StringView); Encoder& operator<<(DeprecatedString const&); Encoder& operator<<(ByteBuffer const&); Encoder& operator<<(JsonValue const&); Encoder& operator<<(URL const&); Encoder& operator<<(Dictionary const&); Encoder& operator<<(File const&); Encoder& operator<<(AK::Empty const&); template Encoder& operator<<(HashMap const& hashmap) { *this << (u32)hashmap.size(); for (auto it : hashmap) { *this << it.key; *this << it.value; } return *this; } template Encoder& operator<<(OrderedHashMap const& hashmap) { *this << (u32)hashmap.size(); for (auto it : hashmap) { *this << it.key; *this << it.value; } return *this; } template Encoder& operator<<(Vector const& vector) { *this << (u64)vector.size(); for (auto& value : vector) *this << value; return *this; } template Encoder& operator<<(Core::SharedSingleProducerCircularQueue const& queue) { *this << IPC::File(queue.fd()); return *this; } // Note: We require any encodeable variant to have Empty as its first variant, as only possibly-empty variants can be default constructed. // The default constructability is required by generated IPC message marshalling code. template Encoder& operator<<(AK::Variant const& variant) { // Note: This might be either u8 or size_t depending on the size of the variant; both are encodeable. *this << variant.index(); variant.visit([this](auto const& underlying_value) { *this << underlying_value; }); return *this; } template Encoder& operator<<(T const& enum_value) { *this << AK::to_underlying(enum_value); return *this; } template Encoder& operator<<(T const& value) { encode(value); return *this; } template Encoder& operator<<(Optional const& optional) { *this << optional.has_value(); if (optional.has_value()) *this << optional.value(); return *this; } template void encode(T const& value) { IPC::encode(*this, value); } private: void encode_u32(u32); void encode_u64(u64); MessageBuffer& m_buffer; }; }