// WARNING: This file is machine generated by fidlgen.

#pragma once

#include <bottom/llcpp/fidl.h>
#include <lib/fidl/internal.h>
#include <lib/fidl/llcpp/array.h>
#include <lib/fidl/llcpp/buffer_allocator.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/envelope.h>
#include <lib/fidl/llcpp/memory.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/sync_call.h>
#include <lib/fidl/llcpp/tracking_ptr.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fidl/txn_header.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <middle/llcpp/fidl.h>
#include <zircon/fidl.h>

namespace llcpp {

namespace top {

class Top;

extern "C" const fidl_type_t v1_top_TopGetFooRequestTable;
extern "C" const fidl_type_t v1_top_TopGetFooResponseTable;

class Top final {
  Top() = delete;

 public:
  struct GetFooResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::llcpp::bottom::Foo foo;

    static constexpr const fidl_type_t* Type = &v1_top_TopGetFooResponseTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  using GetFooRequest = ::fidl::AnyZeroArgMessage;

  // Collection of return types of FIDL calls in this protocol.
  class ResultOf final {
    ResultOf() = delete;

   private:
    template <typename ResponseType>
    class GetFoo_Impl final
        : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;

     public:
      GetFoo_Impl(::zx::unowned_channel _client_end);
      ~GetFoo_Impl() = default;
      GetFoo_Impl(GetFoo_Impl&& other) = default;
      GetFoo_Impl& operator=(GetFoo_Impl&& other) = default;
      using Super::error;
      using Super::ok;
      using Super::status;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using GetFoo = GetFoo_Impl<GetFooResponse>;
  };

  // Collection of return types of FIDL calls in this protocol,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;

   private:
    template <typename ResponseType>
    class GetFoo_Impl final
        : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;

     public:
      GetFoo_Impl(::zx::unowned_channel _client_end,
                  ::fidl::BytePart _response_buffer);
      ~GetFoo_Impl() = default;
      GetFoo_Impl(GetFoo_Impl&& other) = default;
      GetFoo_Impl& operator=(GetFoo_Impl&& other) = default;
      using Super::error;
      using Super::ok;
      using Super::status;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using GetFoo = GetFoo_Impl<GetFooResponse>;
  };

  class SyncClient final {
   public:
    SyncClient() = default;
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::GetFoo GetFoo();

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::GetFoo GetFoo(::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding
  // setting up a client.
  class Call final {
    Call() = delete;

   public:
    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::GetFoo GetFoo(::zx::unowned_channel _client_end);

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::GetFoo GetFoo(::zx::unowned_channel _client_end,
                                          ::fidl::BytePart _response_buffer);
  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL
  // wire-format.
  class InPlace final {
    InPlace() = delete;

   public:
    static ::fidl::DecodeResult<GetFooResponse> GetFoo(
        ::zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);
  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = Top;
    using _Base = ::fidl::CompleterBase;

    class GetFooCompleterBase : public _Base {
     public:
      void Reply(::llcpp::bottom::Foo foo);
      void Reply(::fidl::BytePart _buffer, ::llcpp::bottom::Foo foo);
      void Reply(::fidl::DecodedMessage<GetFooResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetFooCompleter = ::fidl::Completer<GetFooCompleterBase>;

    virtual void GetFoo(GetFooCompleter::Sync _completer) = 0;
  };

  // Attempts to dispatch the incoming message to a handler function in the
  // server implementation. If there is no matching handler, it returns false,
  // leaving the message and transaction intact. In all other cases, it consumes
  // the message and returns true. It is possible to chain multiple TryDispatch
  // functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg,
                          ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the
  // protocol. If there is no matching handler, it closes all the handles in
  // |msg| and closes the channel with a |ZX_ERR_NOT_SUPPORTED| epitaph, before
  // returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg,
                       ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used
  // with |fidl::Bind| to reduce template expansion. Do not call this method
  // manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg,
                                 ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }

  // Helper functions to fill in the transaction header in a
  // |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;

   public:
    static void GetFooRequest(
        const ::fidl::DecodedMessage<Top::GetFooRequest>& _msg);
    static void GetFooResponse(
        const ::fidl::DecodedMessage<Top::GetFooResponse>& _msg);
  };
};

}  // namespace top
}  // namespace llcpp

namespace fidl {

template <>
struct IsFidlType<::llcpp::top::Top::GetFooResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::top::Top::GetFooResponse>
    : public std::true_type {};
static_assert(sizeof(::llcpp::top::Top::GetFooResponse) ==
              ::llcpp::top::Top::GetFooResponse::PrimarySize);
static_assert(offsetof(::llcpp::top::Top::GetFooResponse, foo) == 16);

}  // namespace fidl
