#pragma once

#include <LibCore/AnonymousBuffer.h>
#include <LibIPC/TransportHandle.h>
#include <AK/Error.h>
#include <AK/MemoryStream.h>
#include <AK/OwnPtr.h>
#include <AK/Platform.h>
#include <AK/Result.h>
#include <AK/Utf8View.h>
#include <LibIPC/Attachment.h>
#include <LibIPC/Connection.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
#include <LibIPC/File.h>
#include <LibIPC/Message.h>
#include <LibIPC/Stub.h>

#if defined(AK_COMPILER_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdefaulted-function-deleted"
#endif

namespace Messages::ImageDecoderServer {

enum class MessageID : i32 {
    InitTransport = 1,
    InitTransportResponse = 2,
    DecodeImage = 3,
    CancelDecoding = 4,
    RequestAnimationFrames = 5,
    StopAnimationDecode = 6,
    ConnectNewClients = 7,
    ConnectNewClientsResponse = 8,
};

class InitTransportResponse final : public IPC::Message {
public:
    InitTransportResponse(int peer_pid)
        : m_peer_pid(move(peer_pid))
    {
    }

    InitTransportResponse(InitTransportResponse const&) = default;
    InitTransportResponse(InitTransportResponse&&) = default;
    InitTransportResponse& operator=(InitTransportResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, int>)
    InitTransportResponse(WrappedReturnType&& value)
        : m_peer_pid(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 3964467294;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::InitTransportResponse; }
    static i32 static_message_id() { return (int)MessageID::InitTransportResponse; }
    virtual StringView message_name() const override { return "ImageDecoderServer::InitTransportResponse"sv; }

    static ErrorOr<NonnullOwnPtr<InitTransportResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto peer_pid = TRY((decoder.decode<int>()));
        return make<InitTransportResponse>(move(peer_pid));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(int peer_pid)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::InitTransportResponse));
        TRY(stream.encode(peer_pid));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_peer_pid);
    }

    int peer_pid() const { return m_peer_pid; }

private:
    int m_peer_pid;
};

class InitTransport final : public IPC::Message {
public:
    typedef class InitTransportResponse ResponseType;

    InitTransport(int peer_pid)
        : m_peer_pid(move(peer_pid))
    {
    }

    InitTransport(InitTransport const&) = default;
    InitTransport(InitTransport&&) = default;
    InitTransport& operator=(InitTransport const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, int>)
    InitTransport(WrappedReturnType&& value)
        : m_peer_pid(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 3964467294;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::InitTransport; }
    static i32 static_message_id() { return (int)MessageID::InitTransport; }
    virtual StringView message_name() const override { return "ImageDecoderServer::InitTransport"sv; }

    static ErrorOr<NonnullOwnPtr<InitTransport>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto peer_pid = TRY((decoder.decode<int>()));
        return make<InitTransport>(move(peer_pid));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(int peer_pid)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::InitTransport));
        TRY(stream.encode(peer_pid));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_peer_pid);
    }

    int peer_pid() const { return m_peer_pid; }

private:
    int m_peer_pid;
};

class DecodeImage final : public IPC::Message {
public:
    DecodeImage(Core::AnonymousBuffer data, Optional<Gfx::IntSize> ideal_size, Optional<ByteString> mime_type, i64 request_id)
        : m_data(move(data))
        , m_ideal_size(move(ideal_size))
        , m_mime_type(move(mime_type))
        , m_request_id(move(request_id))
    {
    }

    DecodeImage(DecodeImage const&) = default;
    DecodeImage(DecodeImage&&) = default;
    DecodeImage& operator=(DecodeImage const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 3964467294;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::DecodeImage; }
    static i32 static_message_id() { return (int)MessageID::DecodeImage; }
    virtual StringView message_name() const override { return "ImageDecoderServer::DecodeImage"sv; }

