// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIB_ASYNC_CPP_RECEIVER_H_
#define LIB_ASYNC_CPP_RECEIVER_H_

#include <lib/async/receiver.h>
#include <lib/fit/function.h>

#include <utility>

namespace async {

// Holds content for a packet receiver and its handler.
//
// After successfully queuing packets to the receiver, the client is responsible
// for retaining the structure in memory (and unmodified) until all packets have
// been received by the handler or the dispatcher shuts down.  There is no way
// to cancel a packet which has been queued.
//
// Multiple packets may be delivered to the same receiver concurrently.
//
// Concrete implementations: |async::Receiver|, |async::ReceiverMethod|.
// Please do not create subclasses of ReceiverBase outside of this library.
class ReceiverBase {
protected:
    explicit ReceiverBase(async_receiver_handler_t* handler);
    ~ReceiverBase();

    ReceiverBase(const ReceiverBase&) = delete;
    ReceiverBase(ReceiverBase&&) = delete;
    ReceiverBase& operator=(const ReceiverBase&) = delete;
    ReceiverBase& operator=(ReceiverBase&&) = delete;

public:
    // Enqueues a packet of data for delivery to a receiver.
    //
    // The |data| will be copied into the packet.  May be NULL to create a
    // zero-initialized packet payload.
    //
    // Returns |ZX_OK| if the packet was successfully enqueued.
    // Returns |ZX_ERR_BAD_STATE| if the dispatcher is shutting down.
    // Returns |ZX_ERR_NOT_SUPPORTED| if not supported by the dispatcher.
    zx_status_t QueuePacket(async_dispatcher_t* dispatcher, const zx_packet_user_t* data = nullptr);

protected:
    template <typename T>
    static T* Dispatch(async_receiver_t* receiver) {
        static_assert(offsetof(ReceiverBase, receiver_) == 0, "");
        auto self = reinterpret_cast<ReceiverBase*>(receiver);
        return static_cast<T*>(self);
    }

private:
    async_receiver_t receiver_;
};

// A receiver whose handler is bound to a |async::Task::Handler| function.
//
// Prefer using |async::ReceiverMethod| instead for binding to a fixed class member
// function since it is more efficient to dispatch.
class Receiver final : public ReceiverBase {
public:
    // Handles receipt of packets containing user supplied data.
    //
    // The |status| is |ZX_OK| if the packet was successfully delivered and |data|
    // contains the information from the packet, otherwise |data| is null.
    using Handler = fit::function<void(async_dispatcher_t* dispatcher,
                                       async::Receiver* receiver,
                                       zx_status_t status,
                                       const zx_packet_user_t* data)>;

    explicit Receiver(Handler handler = nullptr);
    ~Receiver();

    void set_handler(Handler handler) { handler_ = std::move(handler); }
    bool has_handler() const { return !!handler_; }

private:
    static void CallHandler(async_dispatcher_t* dispatcher, async_receiver_t* receiver,
                            zx_status_t status, const zx_packet_user_t* data);

    Handler handler_;
};

// A receiver whose handler is bound to a fixed class member function.
//
// Usage:
//
// class Foo {
//     void Handle(async_dispatcher_t* dispatcher, async::ReceiverBase* receiver, zx_status_t status,
//                 const zx_packet_user_t* data) { ... }
//     async::ReceiverMethod<Foo, &Foo::Handle> receiver_{this};
// };
template <class Class,
          void (Class::*method)(async_dispatcher_t* dispatcher, async::ReceiverBase* receiver,
                                zx_status_t status, const zx_packet_user_t* data)>
class ReceiverMethod final : public ReceiverBase {
public:
    explicit ReceiverMethod(Class* instance)
        : ReceiverBase(&ReceiverMethod::CallHandler), instance_(instance) {}

private:
    static void CallHandler(async_dispatcher_t* dispatcher, async_receiver_t* receiver,
                            zx_status_t status, const zx_packet_user_t* data) {
        auto self = Dispatch<ReceiverMethod>(receiver);
        (self->instance_->*method)(dispatcher, self, status, data);
    }

    Class* const instance_;
};

} // namespace async

#endif  // LIB_ASYNC_CPP_RECEIVER_H_
