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

#pragma once

#include <lib/fidl/internal.h>
#include <lib/fidl/llcpp/array.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/fidl/llcpp/envelope.h>
#include <lib/fidl/llcpp/errors.h>
#include <lib/fidl/llcpp/message.h>
#include <lib/fidl/llcpp/message_storage.h>
#include <lib/fidl/llcpp/object_view.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fit/function.h>
#include <lib/stdcompat/optional.h>

#include <algorithm>
#include <cstddef>
#include <variant>
#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/client_end.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/result.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/server_end.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/sync_call.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fidl/llcpp/wire_messaging.h>
#include <lib/fidl/txn_header.h>
#include <lib/zx/channel.h>

#endif  // __Fuchsia__
#include <zircon/fidl.h>

namespace fidl_test_bindingsdenylist {
class OnlyLibfuzzerAndDeps;
namespace wire {
class OnlyLlcpp;
}  // namespace wire
class OnlyCppAndDeps;
namespace wire {

extern "C" const fidl_type_t fidl_test_bindingsdenylist_OnlyLlcppTable;

class OnlyLlcpp {
 public:
  OnlyLlcpp()
      : ordinal_(
            ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Ordinal::Invalid),
        envelope_{} {}

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

  enum class Tag : fidl_xunion_tag_t {
    kX = 1,  // 0x1
  };

  bool has_invalid_tag() const {
    return ordinal_ ==
           ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Ordinal::Invalid;
  }

  bool is_x() const {
    return ordinal_ ==
           ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Ordinal::kX;
  }

  static OnlyLlcpp WithX(::fidl::ObjectView<uint32_t> val) {
    OnlyLlcpp result;
    result.set_x(val);
    return result;
  }

  template <typename... Args>
  static OnlyLlcpp WithX(::fidl::AnyAllocator& allocator, Args&&... args) {
    OnlyLlcpp result;
    result.set_x(
        ::fidl::ObjectView<uint32_t>(allocator, std::forward<Args>(args)...));
    return result;
  }

  void set_x(::fidl::ObjectView<uint32_t> elem) {
    ordinal_ = ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Ordinal::kX;
    envelope_.data =
        ::fidl::ObjectView<void>::FromExternal(static_cast<void*>(elem.get()));
  }

  template <typename... Args>
  void set_x(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Ordinal::kX;
    set_x(::fidl::ObjectView<uint32_t>(allocator, std::forward<Args>(args)...));
  }

  uint32_t& mutable_x() {
    ZX_ASSERT(ordinal_ ==
              ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Ordinal::kX);
    return *static_cast<uint32_t*>(envelope_.data.get());
  }
  const uint32_t& x() const {
    ZX_ASSERT(ordinal_ ==
              ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Ordinal::kX);
    return *static_cast<uint32_t*>(envelope_.data.get());
  }
  ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Tag which() const {
    ZX_ASSERT(!has_invalid_tag());
    return static_cast<::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Tag>(
        ordinal_);
  }

  static constexpr const fidl_type_t* Type =
      &fidl_test_bindingsdenylist_OnlyLlcppTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 8;
  static constexpr bool HasPointer = true;

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kX = 1,  // 0x1
  };

  static void SizeAndOffsetAssertionHelper();
  ::fidl_test_bindingsdenylist::wire::OnlyLlcpp::Ordinal ordinal_;
  FIDL_ALIGNDECL
  ::fidl::Envelope<void> envelope_;
};

}  // namespace wire
extern "C" const fidl_type_t
    fidl_test_bindingsdenylist_OnlyLibfuzzerAndDepsLibfuzzerNeedsNonemptyProtocolRequestTable;

extern "C" const fidl_type_t
    fidl_test_bindingsdenylist_OnlyLibfuzzerAndDepsLibfuzzerNeedsNonemptyProtocolResponseTable;

class OnlyLibfuzzerAndDeps final {
  OnlyLibfuzzerAndDeps() = delete;

 public:
  class LibfuzzerNeedsNonemptyProtocol final {
    LibfuzzerNeedsNonemptyProtocol() = delete;
  };
};
}  // namespace fidl_test_bindingsdenylist
#ifdef __Fuchsia__