    static ErrorOr<NonnullOwnPtr<DecodeImage>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto data = TRY((decoder.decode<Core::AnonymousBuffer>()));
        auto ideal_size = TRY((decoder.decode<Optional<Gfx::IntSize>>()));
        auto mime_type = TRY((decoder.decode<Optional<ByteString>>()));
        auto request_id = TRY((decoder.decode<i64>()));
        return make<DecodeImage>(move(data), move(ideal_size), move(mime_type), move(request_id));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Core::AnonymousBuffer const& data, Optional<Gfx::IntSize> const& ideal_size, Optional<ByteString> const& mime_type, i64 request_id)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::DecodeImage));
        TRY(stream.encode(data));
        TRY(stream.encode(ideal_size));
        TRY(stream.encode(mime_type));
        TRY(stream.encode(request_id));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_data, m_ideal_size, m_mime_type, m_request_id);
    }

    Core::AnonymousBuffer const& data() const { return m_data; }
    Core::AnonymousBuffer take_data() { return move(m_data); }

    Optional<Gfx::IntSize> const& ideal_size() const { return m_ideal_size; }
    Optional<Gfx::IntSize> take_ideal_size() { return move(m_ideal_size); }

    Optional<ByteString> const& mime_type() const { return m_mime_type; }
    Optional<ByteString> take_mime_type() { return move(m_mime_type); }

    i64 request_id() const { return m_request_id; }

private:
    Core::AnonymousBuffer m_data;
    Optional<Gfx::IntSize> m_ideal_size;
    Optional<ByteString> m_mime_type;
    i64 m_request_id;
};

class CancelDecoding final : public IPC::Message {
public:
    CancelDecoding(i64 request_id)
        : m_request_id(move(request_id))
    {
    }

    CancelDecoding(CancelDecoding const&) = default;
    CancelDecoding(CancelDecoding&&) = default;
    CancelDecoding& operator=(CancelDecoding const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, i64>)
    CancelDecoding(WrappedReturnType&& value)
        : m_request_id(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 3964467294;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::CancelDecoding; }
    static i32 static_message_id() { return (int)MessageID::CancelDecoding; }
    virtual StringView message_name() const override { return "ImageDecoderServer::CancelDecoding"sv; }

    static ErrorOr<NonnullOwnPtr<CancelDecoding>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto request_id = TRY((decoder.decode<i64>()));
        return make<CancelDecoding>(move(request_id));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(i64 request_id)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::CancelDecoding));
        TRY(stream.encode(request_id));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_request_id);
    }

    i64 request_id() const { return m_request_id; }

private:
    i64 m_request_id;
};

class RequestAnimationFrames final : public IPC::Message {
public:
    RequestAnimationFrames(i64 session_id, u32 start_frame_index, u32 count)
        : m_session_id(move(session_id))
        , m_start_frame_index(move(start_frame_index))
        , m_count(move(count))
    {
    }

    RequestAnimationFrames(RequestAnimationFrames const&) = default;
    RequestAnimationFrames(RequestAnimationFrames&&) = default;
    RequestAnimationFrames& operator=(RequestAnimationFrames const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 3964467294;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::RequestAnimationFrames; }
    static i32 static_message_id() { return (int)MessageID::RequestAnimationFrames; }
    virtual StringView message_name() const override { return "ImageDecoderServer::RequestAnimationFrames"sv; }

    static ErrorOr<NonnullOwnPtr<RequestAnimationFrames>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto session_id = TRY((decoder.decode<i64>()));
        auto start_frame_index = TRY((decoder.decode<u32>()));
        auto count = TRY((decoder.decode<u32>()));
        return make<RequestAnimationFrames>(move(session_id), move(start_frame_index), move(count));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(i64 session_id, u32 start_frame_index, u32 count)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::RequestAnimationFrames));
        TRY(stream.encode(session_id));
        TRY(stream.encode(start_frame_index));
        TRY(stream.encode(count));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_session_id, m_start_frame_index, m_count);
    }

    i64 session_id() const { return m_session_id; }

    u32 start_frame_index() const { return m_start_frame_index; }

    u32 count() const { return m_count; }

private:
    i64 m_session_id;
    u32 m_start_frame_index;
    u32 m_count;
};

