/* * Copyright (c) 2018-2021, Andreas Kling * Copyright (c) 2023, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace IPC { template ErrorOr 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) { } template ErrorOr encode(T const& value); ErrorOr extend_capacity(size_t capacity) { TRY(m_buffer.extend_data_capacity(capacity)); return {}; } ErrorOr append(u8 const* values, size_t count) { TRY(m_buffer.append_data(values, count)); return {}; } ErrorOr append_file_descriptor(int fd) { TRY(m_buffer.append_file_descriptor(fd)); return {}; } ErrorOr encode_size(size_t size); private: MessageBuffer& m_buffer; }; template ErrorOr encode(Encoder& encoder, T const& value) { TRY(encoder.append(reinterpret_cast(&value), sizeof(value))); return {}; } template ErrorOr encode(Encoder& encoder, T const& value) { return encoder.encode(to_underlying(value)); } template<> ErrorOr encode(Encoder&, float const&); template<> ErrorOr encode(Encoder&, double const&); template<> ErrorOr encode(Encoder&, String const&); template<> ErrorOr encode(Encoder&, StringView const&); template<> ErrorOr encode(Encoder&, ByteString const&); template<> ErrorOr encode(Encoder&, ByteBuffer const&); template<> ErrorOr encode(Encoder&, JsonValue const&); template<> ErrorOr encode(Encoder&, AK::Duration const&); template<> ErrorOr encode(Encoder&, UnixDateTime const&); template<> ErrorOr encode(Encoder&, URL::URL const&); template<> ErrorOr encode(Encoder&, URL::Origin const&); template<> ErrorOr encode(Encoder&, File const&); template<> ErrorOr encode(Encoder&, Empty const&); template ErrorOr encode(Encoder& encoder, Array const& array) { TRY(encoder.encode_size(array.size())); for (auto const& value : array) TRY(encoder.encode(value)); return {}; } template ErrorOr encode(Encoder& encoder, T const& vector) { // NOTE: Do not change this encoding without also updating LibC/netdb.cpp. TRY(encoder.encode_size(vector.size())); for (auto const& value : vector) TRY(encoder.encode(value)); return {}; } template ErrorOr encode(Encoder& encoder, T const& hashmap) { TRY(encoder.encode_size(hashmap.size())); for (auto it : hashmap) { TRY(encoder.encode(it.key)); TRY(encoder.encode(it.value)); } return {}; } template ErrorOr encode(Encoder& encoder, T const& queue) { TRY(encoder.encode(TRY(IPC::File::clone_fd(queue.fd())))); return {}; } template ErrorOr encode(Encoder& encoder, T const& optional) { TRY(encoder.encode(optional.has_value())); if (optional.has_value()) TRY(encoder.encode(optional.value())); return {}; } template ErrorOr encode(Encoder& encoder, T const& variant) { TRY(encoder.encode(variant.index())); return variant.visit([&](auto const& value) { return encoder.encode(value); }); } // This must be last so that it knows about the above specializations. template ErrorOr Encoder::encode(T const& value) { return IPC::encode(*this, value); } }