template <>
struct ::fidl::internal::ProtocolDetails<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps> {};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct ::fidl::internal::WireDispatcher<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    final {
  WireDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireInterface<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>*
          impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
  static ::fidl::DispatchResult Dispatch(
      ::fidl::WireInterface<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>*
          impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
};

template <>
struct ::fidl::internal::WireServerDispatcher<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    final {
  WireServerDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireServer<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>*
          impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
  static ::fidl::DispatchResult Dispatch(
      ::fidl::WireServer<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>*
          impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
};
#endif  // __Fuchsia__

template <>
struct ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                               LibfuzzerNeedsNonemptyProtocol>
    final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  explicit WireRequest(zx_txid_t _txid) { _InitHeader(_txid); }

  static constexpr const fidl_type_t* Type =
      &::fidl::_llcpp_coding_AnyZeroArgMessageTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 16;
  static constexpr uint32_t MaxOutOfLine = 0;
  static constexpr uint32_t AltPrimarySize = 16;
  static constexpr uint32_t AltMaxOutOfLine = 0;
  static constexpr bool HasFlexibleEnvelope = false;
  static constexpr bool HasPointer = false;
  static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
      ::fidl::internal::TransactionalMessageKind::kRequest;

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* _backing_buffer,
                          uint32_t _backing_buffer_size, zx_txid_t _txid)
        : message_(::fidl::OutgoingMessage::ConstructorArgs{
              .iovecs = iovecs_,
              .iovec_capacity = ::fidl::internal::IovecBufferSize,
              .backing_buffer = _backing_buffer,
              .backing_buffer_capacity = _backing_buffer_size,
          }) {
      if (_backing_buffer_size < sizeof(WireRequest)) {
        ::fidl::internal::OutgoingMessageResultSetter::SetResult(
            message_, ZX_ERR_BUFFER_TOO_SMALL, nullptr);
        return;
      }
      FIDL_ALIGNDECL WireRequest _request(_txid);
      message_.Encode<WireRequest>(&_request);
    }
    UnownedEncodedMessage(uint8_t* _backing_buffer,
                          uint32_t _backing_buffer_size, WireRequest* request)
        : message_(::fidl::OutgoingMessage::ConstructorArgs{
              .iovecs = iovecs_,
              .iovec_capacity = ::fidl::internal::IovecBufferSize,
              .backing_buffer = _backing_buffer,
              .backing_buffer_capacity = _backing_buffer_size,
          }) {
      if (_backing_buffer_size < sizeof(WireRequest)) {
        ::fidl::internal::OutgoingMessageResultSetter::SetResult(
            message_, ZX_ERR_BUFFER_TOO_SMALL, nullptr);
        return;
      }
      message_.Encode<WireRequest>(request);
    }
    UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
    UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

    zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
    const char* status_string() const { return message_.status_string(); }
#endif  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    ::fidl::internal::IovecBuffer iovecs_;
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(zx_txid_t _txid)
        : message_(backing_buffer_.data(), backing_buffer_.size(), _txid) {}
    explicit OwnedEncodedMessage(WireRequest* request)
        : message_(backing_buffer_.data(), backing_buffer_.size(), request) {}
    OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
    OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

    zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
    const char* status_string() const { return message_.status_string(); }
#endif  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    ::fidl::internal::InlineMessageBuffer<16> backing_buffer_;
    UnownedEncodedMessage message_;
  };

 public:
  class DecodedMessage final : public ::fidl::internal::IncomingMessage {
   public:
    DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                   zx_handle_info_t* handles = nullptr,
                   uint32_t handle_actual = 0)
        : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                            handle_actual) {
      Decode<WireRequest>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<WireRequest>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    WireRequest* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<WireRequest*>(bytes());
    }

    // Release the ownership of the decoded message. That means that the handles
    // won't be closed When the object is destroyed. After calling this method,
    // the DecodedMessage object should not be used anymore.
    void ReleasePrimaryObject() { ResetBytes(); }
  };

 private:
  void _InitHeader(zx_txid_t _txid);
};
template <>
struct ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                                LibfuzzerNeedsNonemptyProtocol>
    final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  WireResponse() { _InitHeader(); }

  static constexpr const fidl_type_t* Type =
      &::fidl::_llcpp_coding_AnyZeroArgMessageTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 16;
  static constexpr uint32_t MaxOutOfLine = 0;
  static constexpr bool HasFlexibleEnvelope = false;
  static constexpr bool HasPointer = false;
  static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
      ::fidl::internal::TransactionalMessageKind::kResponse;

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* _backing_buffer,
                          uint32_t _backing_buffer_size)
        : message_(::fidl::OutgoingMessage::ConstructorArgs{
              .iovecs = iovecs_,
              .iovec_capacity = ::fidl::internal::IovecBufferSize,
              .backing_buffer = _backing_buffer,
              .backing_buffer_capacity = _backing_buffer_size,
          }) {
      FIDL_ALIGNDECL WireResponse _response{};
      if (_backing_buffer_size < sizeof(WireResponse)) {
        ::fidl::internal::OutgoingMessageResultSetter::SetResult(
            message_, ZX_ERR_BUFFER_TOO_SMALL, nullptr);
        return;
      }
      message_.Encode<::fidl::WireResponse<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
              LibfuzzerNeedsNonemptyProtocol>>(&_response);
    }
    UnownedEncodedMessage(uint8_t* _backing_buffer,
                          uint32_t _backing_buffer_size, WireResponse* response)
        : message_(::fidl::OutgoingMessage::ConstructorArgs{
              .iovecs = iovecs_,
              .iovec_capacity = ::fidl::internal::IovecBufferSize,
              .backing_buffer = _backing_buffer,
              .backing_buffer_capacity = _backing_buffer_size,
          }) {
      if (_backing_buffer_size < sizeof(WireResponse)) {
        ::fidl::internal::OutgoingMessageResultSetter::SetResult(
            message_, ZX_ERR_BUFFER_TOO_SMALL, nullptr);
        return;
      }
      message_.Encode<::fidl::WireResponse<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
              LibfuzzerNeedsNonemptyProtocol>>(response);
    }
    UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
    UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

    zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
    const char* status_string() const { return message_.status_string(); }
#endif  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    ::fidl::internal::IovecBuffer iovecs_;
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage()
        : message_(backing_buffer_.data(), backing_buffer_.size()) {}
    explicit OwnedEncodedMessage(
        ::fidl::WireResponse<
            ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                LibfuzzerNeedsNonemptyProtocol>* response)
        : message_(backing_buffer_.data(), backing_buffer_.size(), response) {}
    OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
    OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

    zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
    const char* status_string() const { return message_.status_string(); }