class StopAnimationDecode final : public IPC::Message {
public:
    StopAnimationDecode(i64 session_id)
        : m_session_id(move(session_id))
    {
    }

    StopAnimationDecode(StopAnimationDecode const&) = default;
    StopAnimationDecode(StopAnimationDecode&&) = default;
    StopAnimationDecode& operator=(StopAnimationDecode const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, i64>)
    StopAnimationDecode(WrappedReturnType&& value)
        : m_session_id(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 3964467294;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::StopAnimationDecode; }
    static i32 static_message_id() { return (int)MessageID::StopAnimationDecode; }
    virtual StringView message_name() const override { return "ImageDecoderServer::StopAnimationDecode"sv; }

    static ErrorOr<NonnullOwnPtr<StopAnimationDecode>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto session_id = TRY((decoder.decode<i64>()));
        return make<StopAnimationDecode>(move(session_id));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(i64 session_id)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::StopAnimationDecode));
        TRY(stream.encode(session_id));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_session_id);
    }

    i64 session_id() const { return m_session_id; }

private:
    i64 m_session_id;
};

class ConnectNewClientsResponse final : public IPC::Message {
public:
    ConnectNewClientsResponse(Vector<IPC::TransportHandle> handles)
        : m_handles(move(handles))
    {
    }

    ConnectNewClientsResponse(ConnectNewClientsResponse const&) = default;
    ConnectNewClientsResponse(ConnectNewClientsResponse&&) = default;
    ConnectNewClientsResponse& operator=(ConnectNewClientsResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, Vector<IPC::TransportHandle>>)
    ConnectNewClientsResponse(WrappedReturnType&& value)
        : m_handles(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 3964467294;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ConnectNewClientsResponse; }
    static i32 static_message_id() { return (int)MessageID::ConnectNewClientsResponse; }
    virtual StringView message_name() const override { return "ImageDecoderServer::ConnectNewClientsResponse"sv; }

    static ErrorOr<NonnullOwnPtr<ConnectNewClientsResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto handles = TRY((decoder.decode<Vector<IPC::TransportHandle>>()));
        return make<ConnectNewClientsResponse>(move(handles));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(ReadonlySpan<IPC::TransportHandle> handles)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ConnectNewClientsResponse));
        TRY(stream.encode(handles));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_handles);
    }

    Vector<IPC::TransportHandle> const& handles() const { return m_handles; }
    Vector<IPC::TransportHandle> take_handles() { return move(m_handles); }

private:
    Vector<IPC::TransportHandle> m_handles;
};

class ConnectNewClients final : public IPC::Message {
public:
    typedef class ConnectNewClientsResponse ResponseType;

    ConnectNewClients(size_t count)
        : m_count(move(count))
    {
    }

    ConnectNewClients(ConnectNewClients const&) = default;
    ConnectNewClients(ConnectNewClients&&) = default;
    ConnectNewClients& operator=(ConnectNewClients const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, size_t>)
    ConnectNewClients(WrappedReturnType&& value)
        : m_count(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 3964467294;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ConnectNewClients; }
    static i32 static_message_id() { return (int)MessageID::ConnectNewClients; }
    virtual StringView message_name() const override { return "ImageDecoderServer::ConnectNewClients"sv; }

    static ErrorOr<NonnullOwnPtr<ConnectNewClients>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto count = TRY((decoder.decode<size_t>()));
        return make<ConnectNewClients>(move(count));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(size_t count)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ConnectNewClients));
        TRY(stream.encode(count));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_count);
    }

    size_t count() const { return m_count; }

private:
    size_t m_count;
};

} // namespace Messages::ImageDecoderServer

template<typename LocalEndpoint, typename PeerEndpoint>
class ImageDecoderServerProxy {
public:
    // Used to disambiguate the constructor call.
    struct Tag { };

    ImageDecoderServerProxy(IPC::Connection<LocalEndpoint, PeerEndpoint>& connection, Tag)
        : m_connection(connection)
    {
    }

    int init_transport(int peer_pid)
    {
        return m_connection.template send_sync<Messages::ImageDecoderServer::InitTransport>(peer_pid)->peer_pid();
    }

    void async_init_transport(int peer_pid)
    {
        auto message_buffer = MUST(Messages::ImageDecoderServer::InitTransport::static_encode(peer_pid));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<int> try_init_transport(int peer_pid)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::ImageDecoderServer::InitTransport>(peer_pid))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    void async_decode_image(Core::AnonymousBuffer const& data, Optional<Gfx::IntSize> const& ideal_size, Optional<ByteString> const& mime_type, i64 request_id)
    {
        auto message_buffer = MUST(Messages::ImageDecoderServer::DecodeImage::static_encode(move(data), move(ideal_size), move(mime_type), request_id));
        (void)m_connection.post_message(message_buffer);
    }

    void async_cancel_decoding(i64 request_id)
    {
        auto message_buffer = MUST(Messages::ImageDecoderServer::CancelDecoding::static_encode(request_id));
        (void)m_connection.post_message(message_buffer);
    }

    void async_request_animation_frames(i64 session_id, u32 start_frame_index, u32 count)
    {
        auto message_buffer = MUST(Messages::ImageDecoderServer::RequestAnimationFrames::static_encode(session_id, start_frame_index, count));
        (void)m_connection.post_message(message_buffer);
    }

    void async_stop_animation_decode(i64 session_id)
    {
        auto message_buffer = MUST(Messages::ImageDecoderServer::StopAnimationDecode::static_encode(session_id));
        (void)m_connection.post_message(message_buffer);
    }

    Vector<IPC::TransportHandle> connect_new_clients(size_t count)
    {
        return m_connection.template send_sync<Messages::ImageDecoderServer::ConnectNewClients>(count)->take_handles();
    }

    void async_connect_new_clients(size_t count)
    {
        auto message_buffer = MUST(Messages::ImageDecoderServer::ConnectNewClients::static_encode(count));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<Vector<IPC::TransportHandle>> try_connect_new_clients(size_t count)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::ImageDecoderServer::ConnectNewClients>(count))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

private:
    IPC::Connection<LocalEndpoint, PeerEndpoint>& m_connection;
};

template<typename LocalEndpoint, typename PeerEndpoint>
class ImageDecoderServerProxy;
class ImageDecoderServerStub;

class ImageDecoderServerEndpoint {
public:
    template<typename LocalEndpoint>
    using Proxy = ImageDecoderServerProxy<LocalEndpoint, ImageDecoderServerEndpoint>;
    using Stub = ImageDecoderServerStub;

    static u32 static_magic() { return 3964467294; }

    static ErrorOr<NonnullOwnPtr<IPC::Message>> decode_message(ReadonlyBytes buffer, [[maybe_unused]] Queue<IPC::Attachment>& attachments)
    {
        FixedMemoryStream stream { buffer };
        auto message_endpoint_magic = TRY(stream.read_value<u32>());

        if (message_endpoint_magic != static_magic())
            return Error::from_string_literal("Endpoint magic number mismatch, not my message!");

        auto message_id = TRY(stream.read_value<i32>());

        switch (message_id) {
        case (int)Messages::ImageDecoderServer::MessageID::InitTransport:
            return Messages::ImageDecoderServer::InitTransport::decode(stream, attachments);
        case (int)Messages::ImageDecoderServer::MessageID::InitTransportResponse:
            return Messages::ImageDecoderServer::InitTransportResponse::decode(stream, attachments);
        case (int)Messages::ImageDecoderServer::MessageID::DecodeImage:
            return Messages::ImageDecoderServer::DecodeImage::decode(stream, attachments);
        case (int)Messages::ImageDecoderServer::MessageID::CancelDecoding:
            return Messages::ImageDecoderServer::CancelDecoding::decode(stream, attachments);
        case (int)Messages::ImageDecoderServer::MessageID::RequestAnimationFrames:
            return Messages::ImageDecoderServer::RequestAnimationFrames::decode(stream, attachments);
        case (int)Messages::ImageDecoderServer::MessageID::StopAnimationDecode:
            return Messages::ImageDecoderServer::StopAnimationDecode::decode(stream, attachments);
        case (int)Messages::ImageDecoderServer::MessageID::ConnectNewClients:
            return Messages::ImageDecoderServer::ConnectNewClients::decode(stream, attachments);
        case (int)Messages::ImageDecoderServer::MessageID::ConnectNewClientsResponse:
            return Messages::ImageDecoderServer::ConnectNewClientsResponse::decode(stream, attachments);
        default:
            return Error::from_string_literal("Failed to decode ImageDecoderServer message");
        }

        VERIFY_NOT_REACHED();
    }
};