#endif  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    ::fidl::internal::InlineMessageBuffer<16> backing_buffer_;
    UnownedEncodedMessage message_;
  };

 public:
  class DecodedMessage final : public ::fidl::internal::IncomingMessage {
   public:
    DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                   zx_handle_info_t* handles = nullptr,
                   uint32_t handle_actual = 0)
        : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                            handle_actual) {
      Decode<::fidl::WireResponse<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
              LibfuzzerNeedsNonemptyProtocol>>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<::fidl::WireResponse<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
              LibfuzzerNeedsNonemptyProtocol>>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    WireResponse* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<::fidl::WireResponse<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
              LibfuzzerNeedsNonemptyProtocol>*>(bytes());
    }

    // Release the ownership of the decoded message. That means that the handles
    // won't be closed When the object is destroyed. After calling this method,
    // the DecodedMessage object should not be used anymore.
    void ReleasePrimaryObject() { ResetBytes(); }
  };

 private:
  void _InitHeader();
};
template <>
class ::fidl::WireResult<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                             LibfuzzerNeedsNonemptyProtocol>
    final : public ::fidl::Result {
 public:
  explicit WireResult(::fidl::UnownedClientEnd<
                      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
                          _client);
  WireResult(::fidl::UnownedClientEnd<
                 ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
                 _client,
             zx_time_t _deadline);
  explicit WireResult(const ::fidl::Result& result) : ::fidl::Result(result) {}
  WireResult(WireResult&&) = delete;
  WireResult(const WireResult&) = delete;
  WireResult* operator=(WireResult&&) = delete;
  WireResult* operator=(const WireResult&) = delete;
  ~WireResult() = default;

  ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                           LibfuzzerNeedsNonemptyProtocol>*
  Unwrap() {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<::fidl::WireResponse<
        ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
            LibfuzzerNeedsNonemptyProtocol>*>(bytes_.data());
  }
  const ::fidl::WireResponse<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
          LibfuzzerNeedsNonemptyProtocol>*
  Unwrap() const {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<const ::fidl::WireResponse<
        ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
            LibfuzzerNeedsNonemptyProtocol>*>(bytes_.data());
  }

  ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                           LibfuzzerNeedsNonemptyProtocol>&
  value() {
    return *Unwrap();
  }
  const ::fidl::WireResponse<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
          LibfuzzerNeedsNonemptyProtocol>&
  value() const {
    return *Unwrap();
  }

  ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                           LibfuzzerNeedsNonemptyProtocol>*
  operator->() {
    return &value();
  }
  const ::fidl::WireResponse<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
          LibfuzzerNeedsNonemptyProtocol>*
  operator->() const {
    return &value();
  }

  ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                           LibfuzzerNeedsNonemptyProtocol>&
  operator*() {
    return value();
  }
  const ::fidl::WireResponse<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
          LibfuzzerNeedsNonemptyProtocol>&
  operator*() const {
    return value();
  }

 private:
  ::fidl::internal::InlineMessageBuffer<16> bytes_;
};
template <>
class ::fidl::WireUnownedResult<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
        LibfuzzerNeedsNonemptyProtocol>
    final : public ::fidl::Result {
 public:
  explicit WireUnownedResult(
      ::fidl::UnownedClientEnd<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
          _client,
      uint8_t* _response_bytes, uint32_t _response_byte_capacity);
  explicit WireUnownedResult(const ::fidl::Result& result)
      : ::fidl::Result(result) {}
  WireUnownedResult(WireUnownedResult&&) = delete;
  WireUnownedResult(const WireUnownedResult&) = delete;
  WireUnownedResult* operator=(WireUnownedResult&&) = delete;
  WireUnownedResult* operator=(const WireUnownedResult&) = delete;
  ~WireUnownedResult() = default;

  ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                           LibfuzzerNeedsNonemptyProtocol>*
  Unwrap() {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<::fidl::WireResponse<
        ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
            LibfuzzerNeedsNonemptyProtocol>*>(bytes_);
  }
  const ::fidl::WireResponse<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
          LibfuzzerNeedsNonemptyProtocol>*
  Unwrap() const {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<const ::fidl::WireResponse<
        ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
            LibfuzzerNeedsNonemptyProtocol>*>(bytes_);
  }

  ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                           LibfuzzerNeedsNonemptyProtocol>&
  value() {
    return *Unwrap();
  }
  const ::fidl::WireResponse<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
          LibfuzzerNeedsNonemptyProtocol>&
  value() const {
    return *Unwrap();
  }

  ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                           LibfuzzerNeedsNonemptyProtocol>*
  operator->() {
    return &value();
  }
  const ::fidl::WireResponse<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
          LibfuzzerNeedsNonemptyProtocol>*
  operator->() const {
    return &value();
  }

  ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                           LibfuzzerNeedsNonemptyProtocol>&
  operator*() {
    return value();
  }
  const ::fidl::WireResponse<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
          LibfuzzerNeedsNonemptyProtocol>&
  operator*() const {
    return value();
  }

 private:
  uint8_t* bytes_;
};

// Methods to make a sync FIDL call directly on an unowned channel or a
// const reference to a
// |fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>|,
// avoiding setting up a client.
template <>
class ::fidl::internal::WireCaller<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    final {
 public:
  explicit WireCaller(::fidl::UnownedClientEnd<
                      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
                          client_end)
      : client_end_(client_end) {}

  // Allocates 32 bytes of message buffer on the stack. No heap allocation
  // necessary.
  static ::fidl::WireResult<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                                LibfuzzerNeedsNonemptyProtocol>
  LibfuzzerNeedsNonemptyProtocol(
      ::fidl::UnownedClientEnd<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
          _client_end) {
    return ::fidl::WireResult<
        ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
            LibfuzzerNeedsNonemptyProtocol>(_client_end);
  }
  // Allocates 32 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                         LibfuzzerNeedsNonemptyProtocol>
  LibfuzzerNeedsNonemptyProtocol() && {
    return ::fidl::WireResult<
        ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
            LibfuzzerNeedsNonemptyProtocol>(client_end_);
  }

 private:
  ::fidl::UnownedClientEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
      client_end_;
};
#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireEventHandlerInterface<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps> {
 public:
  WireEventHandlerInterface() = default;
  virtual ~WireEventHandlerInterface() = default;
};

template <>
class ::fidl::WireAsyncEventHandler<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps> {
 public:
  WireAsyncEventHandler() = default;