class ImageDecoderServerStub : public IPC::Stub {
public:
    ImageDecoderServerStub() { }
    virtual ~ImageDecoderServerStub() override { }

    virtual u32 magic() const override { return 3964467294; }
    virtual ByteString name() const override { return "ImageDecoderServer"; }

    virtual ErrorOr<OwnPtr<IPC::MessageBuffer>> handle(NonnullOwnPtr<IPC::Message> message) override
    {
        switch (message->message_id()) {
        case (int)Messages::ImageDecoderServer::MessageID::InitTransport:
            return handle_init_transport(*message);
        case (int)Messages::ImageDecoderServer::MessageID::DecodeImage:
            return handle_decode_image(*message);
        case (int)Messages::ImageDecoderServer::MessageID::CancelDecoding:
            return handle_cancel_decoding(*message);
        case (int)Messages::ImageDecoderServer::MessageID::RequestAnimationFrames:
            return handle_request_animation_frames(*message);
        case (int)Messages::ImageDecoderServer::MessageID::StopAnimationDecode:
            return handle_stop_animation_decode(*message);
        case (int)Messages::ImageDecoderServer::MessageID::ConnectNewClients:
            return handle_connect_new_clients(*message);
        default:
            return Error::from_string_literal("Unknown message ID for ImageDecoderServer endpoint");
        }
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_init_transport(IPC::Message& message)
    {
        auto& request = static_cast<Messages::ImageDecoderServer::InitTransport&>(message);
        auto response = init_transport(request.peer_pid());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_decode_image(IPC::Message& message)
    {
        auto& request = static_cast<Messages::ImageDecoderServer::DecodeImage&>(message);
        decode_image(request.take_data(), request.take_ideal_size(), request.take_mime_type(), request.request_id());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_cancel_decoding(IPC::Message& message)
    {
        auto& request = static_cast<Messages::ImageDecoderServer::CancelDecoding&>(message);
        cancel_decoding(request.request_id());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_request_animation_frames(IPC::Message& message)
    {
        auto& request = static_cast<Messages::ImageDecoderServer::RequestAnimationFrames&>(message);
        request_animation_frames(request.session_id(), request.start_frame_index(), request.count());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_stop_animation_decode(IPC::Message& message)
    {
        auto& request = static_cast<Messages::ImageDecoderServer::StopAnimationDecode&>(message);
        stop_animation_decode(request.session_id());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_connect_new_clients(IPC::Message& message)
    {
        auto& request = static_cast<Messages::ImageDecoderServer::ConnectNewClients&>(message);
        auto response = connect_new_clients(request.count());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    virtual Messages::ImageDecoderServer::InitTransportResponse init_transport(int peer_pid) = 0;
    virtual void decode_image(Core::AnonymousBuffer data, Optional<Gfx::IntSize> ideal_size, Optional<ByteString> mime_type, i64 request_id) = 0;
    virtual void cancel_decoding(i64 request_id) = 0;
    virtual void request_animation_frames(i64 session_id, u32 start_frame_index, u32 count) = 0;
    virtual void stop_animation_decode(i64 session_id) = 0;
    virtual Messages::ImageDecoderServer::ConnectNewClientsResponse connect_new_clients(size_t count) = 0;
};

#if defined(AK_COMPILER_CLANG)
#pragma clang diagnostic pop
#endif