  virtual void Unbound(::fidl::UnbindInfo info) {}
};

template <>
class ::fidl::WireSyncEventHandler<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps> {
 public:
  WireSyncEventHandler() = default;

  // Method called when an unknown event is found. This methods gives the status
  // which, in this case, is returned by HandleOneEvent.
  virtual zx_status_t Unknown() = 0;

  // Handle all possible events defined in this protocol.
  // Blocks to consume exactly one message from the channel, then call the
  // corresponding virtual method.
  ::fidl::Result HandleOneEvent(
      ::fidl::UnownedClientEnd<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
          client_end);
};
#endif  // __Fuchsia__

template <>
class ::fidl::WireSyncClient<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    final {
 public:
  WireSyncClient() = default;

  explicit WireSyncClient(
      ::fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
          client_end)
      : client_end_(std::move(client_end)) {}

  ~WireSyncClient() = default;
  WireSyncClient(WireSyncClient&&) = default;
  WireSyncClient& operator=(WireSyncClient&&) = default;

  const ::fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>&
  client_end() const {
    return client_end_;
  }
  ::fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>&
  client_end() {
    return client_end_;
  }

  const ::zx::channel& channel() const { return client_end_.channel(); }
  ::zx::channel* mutable_channel() { return &client_end_.channel(); }

  // Allocates 32 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                         LibfuzzerNeedsNonemptyProtocol>
  LibfuzzerNeedsNonemptyProtocol() {
    return ::fidl::WireResult<
        ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
            LibfuzzerNeedsNonemptyProtocol>(this->client_end());
  }

 private:
  ::fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
      client_end_;
};

// Pure-virtual interface to be implemented by a server.
// This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
// and |fidl::ServerEnd<SomeProtocol>|).
template <>
class ::fidl::WireServer<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    : public ::fidl::internal::IncomingMessageDispatcher {
 public:
  WireServer() = default;
  virtual ~WireServer() = default;

  // The FIDL protocol type that is implemented by this server.
  using _EnclosingProtocol = ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps;

  class LibfuzzerNeedsNonemptyProtocolCompleterBase
      : public ::fidl::CompleterBase {
   public:
    // In the following methods, the return value indicates internal errors
    // during the reply, such as encoding or writing to the transport. Note that
    // any error will automatically lead to the destruction of the binding,
    // after which the |on_unbound| callback will be triggered with a detailed
    // reason.
    //
    // See //zircon/system/ulib/fidl/include/lib/fidl/llcpp/server.h.
    //
    // Because the reply status is identical to the unbinding status, it can be
    // safely ignored.
    ::fidl::Result Reply();

   protected:
    using ::fidl::CompleterBase::CompleterBase;
  };
  using LibfuzzerNeedsNonemptyProtocolCompleter =
      ::fidl::Completer<LibfuzzerNeedsNonemptyProtocolCompleterBase>;
  class LibfuzzerNeedsNonemptyProtocolRequestView {
   public:
    LibfuzzerNeedsNonemptyProtocolRequestView(
        ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                                LibfuzzerNeedsNonemptyProtocol>* request)
        : request_(request) {}
    ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                            LibfuzzerNeedsNonemptyProtocol>*
    operator->() const {
      return request_;
    }

   private:
    ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                            LibfuzzerNeedsNonemptyProtocol>* request_;
  };

  virtual void LibfuzzerNeedsNonemptyProtocol(
      LibfuzzerNeedsNonemptyProtocolRequestView request,
      LibfuzzerNeedsNonemptyProtocolCompleter::Sync& _completer) = 0;

 private:
  ::fidl::DispatchResult dispatch_message(fidl_incoming_msg_t* msg,
                                          ::fidl::Transaction* txn) final;
};

// Pure-virtual interface to be implemented by a server.
// This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
// and |fidl::ServerEnd<SomeProtocol>|).
template <>
class ::fidl::WireInterface<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    : public ::fidl::internal::IncomingMessageDispatcher {
 public:
  WireInterface() = default;
  virtual ~WireInterface() = default;

  // The marker protocol type within which this |WireInterface| class is
  // defined.
  using _EnclosingProtocol = ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps;

  using LibfuzzerNeedsNonemptyProtocolCompleterBase =
      ::fidl::WireServer<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>::
          LibfuzzerNeedsNonemptyProtocolCompleterBase;

  using LibfuzzerNeedsNonemptyProtocolCompleter =
      ::fidl::WireServer<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>::
          LibfuzzerNeedsNonemptyProtocolCompleter;
  virtual void LibfuzzerNeedsNonemptyProtocol(
      LibfuzzerNeedsNonemptyProtocolCompleter::Sync& _completer) = 0;

 private:
  ::fidl::DispatchResult dispatch_message(fidl_incoming_msg_t* msg,
                                          ::fidl::Transaction* txn) final;
};

namespace fidl_test_bindingsdenylist {
class OnlyCppAndDeps final {
  OnlyCppAndDeps() = delete;

 public:
};
}  // namespace fidl_test_bindingsdenylist
#ifdef __Fuchsia__

template <>
struct ::fidl::internal::ProtocolDetails<
    ::fidl_test_bindingsdenylist::OnlyCppAndDeps> {};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct ::fidl::internal::WireDispatcher<
    ::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    final {
  WireDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireInterface<::fidl_test_bindingsdenylist::OnlyCppAndDeps>* impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
  static ::fidl::DispatchResult Dispatch(
      ::fidl::WireInterface<::fidl_test_bindingsdenylist::OnlyCppAndDeps>* impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
};

template <>
struct ::fidl::internal::WireServerDispatcher<
    ::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    final {
  WireServerDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireServer<::fidl_test_bindingsdenylist::OnlyCppAndDeps>* impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
  static ::fidl::DispatchResult Dispatch(
      ::fidl::WireServer<::fidl_test_bindingsdenylist::OnlyCppAndDeps>* impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
};
#endif  // __Fuchsia__

// Methods to make a sync FIDL call directly on an unowned channel or a
// const reference to a
// |fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>|, avoiding
// setting up a client.
template <>
class ::fidl::internal::WireCaller<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    final {
 public:
  explicit WireCaller(
      ::fidl::UnownedClientEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
          client_end)
      : client_end_(client_end) {}

 private:
  ::fidl::UnownedClientEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
      client_end_;
};
#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireEventHandlerInterface<
    ::fidl_test_bindingsdenylist::OnlyCppAndDeps> {
 public:
  WireEventHandlerInterface() = default;
  virtual ~WireEventHandlerInterface() = default;
};

template <>
class ::fidl::WireAsyncEventHandler<
    ::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_bindingsdenylist::OnlyCppAndDeps> {
 public:
  WireAsyncEventHandler() = default;

  virtual void Unbound(::fidl::UnbindInfo info) {}
};

template <>
class ::fidl::WireSyncEventHandler<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_bindingsdenylist::OnlyCppAndDeps> {
 public:
  WireSyncEventHandler() = default;

  // Method called when an unknown event is found. This methods gives the status
  // which, in this case, is returned by HandleOneEvent.
  virtual zx_status_t Unknown() = 0;

  // Handle all possible events defined in this protocol.
  // Blocks to consume exactly one message from the channel, then call the
  // corresponding virtual method.
  ::fidl::Result HandleOneEvent(
      ::fidl::UnownedClientEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
          client_end);
};
#endif  // __Fuchsia__

template <>
class ::fidl::WireSyncClient<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    final {
 public:
  WireSyncClient() = default;

  explicit WireSyncClient(
      ::fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
          client_end)
      : client_end_(std::move(client_end)) {}

  ~WireSyncClient() = default;
  WireSyncClient(WireSyncClient&&) = default;
  WireSyncClient& operator=(WireSyncClient&&) = default;

  const ::fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>&
  client_end() const {
    return client_end_;
  }
  ::fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>&
  client_end() {
    return client_end_;
  }

  const ::zx::channel& channel() const { return client_end_.channel(); }
  ::zx::channel* mutable_channel() { return &client_end_.channel(); }

 private:
  ::fidl::ClientEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps> client_end_;
};

// Pure-virtual interface to be implemented by a server.
// This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
// and |fidl::ServerEnd<SomeProtocol>|).
template <>
class ::fidl::WireServer<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    : public ::fidl::internal::IncomingMessageDispatcher {
 public:
  WireServer() = default;
  virtual ~WireServer() = default;

  // The FIDL protocol type that is implemented by this server.
  using _EnclosingProtocol = ::fidl_test_bindingsdenylist::OnlyCppAndDeps;

 private:
  ::fidl::DispatchResult dispatch_message(fidl_incoming_msg_t* msg,
                                          ::fidl::Transaction* txn) final;
};

// Pure-virtual interface to be implemented by a server.
// This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
// and |fidl::ServerEnd<SomeProtocol>|).
template <>
class ::fidl::WireInterface<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    : public ::fidl::internal::IncomingMessageDispatcher {
 public:
  WireInterface() = default;
  virtual ~WireInterface() = default;

  // The marker protocol type within which this |WireInterface| class is
  // defined.
  using _EnclosingProtocol = ::fidl_test_bindingsdenylist::OnlyCppAndDeps;

 private:
  ::fidl::DispatchResult dispatch_message(fidl_incoming_msg_t* msg,
                                          ::fidl::Transaction* txn) final;
};

namespace fidl_test_bindingsdenylist {
namespace wire {

constexpr uint32_t kAllBindings = 0u;

}  // namespace wire
}  // namespace fidl_test_bindingsdenylist
namespace fidl {

template <>
struct IsFidlType<
    ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                            LibfuzzerNeedsNonemptyProtocol>>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                            LibfuzzerNeedsNonemptyProtocol>>
    : public std::true_type {};
static_assert(
    sizeof(
        ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                                LibfuzzerNeedsNonemptyProtocol>) ==
    ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                            LibfuzzerNeedsNonemptyProtocol>::PrimarySize);

template <>
struct IsFidlType<
    ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                             LibfuzzerNeedsNonemptyProtocol>>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                             LibfuzzerNeedsNonemptyProtocol>>
    : public std::true_type {};
static_assert(
    sizeof(::fidl::WireResponse<
           ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
               LibfuzzerNeedsNonemptyProtocol>) ==
    ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                             LibfuzzerNeedsNonemptyProtocol>::PrimarySize);

template <>
struct IsFidlType<::fidl_test_bindingsdenylist::wire::OnlyLlcpp>
    : public std::true_type {};
template <>
struct IsUnion<::fidl_test_bindingsdenylist::wire::OnlyLlcpp>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_bindingsdenylist::wire::OnlyLlcpp>);
}  // namespace fidl
#ifdef __Fuchsia__

template <>
class ::fidl::WireResponseContext<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
        LibfuzzerNeedsNonemptyProtocol>
    : public ::fidl::internal::ResponseContext {
 public:
  WireResponseContext();

  virtual void OnReply(
      ::fidl::WireResponse<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                               LibfuzzerNeedsNonemptyProtocol>* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireClientImpl<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
    final : private ::fidl::internal::ClientBase {
 public:
  // Asynchronous variant of
  // |OnlyLibfuzzerAndDeps.LibfuzzerNeedsNonemptyProtocol()|. Allocates 16 bytes
  // of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result LibfuzzerNeedsNonemptyProtocol(
      ::fit::callback<void(::fidl::WireResponse<
                           ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                               LibfuzzerNeedsNonemptyProtocol>* response)>
          _cb);

  // Asynchronous variant of
  // |OnlyLibfuzzerAndDeps.LibfuzzerNeedsNonemptyProtocol()|. Caller provides
  // the backing storage for FIDL message via request buffer. Ownership of
  // |_context| is given unsafely to the binding until |OnError| or |OnReply|
  // are called on it.
  ::fidl::Result LibfuzzerNeedsNonemptyProtocol(
      ::fidl::WireResponseContext<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
              LibfuzzerNeedsNonemptyProtocol>* _context);

  // Synchronous variant of
  // |OnlyLibfuzzerAndDeps.LibfuzzerNeedsNonemptyProtocol()|. Allocates 32 bytes
  // of message buffer on the stack. No heap allocation necessary.
  ::fidl::WireResult<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                         LibfuzzerNeedsNonemptyProtocol>
  LibfuzzerNeedsNonemptyProtocol_Sync();

  ::fidl::WireAsyncEventHandler<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>*
  event_handler() const {
    return event_handler_.get();
  }

 private:
  friend class ::fidl::Client<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>;
  friend class ::fidl::internal::ControlBlock<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>;

  explicit WireClientImpl(
      std::shared_ptr<::fidl::WireAsyncEventHandler<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>>
          event_handler)
      : event_handler_(std::move(event_handler)) {}

  std::optional<::fidl::UnbindInfo> DispatchEvent(
      fidl_incoming_msg_t* msg) override;

  std::shared_ptr<::fidl::WireAsyncEventHandler<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>>
      event_handler_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__
// |EventSender| owns a server endpoint of a channel speaking
// the OnlyLibfuzzerAndDeps protocol, and can send events in that protocol.
template <>
class ::fidl::WireEventSender<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps> {
 public:
  // Constructs an event sender with an invalid channel.
  WireEventSender() = default;

  explicit WireEventSender(
      ::fidl::ServerEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
          server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::fidl::ServerEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>&
  server_end() const {
    return server_end_;
  }
  ::fidl::ServerEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>&
  server_end() {
    return server_end_;
  }

  const ::zx::channel& channel() const { return server_end_.channel(); }
  ::zx::channel& channel() { return server_end_.channel(); }

  // Whether the underlying channel is valid.
  bool is_valid() const { return server_end_.is_valid(); }

 private:
  ::fidl::ServerEnd<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
      server_end_;
};

template <>
class ::fidl::internal::WireWeakEventSender<
    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps> {
 public:
 private:
  friend class ::fidl::ServerBindingRef<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>;

  explicit WireWeakEventSender(
      std::weak_ptr<::fidl::internal::AsyncServerBinding<
          ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>>
          binding)
      : binding_(std::move(binding)) {}

  std::weak_ptr<::fidl::internal::AsyncServerBinding<
      ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>>
      binding_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireClientImpl<
    ::fidl_test_bindingsdenylist::OnlyCppAndDeps>
    final : private ::fidl::internal::ClientBase {
 public:
  ::fidl::WireAsyncEventHandler<::fidl_test_bindingsdenylist::OnlyCppAndDeps>*
  event_handler() const {
    return event_handler_.get();
  }

 private:
  friend class ::fidl::Client<::fidl_test_bindingsdenylist::OnlyCppAndDeps>;
  friend class ::fidl::internal::ControlBlock<
      ::fidl_test_bindingsdenylist::OnlyCppAndDeps>;

  explicit WireClientImpl(std::shared_ptr<::fidl::WireAsyncEventHandler<
                              ::fidl_test_bindingsdenylist::OnlyCppAndDeps>>
                              event_handler)
      : event_handler_(std::move(event_handler)) {}

  std::optional<::fidl::UnbindInfo> DispatchEvent(
      fidl_incoming_msg_t* msg) override;

  std::shared_ptr<::fidl::WireAsyncEventHandler<
      ::fidl_test_bindingsdenylist::OnlyCppAndDeps>>
      event_handler_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__
// |EventSender| owns a server endpoint of a channel speaking
// the OnlyCppAndDeps protocol, and can send events in that protocol.
template <>
class ::fidl::WireEventSender<::fidl_test_bindingsdenylist::OnlyCppAndDeps> {
 public:
  // Constructs an event sender with an invalid channel.
  WireEventSender() = default;

  explicit WireEventSender(
      ::fidl::ServerEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>
          server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::fidl::ServerEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>&
  server_end() const {
    return server_end_;
  }
  ::fidl::ServerEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps>&
  server_end() {
    return server_end_;
  }

  const ::zx::channel& channel() const { return server_end_.channel(); }
  ::zx::channel& channel() { return server_end_.channel(); }

  // Whether the underlying channel is valid.
  bool is_valid() const { return server_end_.is_valid(); }

 private:
  ::fidl::ServerEnd<::fidl_test_bindingsdenylist::OnlyCppAndDeps> server_end_;
};

template <>
class ::fidl::internal::WireWeakEventSender<
    ::fidl_test_bindingsdenylist::OnlyCppAndDeps> {
 public:
 private:
  friend class ::fidl::ServerBindingRef<
      ::fidl_test_bindingsdenylist::OnlyCppAndDeps>;

  explicit WireWeakEventSender(
      std::weak_ptr<::fidl::internal::AsyncServerBinding<
          ::fidl_test_bindingsdenylist::OnlyCppAndDeps>>
          binding)
      : binding_(std::move(binding)) {}

  std::weak_ptr<::fidl::internal::AsyncServerBinding<
      ::fidl_test_bindingsdenylist::OnlyCppAndDeps>>
      binding_;
};
#endif  // __Fuchsia__
