// 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/buffer_allocator.h>
#include <lib/fidl/llcpp/buffer_then_heap_allocator.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/fidl/llcpp/envelope.h>
#include <lib/fidl/llcpp/errors.h>
#include <lib/fidl/llcpp/memory.h>
#include <lib/fidl/llcpp/message.h>
#include <lib/fidl/llcpp/message_storage.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/tracking_ptr.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fit/function.h>
#include <lib/fit/optional.h>

#include <variant>
#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/result.h>
#include <lib/fidl/llcpp/server.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/txn_header.h>
#include <lib/zx/channel.h>
#include <lib/zx/handle.h>
#include <lib/zx/socket.h>
#endif  // __Fuchsia__
#include <zircon/fidl.h>

namespace llcpp {

namespace fidl {
namespace test {
namespace protocols {

enum class obj_type : uint32_t {

  NONE = 0u,

  SOCKET = 14u,
};

struct WithErrorSyntax_ResponseAsStruct_Response;
class WithErrorSyntax_ResponseAsStruct_Result;
struct WithErrorSyntax_ErrorAsPrimitive_Response;
class WithErrorSyntax_ErrorAsPrimitive_Result;
struct WithErrorSyntax_ErrorAsEnum_Response;
class Transitional;
class ChannelProtocol;
class WithAndWithoutRequestResponse;

enum class ErrorEnun : uint32_t {

  ERR_FOO = 1u,

  ERR_BAR = 2u,
};

class WithErrorSyntax_ErrorAsEnum_Result;
class WithErrorSyntax;

extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntax_ResponseAsStruct_ResultTable;

class WithErrorSyntax_ResponseAsStruct_Result {
 public:
  WithErrorSyntax_ResponseAsStruct_Result()
      : ordinal_(Ordinal::Invalid), envelope_{} {}

  WithErrorSyntax_ResponseAsStruct_Result(
      WithErrorSyntax_ResponseAsStruct_Result&&) = default;
  WithErrorSyntax_ResponseAsStruct_Result& operator=(
      WithErrorSyntax_ResponseAsStruct_Result&&) = default;

  ~WithErrorSyntax_ResponseAsStruct_Result() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kResponse = 1,  // 0x1
    kErr = 2,       // 0x2
  };

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

  bool is_response() const { return ordinal_ == Ordinal::kResponse; }

  static WithErrorSyntax_ResponseAsStruct_Result WithResponse(
      ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::
                               WithErrorSyntax_ResponseAsStruct_Response>&&
          val) {
    WithErrorSyntax_ResponseAsStruct_Result result;
    result.set_response(std::move(val));
    return result;
  }

  void set_response(::fidl::tracking_ptr<
                    ::llcpp::fidl::test::protocols::
                        WithErrorSyntax_ResponseAsStruct_Response>&& elem) {
    ordinal_ = Ordinal::kResponse;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Response&
  mutable_response() {
    ZX_ASSERT(ordinal_ == Ordinal::kResponse);
    return *static_cast<::llcpp::fidl::test::protocols::
                            WithErrorSyntax_ResponseAsStruct_Response*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::protocols::
      WithErrorSyntax_ResponseAsStruct_Response&
      response() const {
    ZX_ASSERT(ordinal_ == Ordinal::kResponse);
    return *static_cast<::llcpp::fidl::test::protocols::
                            WithErrorSyntax_ResponseAsStruct_Response*>(
        envelope_.data.get());
  }

  bool is_err() const { return ordinal_ == Ordinal::kErr; }

  static WithErrorSyntax_ResponseAsStruct_Result WithErr(
      ::fidl::tracking_ptr<uint32_t>&& val) {
    WithErrorSyntax_ResponseAsStruct_Result result;
    result.set_err(std::move(val));
    return result;
  }

  void set_err(::fidl::tracking_ptr<uint32_t>&& elem) {
    ordinal_ = Ordinal::kErr;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  uint32_t& mutable_err() {
    ZX_ASSERT(ordinal_ == Ordinal::kErr);
    return *static_cast<uint32_t*>(envelope_.data.get());
  }
  const uint32_t& err() const {
    ZX_ASSERT(ordinal_ == Ordinal::kErr);
    return *static_cast<uint32_t*>(envelope_.data.get());
  }
  Tag which() const {
    ZX_ASSERT(!has_invalid_tag());
    return static_cast<Tag>(ordinal_);
  }

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

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kResponse = 1,  // 0x1
    kErr = 2,       // 0x2
  };

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::
                                 WithErrorSyntax_ResponseAsStruct_Response>
            to_destroy = static_cast<::fidl::tracking_ptr<
                ::llcpp::fidl::test::protocols::
                    WithErrorSyntax_ResponseAsStruct_Response>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::fidl::tracking_ptr<uint32_t> to_destroy =
            static_cast<::fidl::tracking_ptr<uint32_t>>(
                std::move(envelope_.data));
        break;
      }
    }

    envelope_.data = std::move(new_ptr);
  }

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

extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntax_ErrorAsPrimitive_ResultTable;

class WithErrorSyntax_ErrorAsPrimitive_Result {
 public:
  WithErrorSyntax_ErrorAsPrimitive_Result()
      : ordinal_(Ordinal::Invalid), envelope_{} {}

  WithErrorSyntax_ErrorAsPrimitive_Result(
      WithErrorSyntax_ErrorAsPrimitive_Result&&) = default;
  WithErrorSyntax_ErrorAsPrimitive_Result& operator=(
      WithErrorSyntax_ErrorAsPrimitive_Result&&) = default;

  ~WithErrorSyntax_ErrorAsPrimitive_Result() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kResponse = 1,  // 0x1
    kErr = 2,       // 0x2
  };

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

  bool is_response() const { return ordinal_ == Ordinal::kResponse; }

  static WithErrorSyntax_ErrorAsPrimitive_Result WithResponse(
      ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::
                               WithErrorSyntax_ErrorAsPrimitive_Response>&&
          val) {
    WithErrorSyntax_ErrorAsPrimitive_Result result;
    result.set_response(std::move(val));
    return result;
  }

  void set_response(::fidl::tracking_ptr<
                    ::llcpp::fidl::test::protocols::
                        WithErrorSyntax_ErrorAsPrimitive_Response>&& elem) {
    ordinal_ = Ordinal::kResponse;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Response&
  mutable_response() {
    ZX_ASSERT(ordinal_ == Ordinal::kResponse);
    return *static_cast<::llcpp::fidl::test::protocols::
                            WithErrorSyntax_ErrorAsPrimitive_Response*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::protocols::
      WithErrorSyntax_ErrorAsPrimitive_Response&
      response() const {
    ZX_ASSERT(ordinal_ == Ordinal::kResponse);
    return *static_cast<::llcpp::fidl::test::protocols::
                            WithErrorSyntax_ErrorAsPrimitive_Response*>(
        envelope_.data.get());
  }

  bool is_err() const { return ordinal_ == Ordinal::kErr; }

  static WithErrorSyntax_ErrorAsPrimitive_Result WithErr(
      ::fidl::tracking_ptr<uint32_t>&& val) {
    WithErrorSyntax_ErrorAsPrimitive_Result result;
    result.set_err(std::move(val));
    return result;
  }

  void set_err(::fidl::tracking_ptr<uint32_t>&& elem) {
    ordinal_ = Ordinal::kErr;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  uint32_t& mutable_err() {
    ZX_ASSERT(ordinal_ == Ordinal::kErr);
    return *static_cast<uint32_t*>(envelope_.data.get());
  }
  const uint32_t& err() const {
    ZX_ASSERT(ordinal_ == Ordinal::kErr);
    return *static_cast<uint32_t*>(envelope_.data.get());
  }
  Tag which() const {
    ZX_ASSERT(!has_invalid_tag());
    return static_cast<Tag>(ordinal_);
  }

  static constexpr const fidl_type_t* Type =
      &fidl_test_protocols_WithErrorSyntax_ErrorAsPrimitive_ResultTable;
  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,
    kResponse = 1,  // 0x1
    kErr = 2,       // 0x2
  };

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::
                                 WithErrorSyntax_ErrorAsPrimitive_Response>
            to_destroy = static_cast<::fidl::tracking_ptr<
                ::llcpp::fidl::test::protocols::
                    WithErrorSyntax_ErrorAsPrimitive_Response>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::fidl::tracking_ptr<uint32_t> to_destroy =
            static_cast<::fidl::tracking_ptr<uint32_t>>(
                std::move(envelope_.data));
        break;
      }
    }

    envelope_.data = std::move(new_ptr);
  }

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

extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntax_ErrorAsEnum_ResultTable;

class WithErrorSyntax_ErrorAsEnum_Result {
 public:
  WithErrorSyntax_ErrorAsEnum_Result()
      : ordinal_(Ordinal::Invalid), envelope_{} {}

  WithErrorSyntax_ErrorAsEnum_Result(WithErrorSyntax_ErrorAsEnum_Result&&) =
      default;
  WithErrorSyntax_ErrorAsEnum_Result& operator=(
      WithErrorSyntax_ErrorAsEnum_Result&&) = default;

  ~WithErrorSyntax_ErrorAsEnum_Result() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kResponse = 1,  // 0x1
    kErr = 2,       // 0x2
  };

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

  bool is_response() const { return ordinal_ == Ordinal::kResponse; }

  static WithErrorSyntax_ErrorAsEnum_Result WithResponse(
      ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::
                               WithErrorSyntax_ErrorAsEnum_Response>&& val) {
    WithErrorSyntax_ErrorAsEnum_Result result;
    result.set_response(std::move(val));
    return result;
  }

  void set_response(
      ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::
                               WithErrorSyntax_ErrorAsEnum_Response>&& elem) {
    ordinal_ = Ordinal::kResponse;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response&
  mutable_response() {
    ZX_ASSERT(ordinal_ == Ordinal::kResponse);
    return *static_cast<
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response&
  response() const {
    ZX_ASSERT(ordinal_ == Ordinal::kResponse);
    return *static_cast<
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response*>(
        envelope_.data.get());
  }

  bool is_err() const { return ordinal_ == Ordinal::kErr; }

  static WithErrorSyntax_ErrorAsEnum_Result WithErr(
      ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::ErrorEnun>&& val) {
    WithErrorSyntax_ErrorAsEnum_Result result;
    result.set_err(std::move(val));
    return result;
  }

  void set_err(
      ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::ErrorEnun>&& elem) {
    ordinal_ = Ordinal::kErr;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::protocols::ErrorEnun& mutable_err() {
    ZX_ASSERT(ordinal_ == Ordinal::kErr);
    return *static_cast<::llcpp::fidl::test::protocols::ErrorEnun*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::protocols::ErrorEnun& err() const {
    ZX_ASSERT(ordinal_ == Ordinal::kErr);
    return *static_cast<::llcpp::fidl::test::protocols::ErrorEnun*>(
        envelope_.data.get());
  }
  Tag which() const {
    ZX_ASSERT(!has_invalid_tag());
    return static_cast<Tag>(ordinal_);
  }

  static constexpr const fidl_type_t* Type =
      &fidl_test_protocols_WithErrorSyntax_ErrorAsEnum_ResultTable;
  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,
    kResponse = 1,  // 0x1
    kErr = 2,       // 0x2
  };

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::
                                 WithErrorSyntax_ErrorAsEnum_Response>
            to_destroy = static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::
                                         WithErrorSyntax_ErrorAsEnum_Response>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::protocols::ErrorEnun>
            to_destroy = static_cast<::fidl::tracking_ptr<
                ::llcpp::fidl::test::protocols::ErrorEnun>>(
                std::move(envelope_.data));
        break;
      }
    }

    envelope_.data = std::move(new_ptr);
  }

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

extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntax_ResponseAsStruct_ResponseTable;

struct WithErrorSyntax_ResponseAsStruct_Response {
  static constexpr const fidl_type_t* Type =
      &fidl_test_protocols_WithErrorSyntax_ResponseAsStruct_ResponseTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 0;
  static constexpr bool HasPointer = false;

  int64_t a = {};

  int64_t b = {};

  int64_t c = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          WithErrorSyntax_ResponseAsStruct_Response* value)
        : message_(bytes, byte_size,
                   sizeof(WithErrorSyntax_ResponseAsStruct_Response), nullptr,
                   0, 0) {
      message_.LinearizeAndEncode<WithErrorSyntax_ResponseAsStruct_Response>(
          value);
    }
    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
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

   private:
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(
        WithErrorSyntax_ResponseAsStruct_Response* value)
        : message_(bytes_, sizeof(bytes_), value) {}
    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
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }

   private:
    FIDL_ALIGNDECL
    uint8_t bytes_[FIDL_ALIGN(PrimarySize + MaxOutOfLine)];
    UnownedEncodedMessage message_;
  };

  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<struct WithErrorSyntax_ResponseAsStruct_Response>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct WithErrorSyntax_ResponseAsStruct_Response>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    struct WithErrorSyntax_ResponseAsStruct_Response* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<
          struct WithErrorSyntax_ResponseAsStruct_Response*>(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(); }

    // These methods should only be used for testing purpose.
    // They create an DecodedMessage using the bytes of an outgoing message and
    // copying the handles.
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        UnownedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        OwnedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }

   private:
    DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
      Init(outgoing_message, nullptr, 0);
      if (ok()) {
        Decode<struct WithErrorSyntax_ResponseAsStruct_Response>();
      }
    }
  };
};

extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntax_ErrorAsPrimitive_ResponseTable;

struct WithErrorSyntax_ErrorAsPrimitive_Response {
  static constexpr const fidl_type_t* Type =
      &fidl_test_protocols_WithErrorSyntax_ErrorAsPrimitive_ResponseTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 1;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 0;
  static constexpr bool HasPointer = false;

  uint8_t __reserved = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          WithErrorSyntax_ErrorAsPrimitive_Response* value)
        : message_(bytes, byte_size,
                   sizeof(WithErrorSyntax_ErrorAsPrimitive_Response), nullptr,
                   0, 0) {
      message_.LinearizeAndEncode<WithErrorSyntax_ErrorAsPrimitive_Response>(
          value);
    }
    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
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

   private:
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(
        WithErrorSyntax_ErrorAsPrimitive_Response* value)
        : message_(bytes_, sizeof(bytes_), value) {}
    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
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }

   private:
    FIDL_ALIGNDECL
    uint8_t bytes_[FIDL_ALIGN(PrimarySize + MaxOutOfLine)];
    UnownedEncodedMessage message_;
  };

  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<struct WithErrorSyntax_ErrorAsPrimitive_Response>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct WithErrorSyntax_ErrorAsPrimitive_Response>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    struct WithErrorSyntax_ErrorAsPrimitive_Response* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<
          struct WithErrorSyntax_ErrorAsPrimitive_Response*>(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(); }

    // These methods should only be used for testing purpose.
    // They create an DecodedMessage using the bytes of an outgoing message and
    // copying the handles.
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        UnownedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        OwnedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }

   private:
    DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
      Init(outgoing_message, nullptr, 0);
      if (ok()) {
        Decode<struct WithErrorSyntax_ErrorAsPrimitive_Response>();
      }
    }
  };
};

extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntax_ErrorAsEnum_ResponseTable;

struct WithErrorSyntax_ErrorAsEnum_Response {
  static constexpr const fidl_type_t* Type =
      &fidl_test_protocols_WithErrorSyntax_ErrorAsEnum_ResponseTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 1;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 0;
  static constexpr bool HasPointer = false;

  uint8_t __reserved = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          WithErrorSyntax_ErrorAsEnum_Response* value)
        : message_(bytes, byte_size,
                   sizeof(WithErrorSyntax_ErrorAsEnum_Response), nullptr, 0,
                   0) {
      message_.LinearizeAndEncode<WithErrorSyntax_ErrorAsEnum_Response>(value);
    }
    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
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

   private:
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(WithErrorSyntax_ErrorAsEnum_Response* value)
        : message_(bytes_, sizeof(bytes_), value) {}
    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
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }

   private:
    FIDL_ALIGNDECL
    uint8_t bytes_[FIDL_ALIGN(PrimarySize + MaxOutOfLine)];
    UnownedEncodedMessage message_;
  };

  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<struct WithErrorSyntax_ErrorAsEnum_Response>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct WithErrorSyntax_ErrorAsEnum_Response>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    struct WithErrorSyntax_ErrorAsEnum_Response* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<struct WithErrorSyntax_ErrorAsEnum_Response*>(
          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(); }

    // These methods should only be used for testing purpose.
    // They create an DecodedMessage using the bytes of an outgoing message and
    // copying the handles.
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        UnownedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        OwnedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }

   private:
    DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
      Init(outgoing_message, nullptr, 0);
      if (ok()) {
        Decode<struct WithErrorSyntax_ErrorAsEnum_Response>();
      }
    }
  };
};

extern "C" const fidl_type_t
    fidl_test_protocols_TransitionalRequestRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_TransitionalRequestResponseTable;
extern "C" const fidl_type_t fidl_test_protocols_TransitionalOneWayRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_TransitionalOneWayResponseTable;
extern "C" const fidl_type_t fidl_test_protocols_TransitionalEventRequestTable;
extern "C" const fidl_type_t fidl_test_protocols_TransitionalEventEventTable;

class Transitional final {
  Transitional() = delete;

 public:
  struct RequestResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    int64_t y;
    explicit RequestResponse(int64_t y) : y(y) { _InitHeader(); }
    RequestResponse() { _InitHeader(); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_TransitionalRequestResponseTable;
    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 ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size, int64_t y)
          : message_(_bytes, _byte_size, sizeof(RequestResponse), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL RequestResponse _response{y};
        message_.LinearizeAndEncode<RequestResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            RequestResponse* response)
          : message_(bytes, byte_size, sizeof(RequestResponse), nullptr, 0, 0) {
        message_.LinearizeAndEncode<RequestResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      RequestResponse& Message() {
        return *reinterpret_cast<RequestResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(int64_t y)
          : message_(bytes_, sizeof(bytes_), y) {}
      explicit OwnedEncodedMessage(RequestResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<RequestResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<RequestResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      RequestResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<RequestResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<RequestResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct RequestRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    int64_t x;
    explicit RequestRequest(zx_txid_t _txid, int64_t x) : x(x) {
      _InitHeader(_txid);
    }
    explicit RequestRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_TransitionalRequestRequestTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 24;
    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;
    using ResponseType = RequestResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, int64_t x)
          : message_(_bytes, _byte_size, sizeof(RequestRequest), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL RequestRequest _request(_txid, x);
        message_.LinearizeAndEncode<RequestRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            RequestRequest* request)
          : message_(bytes, byte_size, sizeof(RequestRequest), nullptr, 0, 0) {
        message_.LinearizeAndEncode<RequestRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      RequestRequest& Message() {
        return *reinterpret_cast<RequestRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid, int64_t x)
          : message_(bytes_, sizeof(bytes_), _txid, x) {}
      explicit OwnedEncodedMessage(RequestRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<RequestRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<RequestRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      RequestRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<RequestRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<RequestRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct OneWayRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    int64_t x;
    explicit OneWayRequest(zx_txid_t _txid, int64_t x) : x(x) {
      _InitHeader(_txid);
    }
    explicit OneWayRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_TransitionalOneWayRequestTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 24;
    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* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, int64_t x)
          : message_(_bytes, _byte_size, sizeof(OneWayRequest), nullptr, 0, 0) {
        FIDL_ALIGNDECL OneWayRequest _request(_txid, x);
        message_.LinearizeAndEncode<OneWayRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            OneWayRequest* request)
          : message_(bytes, byte_size, sizeof(OneWayRequest), nullptr, 0, 0) {
        message_.LinearizeAndEncode<OneWayRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      OneWayRequest& Message() {
        return *reinterpret_cast<OneWayRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid, int64_t x)
          : message_(bytes_, sizeof(bytes_), _txid, x) {}
      explicit OwnedEncodedMessage(OneWayRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<OneWayRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<OneWayRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      OneWayRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<OneWayRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<OneWayRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct EventResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    int64_t x;
    explicit EventResponse(int64_t x) : x(x) { _InitHeader(); }
    EventResponse() { _InitHeader(); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_TransitionalEventEventTable;
    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 ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size, int64_t x)
          : message_(_bytes, _byte_size, sizeof(EventResponse), nullptr, 0, 0) {
        FIDL_ALIGNDECL EventResponse _response{x};
        message_.LinearizeAndEncode<EventResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            EventResponse* response)
          : message_(bytes, byte_size, sizeof(EventResponse), nullptr, 0, 0) {
        message_.LinearizeAndEncode<EventResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      EventResponse& Message() {
        return *reinterpret_cast<EventResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(int64_t x)
          : message_(bytes_, sizeof(bytes_), x) {}
      explicit OwnedEncodedMessage(EventResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<EventResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<EventResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      EventResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<EventResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<EventResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };

  class EventHandler {
   public:
    EventHandler() = default;
    virtual ~EventHandler() = default;
    virtual void Event(EventResponse* event) {
      ZX_PANIC("Got event Event which is marked as [Transitional].");
    }

    // 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(::zx::unowned_channel client_end);
  };

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

   public:
    class Request final : public ::fidl::Result {
     public:
      explicit Request(zx_handle_t _client, int64_t x);
      Request(zx_handle_t _client, int64_t x, zx_time_t _deadline);
      explicit Request(const ::fidl::Result& result) : ::fidl::Result(result) {}
      Request(Request&&) = delete;
      Request(const Request&) = delete;
      Request* operator=(Request&&) = delete;
      Request* operator=(const Request&) = delete;
      ~Request() = default;

      RequestResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<RequestResponse*>(bytes_);
      }
      const RequestResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const RequestResponse*>(bytes_);
      }

      RequestResponse& value() { return *Unwrap(); }
      const RequestResponse& value() const { return *Unwrap(); }

      RequestResponse* operator->() { return &value(); }
      const RequestResponse* operator->() const { return &value(); }

      RequestResponse& operator*() { return value(); }
      const RequestResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t
          bytes_[RequestResponse::PrimarySize + RequestResponse::MaxOutOfLine];
    };
    class OneWay final : public ::fidl::Result {
     public:
      explicit OneWay(zx_handle_t _client, int64_t x);
      explicit OneWay(const ::fidl::Result& result) : ::fidl::Result(result) {}
      OneWay(OneWay&&) = delete;
      OneWay(const OneWay&) = delete;
      OneWay* operator=(OneWay&&) = delete;
      OneWay* operator=(const OneWay&) = delete;
      ~OneWay() = default;

     private:
    };
  };

  // 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;

   public:
    class Request final : public ::fidl::Result {
     public:
      explicit Request(zx_handle_t _client, uint8_t* _request_bytes,
                       uint32_t _request_byte_capacity, int64_t x,
                       uint8_t* _response_bytes,
                       uint32_t _response_byte_capacity);
      explicit Request(const ::fidl::Result& result) : ::fidl::Result(result) {}
      Request(Request&&) = delete;
      Request(const Request&) = delete;
      Request* operator=(Request&&) = delete;
      Request* operator=(const Request&) = delete;
      ~Request() = default;

      RequestResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<RequestResponse*>(bytes_);
      }
      const RequestResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const RequestResponse*>(bytes_);
      }

      RequestResponse& value() { return *Unwrap(); }
      const RequestResponse& value() const { return *Unwrap(); }

      RequestResponse* operator->() { return &value(); }
      const RequestResponse* operator->() const { return &value(); }

      RequestResponse& operator*() { return value(); }
      const RequestResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
    class OneWay final : public ::fidl::Result {
     public:
      explicit OneWay(zx_handle_t _client, uint8_t* _request_bytes,
                      uint32_t _request_byte_capacity, int64_t x);
      explicit OneWay(const ::fidl::Result& result) : ::fidl::Result(result) {}
      OneWay(OneWay&&) = delete;
      OneWay(const OneWay&) = delete;
      OneWay* operator=(OneWay&&) = delete;
      OneWay* operator=(const OneWay&) = delete;
      ~OneWay() = default;
    };
  };

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

   public:
    // Allocates 48 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::Request Request(::zx::unowned_channel _client_end,
                                     int64_t x) {
      return ResultOf::Request(_client_end->get(), x);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::Request Request(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        int64_t x, ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::Request(
          _client_end->get(), _request_buffer.data, _request_buffer.capacity, x,
          _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::OneWay OneWay(::zx::unowned_channel _client_end,
                                   int64_t x) {
      return ResultOf::OneWay(_client_end->get(), x);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::OneWay OneWay(::zx::unowned_channel _client_end,
                                          ::fidl::BufferSpan _request_buffer,
                                          int64_t x) {
      return UnownedResultOf::OneWay(_client_end->get(), _request_buffer.data,
                                     _request_buffer.capacity, x);
    }
  };

  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 48 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::Request Request(int64_t x) {
      return ResultOf::Request(this->channel().get(), x);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::Request Request(::fidl::BufferSpan _request_buffer,
                                     int64_t x,
                                     ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::Request(
          this->channel().get(), _request_buffer.data, _request_buffer.capacity,
          x, _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::OneWay OneWay(int64_t x) {
      return ResultOf::OneWay(this->channel().get(), x);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::OneWay OneWay(::fidl::BufferSpan _request_buffer,
                                   int64_t x) {
      return UnownedResultOf::OneWay(this->channel().get(),
                                     _request_buffer.data,
                                     _request_buffer.capacity, x);
    }

    // Handle all possible events defined in this protocol.
    // Blocks to consume exactly one message from the channel, then call the
    // corresponding virtual method defined in |EventHandler|. The return status
    // of the handler function is folded with any transport-level errors and
    // returned.
    ::fidl::Result HandleOneEvent(EventHandler& event_handler) {
      return event_handler.HandleOneEvent(::zx::unowned_channel(channel_));
    }

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

  struct AsyncEventHandlers;
  class RequestResponseContext;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  class Interface : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    Interface() = default;
    virtual ~Interface() = default;

    // The marker protocol type within which this |Interface| class is defined.
    using _EnclosingProtocol = Transitional;

    class RequestCompleterBase : 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(int64_t y);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer, int64_t y);

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

    using RequestCompleter = ::fidl::Completer<RequestCompleterBase>;

    virtual void Request(int64_t x, RequestCompleter::Sync& _completer) {
      _completer.Close(ZX_ERR_NOT_SUPPORTED);
    }

    using OneWayCompleter = ::fidl::Completer<>;

    virtual void OneWay(int64_t x, OneWayCompleter::Sync& _completer) {
      _completer.Close(ZX_ERR_NOT_SUPPORTED);
    }

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

  // 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 ::fidl::DispatchResult TryDispatch(Interface* impl,
                                            fidl_incoming_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 ::fidl::DispatchResult Dispatch(Interface* impl,
                                         fidl_incoming_msg_t* msg,
                                         ::fidl::Transaction* txn);

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

  class EventSender;
  class WeakEventSender;
};

extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolMethodARequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolMethodAResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolEventARequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolEventAEventTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolMethodBRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolMethodBResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolTakeHandleRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolTakeHandleResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolMutateSocketRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_ChannelProtocolMutateSocketResponseTable;

class ChannelProtocol final {
  ChannelProtocol() = delete;

 public:
  struct MethodARequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    int64_t a;
    int64_t b;
    explicit MethodARequest(zx_txid_t _txid, int64_t a, int64_t b)
        : a(a), b(b) {
      _InitHeader(_txid);
    }
    explicit MethodARequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_ChannelProtocolMethodARequestTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 32;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 32;
    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* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, int64_t a, int64_t b)
          : message_(_bytes, _byte_size, sizeof(MethodARequest), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL MethodARequest _request(_txid, a, b);
        message_.LinearizeAndEncode<MethodARequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            MethodARequest* request)
          : message_(bytes, byte_size, sizeof(MethodARequest), nullptr, 0, 0) {
        message_.LinearizeAndEncode<MethodARequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      MethodARequest& Message() {
        return *reinterpret_cast<MethodARequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid, int64_t a, int64_t b)
          : message_(bytes_, sizeof(bytes_), _txid, a, b) {}
      explicit OwnedEncodedMessage(MethodARequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<MethodARequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<MethodARequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      MethodARequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MethodARequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<MethodARequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct EventAResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    int64_t a;
    int64_t b;
    explicit EventAResponse(int64_t a, int64_t b) : a(a), b(b) {
      _InitHeader();
    }
    EventAResponse() { _InitHeader(); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_ChannelProtocolEventAEventTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 32;
    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* _bytes, uint32_t _byte_size, int64_t a,
                            int64_t b)
          : message_(_bytes, _byte_size, sizeof(EventAResponse), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL EventAResponse _response{a, b};
        message_.LinearizeAndEncode<EventAResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            EventAResponse* response)
          : message_(bytes, byte_size, sizeof(EventAResponse), nullptr, 0, 0) {
        message_.LinearizeAndEncode<EventAResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      EventAResponse& Message() {
        return *reinterpret_cast<EventAResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(int64_t a, int64_t b)
          : message_(bytes_, sizeof(bytes_), a, b) {}
      explicit OwnedEncodedMessage(EventAResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<EventAResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<EventAResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      EventAResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<EventAResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<EventAResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct MethodBResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    int64_t result;
    explicit MethodBResponse(int64_t result) : result(result) { _InitHeader(); }
    MethodBResponse() { _InitHeader(); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_ChannelProtocolMethodBResponseTable;
    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 ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            int64_t result)
          : message_(_bytes, _byte_size, sizeof(MethodBResponse), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL MethodBResponse _response{result};
        message_.LinearizeAndEncode<MethodBResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            MethodBResponse* response)
          : message_(bytes, byte_size, sizeof(MethodBResponse), nullptr, 0, 0) {
        message_.LinearizeAndEncode<MethodBResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      MethodBResponse& Message() {
        return *reinterpret_cast<MethodBResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(int64_t result)
          : message_(bytes_, sizeof(bytes_), result) {}
      explicit OwnedEncodedMessage(MethodBResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<MethodBResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<MethodBResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      MethodBResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MethodBResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<MethodBResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct MethodBRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    int64_t a;
    int64_t b;
    explicit MethodBRequest(zx_txid_t _txid, int64_t a, int64_t b)
        : a(a), b(b) {
      _InitHeader(_txid);
    }
    explicit MethodBRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_ChannelProtocolMethodBRequestTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 32;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 32;
    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;
    using ResponseType = MethodBResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, int64_t a, int64_t b)
          : message_(_bytes, _byte_size, sizeof(MethodBRequest), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL MethodBRequest _request(_txid, a, b);
        message_.LinearizeAndEncode<MethodBRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            MethodBRequest* request)
          : message_(bytes, byte_size, sizeof(MethodBRequest), nullptr, 0, 0) {
        message_.LinearizeAndEncode<MethodBRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      MethodBRequest& Message() {
        return *reinterpret_cast<MethodBRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid, int64_t a, int64_t b)
          : message_(bytes_, sizeof(bytes_), _txid, a, b) {}
      explicit OwnedEncodedMessage(MethodBRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<MethodBRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<MethodBRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      MethodBRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MethodBRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<MethodBRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct TakeHandleResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    TakeHandleResponse() { _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* _bytes, uint32_t _byte_size)
          : message_(_bytes, _byte_size, sizeof(TakeHandleResponse), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL TakeHandleResponse _response{};
        message_.LinearizeAndEncode<TakeHandleResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            TakeHandleResponse* response)
          : message_(bytes, byte_size, sizeof(TakeHandleResponse), nullptr, 0,
                     0) {
        message_.LinearizeAndEncode<TakeHandleResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      TakeHandleResponse& Message() {
        return *reinterpret_cast<TakeHandleResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage() : message_(bytes_, sizeof(bytes_)) {}
      explicit OwnedEncodedMessage(TakeHandleResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<TakeHandleResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<TakeHandleResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      TakeHandleResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<TakeHandleResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<TakeHandleResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct TakeHandleRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::handle h;
    explicit TakeHandleRequest(zx_txid_t _txid, ::zx::handle& h)
        : h(std::move(h)) {
      _InitHeader(_txid);
    }
    explicit TakeHandleRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_ChannelProtocolTakeHandleRequestTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 24;
    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;
    void _CloseHandles();

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, ::zx::handle& h)
          : message_(_bytes, _byte_size, sizeof(TakeHandleRequest), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        FIDL_ALIGNDECL TakeHandleRequest _request(_txid, h);
        message_.LinearizeAndEncode<TakeHandleRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            TakeHandleRequest* request)
          : message_(bytes, byte_size, sizeof(TakeHandleRequest), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        message_.LinearizeAndEncode<TakeHandleRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      TakeHandleRequest& Message() {
        return *reinterpret_cast<TakeHandleRequest*>(message_.bytes());
      }
      zx_handle_disposition_t
          handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid, ::zx::handle& h)
          : message_(bytes_, sizeof(bytes_), _txid, h) {}
      explicit OwnedEncodedMessage(TakeHandleRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<TakeHandleRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<TakeHandleRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;
      ~DecodedMessage() {
        if (ok() && (PrimaryObject() != nullptr)) {
          PrimaryObject()->_CloseHandles();
        }
      }

      TakeHandleRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<TakeHandleRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        zx_handle_info_t
            handles[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
        Init(outgoing_message, handles,
             std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles));
        if (ok()) {
          Decode<TakeHandleRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct MutateSocketResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::socket b;
    explicit MutateSocketResponse(::zx::socket& b) : b(std::move(b)) {
      _InitHeader();
    }
    MutateSocketResponse() { _InitHeader(); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_ChannelProtocolMutateSocketResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    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;
    void _CloseHandles();

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            ::zx::socket& b)
          : message_(_bytes, _byte_size, sizeof(MutateSocketResponse), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        FIDL_ALIGNDECL MutateSocketResponse _response{b};
        message_.LinearizeAndEncode<MutateSocketResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            MutateSocketResponse* response)
          : message_(bytes, byte_size, sizeof(MutateSocketResponse), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        message_.LinearizeAndEncode<MutateSocketResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      MutateSocketResponse& Message() {
        return *reinterpret_cast<MutateSocketResponse*>(message_.bytes());
      }
      zx_handle_disposition_t
          handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(::zx::socket& b)
          : message_(bytes_, sizeof(bytes_), b) {}
      explicit OwnedEncodedMessage(MutateSocketResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<MutateSocketResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<MutateSocketResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;
      ~DecodedMessage() {
        if (ok() && (PrimaryObject() != nullptr)) {
          PrimaryObject()->_CloseHandles();
        }
      }

      MutateSocketResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MutateSocketResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        zx_handle_info_t
            handles[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
        Init(outgoing_message, handles,
             std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles));
        if (ok()) {
          Decode<MutateSocketResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct MutateSocketRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::socket a;
    explicit MutateSocketRequest(zx_txid_t _txid, ::zx::socket& a)
        : a(std::move(a)) {
      _InitHeader(_txid);
    }
    explicit MutateSocketRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_ChannelProtocolMutateSocketRequestTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 24;
    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;
    using ResponseType = MutateSocketResponse;
    void _CloseHandles();

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, ::zx::socket& a)
          : message_(_bytes, _byte_size, sizeof(MutateSocketRequest), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        FIDL_ALIGNDECL MutateSocketRequest _request(_txid, a);
        message_.LinearizeAndEncode<MutateSocketRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            MutateSocketRequest* request)
          : message_(bytes, byte_size, sizeof(MutateSocketRequest), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        message_.LinearizeAndEncode<MutateSocketRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      MutateSocketRequest& Message() {
        return *reinterpret_cast<MutateSocketRequest*>(message_.bytes());
      }
      zx_handle_disposition_t
          handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid, ::zx::socket& a)
          : message_(bytes_, sizeof(bytes_), _txid, a) {}
      explicit OwnedEncodedMessage(MutateSocketRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<MutateSocketRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<MutateSocketRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;
      ~DecodedMessage() {
        if (ok() && (PrimaryObject() != nullptr)) {
          PrimaryObject()->_CloseHandles();
        }
      }

      MutateSocketRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MutateSocketRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        zx_handle_info_t
            handles[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
        Init(outgoing_message, handles,
             std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles));
        if (ok()) {
          Decode<MutateSocketRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  class EventHandler {
   public:
    EventHandler() = default;
    virtual ~EventHandler() = default;
    virtual void EventA(EventAResponse* event) = 0;

    // 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(::zx::unowned_channel client_end);
  };

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

   public:
    class MethodA final : public ::fidl::Result {
     public:
      explicit MethodA(zx_handle_t _client, int64_t a, int64_t b);
      explicit MethodA(const ::fidl::Result& result) : ::fidl::Result(result) {}
      MethodA(MethodA&&) = delete;
      MethodA(const MethodA&) = delete;
      MethodA* operator=(MethodA&&) = delete;
      MethodA* operator=(const MethodA&) = delete;
      ~MethodA() = default;

     private:
    };
    class MethodB final : public ::fidl::Result {
     public:
      explicit MethodB(zx_handle_t _client, int64_t a, int64_t b);
      MethodB(zx_handle_t _client, int64_t a, int64_t b, zx_time_t _deadline);
      explicit MethodB(const ::fidl::Result& result) : ::fidl::Result(result) {}
      MethodB(MethodB&&) = delete;
      MethodB(const MethodB&) = delete;
      MethodB* operator=(MethodB&&) = delete;
      MethodB* operator=(const MethodB&) = delete;
      ~MethodB() = default;

      MethodBResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MethodBResponse*>(bytes_);
      }
      const MethodBResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const MethodBResponse*>(bytes_);
      }

      MethodBResponse& value() { return *Unwrap(); }
      const MethodBResponse& value() const { return *Unwrap(); }

      MethodBResponse* operator->() { return &value(); }
      const MethodBResponse* operator->() const { return &value(); }

      MethodBResponse& operator*() { return value(); }
      const MethodBResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t
          bytes_[MethodBResponse::PrimarySize + MethodBResponse::MaxOutOfLine];
    };
    class TakeHandle final : public ::fidl::Result {
     public:
      explicit TakeHandle(zx_handle_t _client, ::zx::handle& h);
      TakeHandle(zx_handle_t _client, ::zx::handle& h, zx_time_t _deadline);
      explicit TakeHandle(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      TakeHandle(TakeHandle&&) = delete;
      TakeHandle(const TakeHandle&) = delete;
      TakeHandle* operator=(TakeHandle&&) = delete;
      TakeHandle* operator=(const TakeHandle&) = delete;
      ~TakeHandle() = default;

      TakeHandleResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<TakeHandleResponse*>(bytes_);
      }
      const TakeHandleResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const TakeHandleResponse*>(bytes_);
      }

      TakeHandleResponse& value() { return *Unwrap(); }
      const TakeHandleResponse& value() const { return *Unwrap(); }

      TakeHandleResponse* operator->() { return &value(); }
      const TakeHandleResponse* operator->() const { return &value(); }

      TakeHandleResponse& operator*() { return value(); }
      const TakeHandleResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[TakeHandleResponse::PrimarySize +
                     TakeHandleResponse::MaxOutOfLine];
    };
    class MutateSocket final : public ::fidl::Result {
     public:
      explicit MutateSocket(zx_handle_t _client, ::zx::socket& a);
      MutateSocket(zx_handle_t _client, ::zx::socket& a, zx_time_t _deadline);
      explicit MutateSocket(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      MutateSocket(MutateSocket&&) = delete;
      MutateSocket(const MutateSocket&) = delete;
      MutateSocket* operator=(MutateSocket&&) = delete;
      MutateSocket* operator=(const MutateSocket&) = delete;
      ~MutateSocket() {
        if (ok()) {
          Unwrap()->_CloseHandles();
        }
      }

      MutateSocketResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MutateSocketResponse*>(bytes_);
      }
      const MutateSocketResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const MutateSocketResponse*>(bytes_);
      }

      MutateSocketResponse& value() { return *Unwrap(); }
      const MutateSocketResponse& value() const { return *Unwrap(); }

      MutateSocketResponse* operator->() { return &value(); }
      const MutateSocketResponse* operator->() const { return &value(); }

      MutateSocketResponse& operator*() { return value(); }
      const MutateSocketResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[MutateSocketResponse::PrimarySize +
                     MutateSocketResponse::MaxOutOfLine];
    };
  };

  // 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;

   public:
    class MethodA final : public ::fidl::Result {
     public:
      explicit MethodA(zx_handle_t _client, uint8_t* _request_bytes,
                       uint32_t _request_byte_capacity, int64_t a, int64_t b);
      explicit MethodA(const ::fidl::Result& result) : ::fidl::Result(result) {}
      MethodA(MethodA&&) = delete;
      MethodA(const MethodA&) = delete;
      MethodA* operator=(MethodA&&) = delete;
      MethodA* operator=(const MethodA&) = delete;
      ~MethodA() = default;
    };
    class MethodB final : public ::fidl::Result {
     public:
      explicit MethodB(zx_handle_t _client, uint8_t* _request_bytes,
                       uint32_t _request_byte_capacity, int64_t a, int64_t b,
                       uint8_t* _response_bytes,
                       uint32_t _response_byte_capacity);
      explicit MethodB(const ::fidl::Result& result) : ::fidl::Result(result) {}
      MethodB(MethodB&&) = delete;
      MethodB(const MethodB&) = delete;
      MethodB* operator=(MethodB&&) = delete;
      MethodB* operator=(const MethodB&) = delete;
      ~MethodB() = default;

      MethodBResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MethodBResponse*>(bytes_);
      }
      const MethodBResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const MethodBResponse*>(bytes_);
      }

      MethodBResponse& value() { return *Unwrap(); }
      const MethodBResponse& value() const { return *Unwrap(); }

      MethodBResponse* operator->() { return &value(); }
      const MethodBResponse* operator->() const { return &value(); }

      MethodBResponse& operator*() { return value(); }
      const MethodBResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
    class TakeHandle final : public ::fidl::Result {
     public:
      explicit TakeHandle(zx_handle_t _client, uint8_t* _request_bytes,
                          uint32_t _request_byte_capacity, ::zx::handle& h,
                          uint8_t* _response_bytes,
                          uint32_t _response_byte_capacity);
      explicit TakeHandle(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      TakeHandle(TakeHandle&&) = delete;
      TakeHandle(const TakeHandle&) = delete;
      TakeHandle* operator=(TakeHandle&&) = delete;
      TakeHandle* operator=(const TakeHandle&) = delete;
      ~TakeHandle() = default;

      TakeHandleResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<TakeHandleResponse*>(bytes_);
      }
      const TakeHandleResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const TakeHandleResponse*>(bytes_);
      }

      TakeHandleResponse& value() { return *Unwrap(); }
      const TakeHandleResponse& value() const { return *Unwrap(); }

      TakeHandleResponse* operator->() { return &value(); }
      const TakeHandleResponse* operator->() const { return &value(); }

      TakeHandleResponse& operator*() { return value(); }
      const TakeHandleResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
    class MutateSocket final : public ::fidl::Result {
     public:
      explicit MutateSocket(zx_handle_t _client, uint8_t* _request_bytes,
                            uint32_t _request_byte_capacity, ::zx::socket& a,
                            uint8_t* _response_bytes,
                            uint32_t _response_byte_capacity);
      explicit MutateSocket(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      MutateSocket(MutateSocket&&) = delete;
      MutateSocket(const MutateSocket&) = delete;
      MutateSocket* operator=(MutateSocket&&) = delete;
      MutateSocket* operator=(const MutateSocket&) = delete;
      ~MutateSocket() {
        if (ok()) {
          Unwrap()->_CloseHandles();
        }
      }

      MutateSocketResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<MutateSocketResponse*>(bytes_);
      }
      const MutateSocketResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const MutateSocketResponse*>(bytes_);
      }

      MutateSocketResponse& value() { return *Unwrap(); }
      const MutateSocketResponse& value() const { return *Unwrap(); }

      MutateSocketResponse* operator->() { return &value(); }
      const MutateSocketResponse* operator->() const { return &value(); }

      MutateSocketResponse& operator*() { return value(); }
      const MutateSocketResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
  };

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

   public:
    // Allocates 32 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::MethodA MethodA(::zx::unowned_channel _client_end,
                                     int64_t a, int64_t b) {
      return ResultOf::MethodA(_client_end->get(), a, b);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::MethodA MethodA(::zx::unowned_channel _client_end,
                                            ::fidl::BufferSpan _request_buffer,
                                            int64_t a, int64_t b) {
      return UnownedResultOf::MethodA(_client_end->get(), _request_buffer.data,
                                      _request_buffer.capacity, a, b);
    }

    // Allocates 56 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::MethodB MethodB(::zx::unowned_channel _client_end,
                                     int64_t a, int64_t b) {
      return ResultOf::MethodB(_client_end->get(), a, b);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::MethodB MethodB(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        int64_t a, int64_t b, ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::MethodB(
          _client_end->get(), _request_buffer.data, _request_buffer.capacity, a,
          b, _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::TakeHandle TakeHandle(::zx::unowned_channel _client_end,
                                           ::zx::handle h) {
      return ResultOf::TakeHandle(_client_end->get(), h);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::TakeHandle TakeHandle(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        ::zx::handle h, ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::TakeHandle(
          _client_end->get(), _request_buffer.data, _request_buffer.capacity, h,
          _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 48 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::MutateSocket MutateSocket(
        ::zx::unowned_channel _client_end, ::zx::socket a) {
      return ResultOf::MutateSocket(_client_end->get(), a);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::MutateSocket MutateSocket(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        ::zx::socket a, ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::MutateSocket(
          _client_end->get(), _request_buffer.data, _request_buffer.capacity, a,
          _response_buffer.data, _response_buffer.capacity);
    }
  };

  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 32 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::MethodA MethodA(int64_t a, int64_t b) {
      return ResultOf::MethodA(this->channel().get(), a, b);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::MethodA MethodA(::fidl::BufferSpan _request_buffer,
                                     int64_t a, int64_t b) {
      return UnownedResultOf::MethodA(this->channel().get(),
                                      _request_buffer.data,
                                      _request_buffer.capacity, a, b);
    }

    // Allocates 56 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::MethodB MethodB(int64_t a, int64_t b) {
      return ResultOf::MethodB(this->channel().get(), a, b);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::MethodB MethodB(::fidl::BufferSpan _request_buffer,
                                     int64_t a, int64_t b,
                                     ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::MethodB(
          this->channel().get(), _request_buffer.data, _request_buffer.capacity,
          a, b, _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::TakeHandle TakeHandle(::zx::handle h) {
      return ResultOf::TakeHandle(this->channel().get(), h);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::TakeHandle TakeHandle(
        ::fidl::BufferSpan _request_buffer, ::zx::handle h,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::TakeHandle(
          this->channel().get(), _request_buffer.data, _request_buffer.capacity,
          h, _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 48 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::MutateSocket MutateSocket(::zx::socket a) {
      return ResultOf::MutateSocket(this->channel().get(), a);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::MutateSocket MutateSocket(
        ::fidl::BufferSpan _request_buffer, ::zx::socket a,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::MutateSocket(
          this->channel().get(), _request_buffer.data, _request_buffer.capacity,
          a, _response_buffer.data, _response_buffer.capacity);
    }

    // Handle all possible events defined in this protocol.
    // Blocks to consume exactly one message from the channel, then call the
    // corresponding virtual method defined in |EventHandler|. The return status
    // of the handler function is folded with any transport-level errors and
    // returned.
    ::fidl::Result HandleOneEvent(EventHandler& event_handler) {
      return event_handler.HandleOneEvent(::zx::unowned_channel(channel_));
    }

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

  struct AsyncEventHandlers;
  class MethodBResponseContext;
  class TakeHandleResponseContext;
  class MutateSocketResponseContext;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  class Interface : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    Interface() = default;
    virtual ~Interface() = default;

    // The marker protocol type within which this |Interface| class is defined.
    using _EnclosingProtocol = ChannelProtocol;

    using MethodACompleter = ::fidl::Completer<>;

    virtual void MethodA(int64_t a, int64_t b,
                         MethodACompleter::Sync& _completer) = 0;

    class MethodBCompleterBase : 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(int64_t result);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer, int64_t result);

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

    using MethodBCompleter = ::fidl::Completer<MethodBCompleterBase>;

    virtual void MethodB(int64_t a, int64_t b,
                         MethodBCompleter::Sync& _completer) = 0;

    class TakeHandleCompleterBase : 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 TakeHandleCompleter = ::fidl::Completer<TakeHandleCompleterBase>;

    virtual void TakeHandle(::zx::handle h,
                            TakeHandleCompleter::Sync& _completer) = 0;

    class MutateSocketCompleterBase : 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(::zx::socket b);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer, ::zx::socket b);

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

    using MutateSocketCompleter = ::fidl::Completer<MutateSocketCompleterBase>;

    virtual void MutateSocket(::zx::socket a,
                              MutateSocketCompleter::Sync& _completer) = 0;

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

  // 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 ::fidl::DispatchResult TryDispatch(Interface* impl,
                                            fidl_incoming_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 ::fidl::DispatchResult Dispatch(Interface* impl,
                                         fidl_incoming_msg_t* msg,
                                         ::fidl::Transaction* txn);

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

  class EventSender;
  class WeakEventSender;
};

extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseNoRequestNoResponseRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseNoRequestNoResponseResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseNoRequestEmptyResponseRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseNoRequestEmptyResponseResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseNoRequestWithResponseRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseNoRequestWithResponseResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseWithRequestNoResponseRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseWithRequestNoResponseResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseWithRequestEmptyResponseRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseWithRequestEmptyResponseResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseWithRequestWithResponseRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseWithRequestWithResponseResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseOnEmptyResponseRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseOnEmptyResponseEventTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseOnWithResponseRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithAndWithoutRequestResponseOnWithResponseEventTable;

class WithAndWithoutRequestResponse final {
  WithAndWithoutRequestResponse() = delete;

 public:
  struct NoRequestNoResponseRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit NoRequestNoResponseRequest(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* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(_bytes, _byte_size, sizeof(NoRequestNoResponseRequest),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL NoRequestNoResponseRequest _request(_txid);
        message_.LinearizeAndEncode<NoRequestNoResponseRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            NoRequestNoResponseRequest* request)
          : message_(bytes, byte_size, sizeof(NoRequestNoResponseRequest),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<NoRequestNoResponseRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      NoRequestNoResponseRequest& Message() {
        return *reinterpret_cast<NoRequestNoResponseRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(NoRequestNoResponseRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<NoRequestNoResponseRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<NoRequestNoResponseRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      NoRequestNoResponseRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestNoResponseRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<NoRequestNoResponseRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct NoRequestEmptyResponseResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    NoRequestEmptyResponseResponse() { _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* _bytes, uint32_t _byte_size)
          : message_(_bytes, _byte_size, sizeof(NoRequestEmptyResponseResponse),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL NoRequestEmptyResponseResponse _response{};
        message_.LinearizeAndEncode<NoRequestEmptyResponseResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            NoRequestEmptyResponseResponse* response)
          : message_(bytes, byte_size, sizeof(NoRequestEmptyResponseResponse),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<NoRequestEmptyResponseResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      NoRequestEmptyResponseResponse& Message() {
        return *reinterpret_cast<NoRequestEmptyResponseResponse*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage() : message_(bytes_, sizeof(bytes_)) {}
      explicit OwnedEncodedMessage(NoRequestEmptyResponseResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<NoRequestEmptyResponseResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<NoRequestEmptyResponseResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      NoRequestEmptyResponseResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestEmptyResponseResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<NoRequestEmptyResponseResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct NoRequestEmptyResponseRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit NoRequestEmptyResponseRequest(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* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(_bytes, _byte_size, sizeof(NoRequestEmptyResponseRequest),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL NoRequestEmptyResponseRequest _request(_txid);
        message_.LinearizeAndEncode<NoRequestEmptyResponseRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            NoRequestEmptyResponseRequest* request)
          : message_(bytes, byte_size, sizeof(NoRequestEmptyResponseRequest),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<NoRequestEmptyResponseRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      NoRequestEmptyResponseRequest& Message() {
        return *reinterpret_cast<NoRequestEmptyResponseRequest*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(NoRequestEmptyResponseRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<NoRequestEmptyResponseRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<NoRequestEmptyResponseRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      NoRequestEmptyResponseRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestEmptyResponseRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<NoRequestEmptyResponseRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct NoRequestWithResponseResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::fidl::StringView ret;
    explicit NoRequestWithResponseResponse(const ::fidl::StringView& ret)
        : ret(::fidl::unowned_ptr_t<const char>(ret.data()), ret.size()) {
      _InitHeader();
    }
    NoRequestWithResponseResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            const ::fidl::StringView& ret)
          : message_(_bytes, _byte_size, sizeof(NoRequestWithResponseResponse),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL NoRequestWithResponseResponse _response{ret};
        message_.LinearizeAndEncode<NoRequestWithResponseResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            NoRequestWithResponseResponse* response)
          : message_(bytes, byte_size, sizeof(NoRequestWithResponseResponse),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<NoRequestWithResponseResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      NoRequestWithResponseResponse& Message() {
        return *reinterpret_cast<NoRequestWithResponseResponse*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(const ::fidl::StringView& ret)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, ret) {}
      explicit OwnedEncodedMessage(NoRequestWithResponseResponse* response)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
          bytes_;
      UnownedEncodedMessage message_;
    };

    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<NoRequestWithResponseResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<NoRequestWithResponseResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      NoRequestWithResponseResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestWithResponseResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<NoRequestWithResponseResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct NoRequestWithResponseRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit NoRequestWithResponseRequest(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;
    using ResponseType = NoRequestWithResponseResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(_bytes, _byte_size, sizeof(NoRequestWithResponseRequest),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL NoRequestWithResponseRequest _request(_txid);
        message_.LinearizeAndEncode<NoRequestWithResponseRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            NoRequestWithResponseRequest* request)
          : message_(bytes, byte_size, sizeof(NoRequestWithResponseRequest),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<NoRequestWithResponseRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      NoRequestWithResponseRequest& Message() {
        return *reinterpret_cast<NoRequestWithResponseRequest*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(NoRequestWithResponseRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<NoRequestWithResponseRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<NoRequestWithResponseRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      NoRequestWithResponseRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestWithResponseRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<NoRequestWithResponseRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct WithRequestNoResponseRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::fidl::StringView arg;
    explicit WithRequestNoResponseRequest(zx_txid_t _txid,
                                          const ::fidl::StringView& arg)
        : arg(::fidl::unowned_ptr_t<const char>(arg.data()), arg.size()) {
      _InitHeader(_txid);
    }
    explicit WithRequestNoResponseRequest(zx_txid_t _txid) {
      _InitHeader(_txid);
    }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, const ::fidl::StringView& arg)
          : message_(_bytes, _byte_size, sizeof(WithRequestNoResponseRequest),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL WithRequestNoResponseRequest _request(_txid, arg);
        message_.LinearizeAndEncode<WithRequestNoResponseRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            WithRequestNoResponseRequest* request)
          : message_(bytes, byte_size, sizeof(WithRequestNoResponseRequest),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<WithRequestNoResponseRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      WithRequestNoResponseRequest& Message() {
        return *reinterpret_cast<WithRequestNoResponseRequest*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid,
                                   const ::fidl::StringView& arg)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, _txid, arg) {}
      explicit OwnedEncodedMessage(WithRequestNoResponseRequest* request)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
          bytes_;
      UnownedEncodedMessage message_;
    };

    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<WithRequestNoResponseRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<WithRequestNoResponseRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      WithRequestNoResponseRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestNoResponseRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<WithRequestNoResponseRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct WithRequestEmptyResponseResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    WithRequestEmptyResponseResponse() { _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* _bytes, uint32_t _byte_size)
          : message_(_bytes, _byte_size,
                     sizeof(WithRequestEmptyResponseResponse), nullptr, 0, 0) {
        FIDL_ALIGNDECL WithRequestEmptyResponseResponse _response{};
        message_.LinearizeAndEncode<WithRequestEmptyResponseResponse>(
            &_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            WithRequestEmptyResponseResponse* response)
          : message_(bytes, byte_size, sizeof(WithRequestEmptyResponseResponse),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<WithRequestEmptyResponseResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      WithRequestEmptyResponseResponse& Message() {
        return *reinterpret_cast<WithRequestEmptyResponseResponse*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage() : message_(bytes_, sizeof(bytes_)) {}
      explicit OwnedEncodedMessage(WithRequestEmptyResponseResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<WithRequestEmptyResponseResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<WithRequestEmptyResponseResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      WithRequestEmptyResponseResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestEmptyResponseResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<WithRequestEmptyResponseResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct WithRequestEmptyResponseRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::fidl::StringView arg;
    explicit WithRequestEmptyResponseRequest(zx_txid_t _txid,
                                             const ::fidl::StringView& arg)
        : arg(::fidl::unowned_ptr_t<const char>(arg.data()), arg.size()) {
      _InitHeader(_txid);
    }
    explicit WithRequestEmptyResponseRequest(zx_txid_t _txid) {
      _InitHeader(_txid);
    }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, const ::fidl::StringView& arg)
          : message_(_bytes, _byte_size,
                     sizeof(WithRequestEmptyResponseRequest), nullptr, 0, 0) {
        FIDL_ALIGNDECL WithRequestEmptyResponseRequest _request(_txid, arg);
        message_.LinearizeAndEncode<WithRequestEmptyResponseRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            WithRequestEmptyResponseRequest* request)
          : message_(bytes, byte_size, sizeof(WithRequestEmptyResponseRequest),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<WithRequestEmptyResponseRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      WithRequestEmptyResponseRequest& Message() {
        return *reinterpret_cast<WithRequestEmptyResponseRequest*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid,
                                   const ::fidl::StringView& arg)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, _txid, arg) {}
      explicit OwnedEncodedMessage(WithRequestEmptyResponseRequest* request)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
          bytes_;
      UnownedEncodedMessage message_;
    };

    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<WithRequestEmptyResponseRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<WithRequestEmptyResponseRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      WithRequestEmptyResponseRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestEmptyResponseRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<WithRequestEmptyResponseRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct WithRequestWithResponseResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::fidl::StringView ret;
    explicit WithRequestWithResponseResponse(const ::fidl::StringView& ret)
        : ret(::fidl::unowned_ptr_t<const char>(ret.data()), ret.size()) {
      _InitHeader();
    }
    WithRequestWithResponseResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            const ::fidl::StringView& ret)
          : message_(_bytes, _byte_size,
                     sizeof(WithRequestWithResponseResponse), nullptr, 0, 0) {
        FIDL_ALIGNDECL WithRequestWithResponseResponse _response{ret};
        message_.LinearizeAndEncode<WithRequestWithResponseResponse>(
            &_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            WithRequestWithResponseResponse* response)
          : message_(bytes, byte_size, sizeof(WithRequestWithResponseResponse),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<WithRequestWithResponseResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      WithRequestWithResponseResponse& Message() {
        return *reinterpret_cast<WithRequestWithResponseResponse*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(const ::fidl::StringView& ret)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, ret) {}
      explicit OwnedEncodedMessage(WithRequestWithResponseResponse* response)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
          bytes_;
      UnownedEncodedMessage message_;
    };

    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<WithRequestWithResponseResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<WithRequestWithResponseResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      WithRequestWithResponseResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestWithResponseResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<WithRequestWithResponseResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct WithRequestWithResponseRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::fidl::StringView arg;
    explicit WithRequestWithResponseRequest(zx_txid_t _txid,
                                            const ::fidl::StringView& arg)
        : arg(::fidl::unowned_ptr_t<const char>(arg.data()), arg.size()) {
      _InitHeader(_txid);
    }
    explicit WithRequestWithResponseRequest(zx_txid_t _txid) {
      _InitHeader(_txid);
    }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocols_WithAndWithoutRequestResponseWithRequestWithResponseRequestTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 32;
    static constexpr uint32_t MaxOutOfLine = 4294967295;
    static constexpr uint32_t AltPrimarySize = 32;
    static constexpr uint32_t AltMaxOutOfLine = 4294967295;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = true;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kRequest;
    using ResponseType = WithRequestWithResponseResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, const ::fidl::StringView& arg)
          : message_(_bytes, _byte_size, sizeof(WithRequestWithResponseRequest),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL WithRequestWithResponseRequest _request(_txid, arg);
        message_.LinearizeAndEncode<WithRequestWithResponseRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            WithRequestWithResponseRequest* request)
          : message_(bytes, byte_size, sizeof(WithRequestWithResponseRequest),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<WithRequestWithResponseRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      WithRequestWithResponseRequest& Message() {
        return *reinterpret_cast<WithRequestWithResponseRequest*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid,
                                   const ::fidl::StringView& arg)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, _txid, arg) {}
      explicit OwnedEncodedMessage(WithRequestWithResponseRequest* request)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
          bytes_;
      UnownedEncodedMessage message_;
    };

    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<WithRequestWithResponseRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<WithRequestWithResponseRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      WithRequestWithResponseRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestWithResponseRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<WithRequestWithResponseRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct OnEmptyResponseResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    OnEmptyResponseResponse() { _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* _bytes, uint32_t _byte_size)
          : message_(_bytes, _byte_size, sizeof(OnEmptyResponseResponse),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL OnEmptyResponseResponse _response{};
        message_.LinearizeAndEncode<OnEmptyResponseResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            OnEmptyResponseResponse* response)
          : message_(bytes, byte_size, sizeof(OnEmptyResponseResponse), nullptr,
                     0, 0) {
        message_.LinearizeAndEncode<OnEmptyResponseResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      OnEmptyResponseResponse& Message() {
        return *reinterpret_cast<OnEmptyResponseResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage() : message_(bytes_, sizeof(bytes_)) {}
      explicit OwnedEncodedMessage(OnEmptyResponseResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<OnEmptyResponseResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<OnEmptyResponseResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      OnEmptyResponseResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<OnEmptyResponseResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<OnEmptyResponseResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct OnWithResponseResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::fidl::StringView ret;
    explicit OnWithResponseResponse(const ::fidl::StringView& ret)
        : ret(::fidl::unowned_ptr_t<const char>(ret.data()), ret.size()) {
      _InitHeader();
    }
    OnWithResponseResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            const ::fidl::StringView& ret)
          : message_(_bytes, _byte_size, sizeof(OnWithResponseResponse),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL OnWithResponseResponse _response{ret};
        message_.LinearizeAndEncode<OnWithResponseResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            OnWithResponseResponse* response)
          : message_(bytes, byte_size, sizeof(OnWithResponseResponse), nullptr,
                     0, 0) {
        message_.LinearizeAndEncode<OnWithResponseResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      OnWithResponseResponse& Message() {
        return *reinterpret_cast<OnWithResponseResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(const ::fidl::StringView& ret)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, ret) {}
      explicit OwnedEncodedMessage(OnWithResponseResponse* response)
          : bytes_(std::make_unique<::fidl::internal::AlignedBuffer<
                       ZX_CHANNEL_MAX_MSG_BYTES>>()),
            message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
          bytes_;
      UnownedEncodedMessage message_;
    };

    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<OnWithResponseResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<OnWithResponseResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      OnWithResponseResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<OnWithResponseResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<OnWithResponseResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };

  class EventHandler {
   public:
    EventHandler() = default;
    virtual ~EventHandler() = default;
    virtual void OnEmptyResponse(OnEmptyResponseResponse* event) = 0;
    virtual void OnWithResponse(OnWithResponseResponse* event) = 0;

    // 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(::zx::unowned_channel client_end);
  };

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

   public:
    class NoRequestNoResponse final : public ::fidl::Result {
     public:
      explicit NoRequestNoResponse(zx_handle_t _client);
      explicit NoRequestNoResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      NoRequestNoResponse(NoRequestNoResponse&&) = delete;
      NoRequestNoResponse(const NoRequestNoResponse&) = delete;
      NoRequestNoResponse* operator=(NoRequestNoResponse&&) = delete;
      NoRequestNoResponse* operator=(const NoRequestNoResponse&) = delete;
      ~NoRequestNoResponse() = default;

     private:
    };
    class NoRequestEmptyResponse final : public ::fidl::Result {
     public:
      explicit NoRequestEmptyResponse(zx_handle_t _client);
      NoRequestEmptyResponse(zx_handle_t _client, zx_time_t _deadline);
      explicit NoRequestEmptyResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      NoRequestEmptyResponse(NoRequestEmptyResponse&&) = delete;
      NoRequestEmptyResponse(const NoRequestEmptyResponse&) = delete;
      NoRequestEmptyResponse* operator=(NoRequestEmptyResponse&&) = delete;
      NoRequestEmptyResponse* operator=(const NoRequestEmptyResponse&) = delete;
      ~NoRequestEmptyResponse() = default;

      NoRequestEmptyResponseResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestEmptyResponseResponse*>(bytes_);
      }
      const NoRequestEmptyResponseResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const NoRequestEmptyResponseResponse*>(bytes_);
      }

      NoRequestEmptyResponseResponse& value() { return *Unwrap(); }
      const NoRequestEmptyResponseResponse& value() const { return *Unwrap(); }

      NoRequestEmptyResponseResponse* operator->() { return &value(); }
      const NoRequestEmptyResponseResponse* operator->() const {
        return &value();
      }

      NoRequestEmptyResponseResponse& operator*() { return value(); }
      const NoRequestEmptyResponseResponse& operator*() const {
        return value();
      }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[NoRequestEmptyResponseResponse::PrimarySize +
                     NoRequestEmptyResponseResponse::MaxOutOfLine];
    };
    class NoRequestWithResponse final : public ::fidl::Result {
     public:
      explicit NoRequestWithResponse(zx_handle_t _client);
      NoRequestWithResponse(zx_handle_t _client, zx_time_t _deadline);
      explicit NoRequestWithResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      NoRequestWithResponse(NoRequestWithResponse&&) = delete;
      NoRequestWithResponse(const NoRequestWithResponse&) = delete;
      NoRequestWithResponse* operator=(NoRequestWithResponse&&) = delete;
      NoRequestWithResponse* operator=(const NoRequestWithResponse&) = delete;
      ~NoRequestWithResponse() = default;

      NoRequestWithResponseResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestWithResponseResponse*>(bytes_->data());
      }
      const NoRequestWithResponseResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const NoRequestWithResponseResponse*>(
            bytes_->data());
      }

      NoRequestWithResponseResponse& value() { return *Unwrap(); }
      const NoRequestWithResponseResponse& value() const { return *Unwrap(); }

      NoRequestWithResponseResponse* operator->() { return &value(); }
      const NoRequestWithResponseResponse* operator->() const {
        return &value();
      }

      NoRequestWithResponseResponse& operator*() { return value(); }
      const NoRequestWithResponseResponse& operator*() const { return value(); }

     private:
      std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
          bytes_;
    };
    class WithRequestNoResponse final : public ::fidl::Result {
     public:
      explicit WithRequestNoResponse(zx_handle_t _client,
                                     const ::fidl::StringView& arg);
      explicit WithRequestNoResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      WithRequestNoResponse(WithRequestNoResponse&&) = delete;
      WithRequestNoResponse(const WithRequestNoResponse&) = delete;
      WithRequestNoResponse* operator=(WithRequestNoResponse&&) = delete;
      WithRequestNoResponse* operator=(const WithRequestNoResponse&) = delete;
      ~WithRequestNoResponse() = default;

     private:
    };
    class WithRequestEmptyResponse final : public ::fidl::Result {
     public:
      explicit WithRequestEmptyResponse(zx_handle_t _client,
                                        const ::fidl::StringView& arg);
      WithRequestEmptyResponse(zx_handle_t _client,
                               const ::fidl::StringView& arg,
                               zx_time_t _deadline);
      explicit WithRequestEmptyResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      WithRequestEmptyResponse(WithRequestEmptyResponse&&) = delete;
      WithRequestEmptyResponse(const WithRequestEmptyResponse&) = delete;
      WithRequestEmptyResponse* operator=(WithRequestEmptyResponse&&) = delete;
      WithRequestEmptyResponse* operator=(const WithRequestEmptyResponse&) =
          delete;
      ~WithRequestEmptyResponse() = default;

      WithRequestEmptyResponseResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestEmptyResponseResponse*>(bytes_);
      }
      const WithRequestEmptyResponseResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const WithRequestEmptyResponseResponse*>(
            bytes_);
      }

      WithRequestEmptyResponseResponse& value() { return *Unwrap(); }
      const WithRequestEmptyResponseResponse& value() const {
        return *Unwrap();
      }

      WithRequestEmptyResponseResponse* operator->() { return &value(); }
      const WithRequestEmptyResponseResponse* operator->() const {
        return &value();
      }

      WithRequestEmptyResponseResponse& operator*() { return value(); }
      const WithRequestEmptyResponseResponse& operator*() const {
        return value();
      }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[WithRequestEmptyResponseResponse::PrimarySize +
                     WithRequestEmptyResponseResponse::MaxOutOfLine];
    };
    class WithRequestWithResponse final : public ::fidl::Result {
     public:
      explicit WithRequestWithResponse(zx_handle_t _client,
                                       const ::fidl::StringView& arg);
      WithRequestWithResponse(zx_handle_t _client,
                              const ::fidl::StringView& arg,
                              zx_time_t _deadline);
      explicit WithRequestWithResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      WithRequestWithResponse(WithRequestWithResponse&&) = delete;
      WithRequestWithResponse(const WithRequestWithResponse&) = delete;
      WithRequestWithResponse* operator=(WithRequestWithResponse&&) = delete;
      WithRequestWithResponse* operator=(const WithRequestWithResponse&) =
          delete;
      ~WithRequestWithResponse() = default;

      WithRequestWithResponseResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestWithResponseResponse*>(
            bytes_->data());
      }
      const WithRequestWithResponseResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const WithRequestWithResponseResponse*>(
            bytes_->data());
      }

      WithRequestWithResponseResponse& value() { return *Unwrap(); }
      const WithRequestWithResponseResponse& value() const { return *Unwrap(); }

      WithRequestWithResponseResponse* operator->() { return &value(); }
      const WithRequestWithResponseResponse* operator->() const {
        return &value();
      }

      WithRequestWithResponseResponse& operator*() { return value(); }
      const WithRequestWithResponseResponse& operator*() const {
        return value();
      }

     private:
      std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
          bytes_;
    };
  };

  // 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;

   public:
    class NoRequestNoResponse final : public ::fidl::Result {
     public:
      explicit NoRequestNoResponse(zx_handle_t _client);
      explicit NoRequestNoResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      NoRequestNoResponse(NoRequestNoResponse&&) = delete;
      NoRequestNoResponse(const NoRequestNoResponse&) = delete;
      NoRequestNoResponse* operator=(NoRequestNoResponse&&) = delete;
      NoRequestNoResponse* operator=(const NoRequestNoResponse&) = delete;
      ~NoRequestNoResponse() = default;
    };
    class NoRequestEmptyResponse final : public ::fidl::Result {
     public:
      explicit NoRequestEmptyResponse(zx_handle_t _client,
                                      uint8_t* _response_bytes,
                                      uint32_t _response_byte_capacity);
      explicit NoRequestEmptyResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      NoRequestEmptyResponse(NoRequestEmptyResponse&&) = delete;
      NoRequestEmptyResponse(const NoRequestEmptyResponse&) = delete;
      NoRequestEmptyResponse* operator=(NoRequestEmptyResponse&&) = delete;
      NoRequestEmptyResponse* operator=(const NoRequestEmptyResponse&) = delete;
      ~NoRequestEmptyResponse() = default;

      NoRequestEmptyResponseResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestEmptyResponseResponse*>(bytes_);
      }
      const NoRequestEmptyResponseResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const NoRequestEmptyResponseResponse*>(bytes_);
      }

      NoRequestEmptyResponseResponse& value() { return *Unwrap(); }
      const NoRequestEmptyResponseResponse& value() const { return *Unwrap(); }

      NoRequestEmptyResponseResponse* operator->() { return &value(); }
      const NoRequestEmptyResponseResponse* operator->() const {
        return &value();
      }

      NoRequestEmptyResponseResponse& operator*() { return value(); }
      const NoRequestEmptyResponseResponse& operator*() const {
        return value();
      }

     private:
      uint8_t* bytes_;
    };
    class NoRequestWithResponse final : public ::fidl::Result {
     public:
      explicit NoRequestWithResponse(zx_handle_t _client,
                                     uint8_t* _response_bytes,
                                     uint32_t _response_byte_capacity);
      explicit NoRequestWithResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      NoRequestWithResponse(NoRequestWithResponse&&) = delete;
      NoRequestWithResponse(const NoRequestWithResponse&) = delete;
      NoRequestWithResponse* operator=(NoRequestWithResponse&&) = delete;
      NoRequestWithResponse* operator=(const NoRequestWithResponse&) = delete;
      ~NoRequestWithResponse() = default;

      NoRequestWithResponseResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<NoRequestWithResponseResponse*>(bytes_);
      }
      const NoRequestWithResponseResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const NoRequestWithResponseResponse*>(bytes_);
      }

      NoRequestWithResponseResponse& value() { return *Unwrap(); }
      const NoRequestWithResponseResponse& value() const { return *Unwrap(); }

      NoRequestWithResponseResponse* operator->() { return &value(); }
      const NoRequestWithResponseResponse* operator->() const {
        return &value();
      }

      NoRequestWithResponseResponse& operator*() { return value(); }
      const NoRequestWithResponseResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
    class WithRequestNoResponse final : public ::fidl::Result {
     public:
      explicit WithRequestNoResponse(zx_handle_t _client,
                                     uint8_t* _request_bytes,
                                     uint32_t _request_byte_capacity,
                                     const ::fidl::StringView& arg);
      explicit WithRequestNoResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      WithRequestNoResponse(WithRequestNoResponse&&) = delete;
      WithRequestNoResponse(const WithRequestNoResponse&) = delete;
      WithRequestNoResponse* operator=(WithRequestNoResponse&&) = delete;
      WithRequestNoResponse* operator=(const WithRequestNoResponse&) = delete;
      ~WithRequestNoResponse() = default;
    };
    class WithRequestEmptyResponse final : public ::fidl::Result {
     public:
      explicit WithRequestEmptyResponse(zx_handle_t _client,
                                        uint8_t* _request_bytes,
                                        uint32_t _request_byte_capacity,
                                        const ::fidl::StringView& arg,
                                        uint8_t* _response_bytes,
                                        uint32_t _response_byte_capacity);
      explicit WithRequestEmptyResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      WithRequestEmptyResponse(WithRequestEmptyResponse&&) = delete;
      WithRequestEmptyResponse(const WithRequestEmptyResponse&) = delete;
      WithRequestEmptyResponse* operator=(WithRequestEmptyResponse&&) = delete;
      WithRequestEmptyResponse* operator=(const WithRequestEmptyResponse&) =
          delete;
      ~WithRequestEmptyResponse() = default;

      WithRequestEmptyResponseResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestEmptyResponseResponse*>(bytes_);
      }
      const WithRequestEmptyResponseResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const WithRequestEmptyResponseResponse*>(
            bytes_);
      }

      WithRequestEmptyResponseResponse& value() { return *Unwrap(); }
      const WithRequestEmptyResponseResponse& value() const {
        return *Unwrap();
      }

      WithRequestEmptyResponseResponse* operator->() { return &value(); }
      const WithRequestEmptyResponseResponse* operator->() const {
        return &value();
      }

      WithRequestEmptyResponseResponse& operator*() { return value(); }
      const WithRequestEmptyResponseResponse& operator*() const {
        return value();
      }

     private:
      uint8_t* bytes_;
    };
    class WithRequestWithResponse final : public ::fidl::Result {
     public:
      explicit WithRequestWithResponse(zx_handle_t _client,
                                       uint8_t* _request_bytes,
                                       uint32_t _request_byte_capacity,
                                       const ::fidl::StringView& arg,
                                       uint8_t* _response_bytes,
                                       uint32_t _response_byte_capacity);
      explicit WithRequestWithResponse(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      WithRequestWithResponse(WithRequestWithResponse&&) = delete;
      WithRequestWithResponse(const WithRequestWithResponse&) = delete;
      WithRequestWithResponse* operator=(WithRequestWithResponse&&) = delete;
      WithRequestWithResponse* operator=(const WithRequestWithResponse&) =
          delete;
      ~WithRequestWithResponse() = default;

      WithRequestWithResponseResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<WithRequestWithResponseResponse*>(bytes_);
      }
      const WithRequestWithResponseResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const WithRequestWithResponseResponse*>(bytes_);
      }

      WithRequestWithResponseResponse& value() { return *Unwrap(); }
      const WithRequestWithResponseResponse& value() const { return *Unwrap(); }

      WithRequestWithResponseResponse* operator->() { return &value(); }
      const WithRequestWithResponseResponse* operator->() const {
        return &value();
      }

      WithRequestWithResponseResponse& operator*() { return value(); }
      const WithRequestWithResponseResponse& operator*() const {
        return value();
      }

     private:
      uint8_t* bytes_;
    };
  };

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

   public:
    // Allocates 16 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::NoRequestNoResponse NoRequestNoResponse(
        ::zx::unowned_channel _client_end) {
      return ResultOf::NoRequestNoResponse(_client_end->get());
    }

    // Allocates 32 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::NoRequestEmptyResponse NoRequestEmptyResponse(
        ::zx::unowned_channel _client_end) {
      return ResultOf::NoRequestEmptyResponse(_client_end->get());
    }

    // Allocates 16 bytes of request buffer on the stack. Response is
    // heap-allocated.
    static ResultOf::NoRequestWithResponse NoRequestWithResponse(
        ::zx::unowned_channel _client_end) {
      return ResultOf::NoRequestWithResponse(_client_end->get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::NoRequestWithResponse NoRequestWithResponse(
        ::zx::unowned_channel _client_end

        ,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::NoRequestWithResponse(
          _client_end->get(), _response_buffer.data, _response_buffer.capacity);
    }

    // Request is heap-allocated.
    static ResultOf::WithRequestNoResponse WithRequestNoResponse(
        ::zx::unowned_channel _client_end, ::fidl::StringView arg) {
      return ResultOf::WithRequestNoResponse(_client_end->get(), arg);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::WithRequestNoResponse WithRequestNoResponse(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        ::fidl::StringView arg) {
      return UnownedResultOf::WithRequestNoResponse(
          _client_end->get(), _request_buffer.data, _request_buffer.capacity,
          arg);
    }

    // Allocates 16 bytes of response buffer on the stack. Request is
    // heap-allocated.
    static ResultOf::WithRequestEmptyResponse WithRequestEmptyResponse(
        ::zx::unowned_channel _client_end, ::fidl::StringView arg) {
      return ResultOf::WithRequestEmptyResponse(_client_end->get(), arg);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::WithRequestEmptyResponse WithRequestEmptyResponse(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        ::fidl::StringView arg, ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::WithRequestEmptyResponse(
          _client_end->get(), _request_buffer.data, _request_buffer.capacity,
          arg, _response_buffer.data, _response_buffer.capacity);
    }

    // Request is heap-allocated. Response is heap-allocated.
    static ResultOf::WithRequestWithResponse WithRequestWithResponse(
        ::zx::unowned_channel _client_end, ::fidl::StringView arg) {
      return ResultOf::WithRequestWithResponse(_client_end->get(), arg);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::WithRequestWithResponse WithRequestWithResponse(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        ::fidl::StringView arg, ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::WithRequestWithResponse(
          _client_end->get(), _request_buffer.data, _request_buffer.capacity,
          arg, _response_buffer.data, _response_buffer.capacity);
    }
  };

  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 16 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::NoRequestNoResponse NoRequestNoResponse() {
      return ResultOf::NoRequestNoResponse(this->channel().get());
    }

    // Allocates 32 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::NoRequestEmptyResponse NoRequestEmptyResponse() {
      return ResultOf::NoRequestEmptyResponse(this->channel().get());
    }

    // Allocates 16 bytes of request buffer on the stack. Response is
    // heap-allocated.
    ResultOf::NoRequestWithResponse NoRequestWithResponse() {
      return ResultOf::NoRequestWithResponse(this->channel().get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::NoRequestWithResponse NoRequestWithResponse(
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::NoRequestWithResponse(this->channel().get(),
                                                    _response_buffer.data,
                                                    _response_buffer.capacity);
    }

    // Request is heap-allocated.
    ResultOf::WithRequestNoResponse WithRequestNoResponse(
        ::fidl::StringView arg) {
      return ResultOf::WithRequestNoResponse(this->channel().get(), arg);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::WithRequestNoResponse WithRequestNoResponse(
        ::fidl::BufferSpan _request_buffer, ::fidl::StringView arg) {
      return UnownedResultOf::WithRequestNoResponse(
          this->channel().get(), _request_buffer.data, _request_buffer.capacity,
          arg);
    }

    // Allocates 16 bytes of response buffer on the stack. Request is
    // heap-allocated.
    ResultOf::WithRequestEmptyResponse WithRequestEmptyResponse(
        ::fidl::StringView arg) {
      return ResultOf::WithRequestEmptyResponse(this->channel().get(), arg);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::WithRequestEmptyResponse WithRequestEmptyResponse(
        ::fidl::BufferSpan _request_buffer, ::fidl::StringView arg,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::WithRequestEmptyResponse(
          this->channel().get(), _request_buffer.data, _request_buffer.capacity,
          arg, _response_buffer.data, _response_buffer.capacity);
    }

    // Request is heap-allocated. Response is heap-allocated.
    ResultOf::WithRequestWithResponse WithRequestWithResponse(
        ::fidl::StringView arg) {
      return ResultOf::WithRequestWithResponse(this->channel().get(), arg);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::WithRequestWithResponse WithRequestWithResponse(
        ::fidl::BufferSpan _request_buffer, ::fidl::StringView arg,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::WithRequestWithResponse(
          this->channel().get(), _request_buffer.data, _request_buffer.capacity,
          arg, _response_buffer.data, _response_buffer.capacity);
    }

    // Handle all possible events defined in this protocol.
    // Blocks to consume exactly one message from the channel, then call the
    // corresponding virtual method defined in |EventHandler|. The return status
    // of the handler function is folded with any transport-level errors and
    // returned.
    ::fidl::Result HandleOneEvent(EventHandler& event_handler) {
      return event_handler.HandleOneEvent(::zx::unowned_channel(channel_));
    }

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

  struct AsyncEventHandlers;
  class NoRequestEmptyResponseResponseContext;
  class NoRequestWithResponseResponseContext;
  class WithRequestEmptyResponseResponseContext;
  class WithRequestWithResponseResponseContext;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  class Interface : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    Interface() = default;
    virtual ~Interface() = default;

    // The marker protocol type within which this |Interface| class is defined.
    using _EnclosingProtocol = WithAndWithoutRequestResponse;

    using NoRequestNoResponseCompleter = ::fidl::Completer<>;

    virtual void NoRequestNoResponse(
        NoRequestNoResponseCompleter::Sync& _completer) = 0;

    class NoRequestEmptyResponseCompleterBase : 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 NoRequestEmptyResponseCompleter =
        ::fidl::Completer<NoRequestEmptyResponseCompleterBase>;

    virtual void NoRequestEmptyResponse(
        NoRequestEmptyResponseCompleter::Sync& _completer) = 0;

    class NoRequestWithResponseCompleterBase : 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(::fidl::StringView ret);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer, ::fidl::StringView ret);

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

    using NoRequestWithResponseCompleter =
        ::fidl::Completer<NoRequestWithResponseCompleterBase>;

    virtual void NoRequestWithResponse(
        NoRequestWithResponseCompleter::Sync& _completer) = 0;

    using WithRequestNoResponseCompleter = ::fidl::Completer<>;

    virtual void WithRequestNoResponse(
        ::fidl::StringView arg,
        WithRequestNoResponseCompleter::Sync& _completer) = 0;

    class WithRequestEmptyResponseCompleterBase : 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 WithRequestEmptyResponseCompleter =
        ::fidl::Completer<WithRequestEmptyResponseCompleterBase>;

    virtual void WithRequestEmptyResponse(
        ::fidl::StringView arg,
        WithRequestEmptyResponseCompleter::Sync& _completer) = 0;

    class WithRequestWithResponseCompleterBase : 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(::fidl::StringView ret);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer, ::fidl::StringView ret);

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

    using WithRequestWithResponseCompleter =
        ::fidl::Completer<WithRequestWithResponseCompleterBase>;

    virtual void WithRequestWithResponse(
        ::fidl::StringView arg,
        WithRequestWithResponseCompleter::Sync& _completer) = 0;

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

  // 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 ::fidl::DispatchResult TryDispatch(Interface* impl,
                                            fidl_incoming_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 ::fidl::DispatchResult Dispatch(Interface* impl,
                                         fidl_incoming_msg_t* msg,
                                         ::fidl::Transaction* txn);

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

  class EventSender;
  class WeakEventSender;
};

extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntaxResponseAsStructRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntaxResponseAsStructResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntaxErrorAsPrimitiveRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntaxErrorAsPrimitiveResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntaxErrorAsEnumRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocols_WithErrorSyntaxErrorAsEnumResponseTable;

class WithErrorSyntax final {
  WithErrorSyntax() = delete;

 public:
  struct ResponseAsStructResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Result
        result;
    explicit ResponseAsStructResponse(
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Result&
            result)
        : result(std::move(result)) {
      _InitHeader();
    }
    ResponseAsStructResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            ::llcpp::fidl::test::protocols::
                                WithErrorSyntax_ResponseAsStruct_Result& result)
          : message_(_bytes, _byte_size, sizeof(ResponseAsStructResponse),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL ResponseAsStructResponse _response{result};
        message_.LinearizeAndEncode<ResponseAsStructResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            ResponseAsStructResponse* response)
          : message_(bytes, byte_size, sizeof(ResponseAsStructResponse),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<ResponseAsStructResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      ResponseAsStructResponse& Message() {
        return *reinterpret_cast<ResponseAsStructResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(
          ::llcpp::fidl::test::protocols::
              WithErrorSyntax_ResponseAsStruct_Result& result)
          : message_(bytes_, sizeof(bytes_), result) {}
      explicit OwnedEncodedMessage(ResponseAsStructResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<ResponseAsStructResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<ResponseAsStructResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      ResponseAsStructResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ResponseAsStructResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<ResponseAsStructResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct ResponseAsStructRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit ResponseAsStructRequest(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;
    using ResponseType = ResponseAsStructResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(_bytes, _byte_size, sizeof(ResponseAsStructRequest),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL ResponseAsStructRequest _request(_txid);
        message_.LinearizeAndEncode<ResponseAsStructRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            ResponseAsStructRequest* request)
          : message_(bytes, byte_size, sizeof(ResponseAsStructRequest), nullptr,
                     0, 0) {
        message_.LinearizeAndEncode<ResponseAsStructRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      ResponseAsStructRequest& Message() {
        return *reinterpret_cast<ResponseAsStructRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(ResponseAsStructRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<ResponseAsStructRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<ResponseAsStructRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      ResponseAsStructRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ResponseAsStructRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<ResponseAsStructRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct ErrorAsPrimitiveResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Result
        result;
    explicit ErrorAsPrimitiveResponse(
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Result&
            result)
        : result(std::move(result)) {
      _InitHeader();
    }
    ErrorAsPrimitiveResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            ::llcpp::fidl::test::protocols::
                                WithErrorSyntax_ErrorAsPrimitive_Result& result)
          : message_(_bytes, _byte_size, sizeof(ErrorAsPrimitiveResponse),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL ErrorAsPrimitiveResponse _response{result};
        message_.LinearizeAndEncode<ErrorAsPrimitiveResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            ErrorAsPrimitiveResponse* response)
          : message_(bytes, byte_size, sizeof(ErrorAsPrimitiveResponse),
                     nullptr, 0, 0) {
        message_.LinearizeAndEncode<ErrorAsPrimitiveResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      ErrorAsPrimitiveResponse& Message() {
        return *reinterpret_cast<ErrorAsPrimitiveResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(
          ::llcpp::fidl::test::protocols::
              WithErrorSyntax_ErrorAsPrimitive_Result& result)
          : message_(bytes_, sizeof(bytes_), result) {}
      explicit OwnedEncodedMessage(ErrorAsPrimitiveResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<ErrorAsPrimitiveResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<ErrorAsPrimitiveResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      ErrorAsPrimitiveResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ErrorAsPrimitiveResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<ErrorAsPrimitiveResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct ErrorAsPrimitiveRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit ErrorAsPrimitiveRequest(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;
    using ResponseType = ErrorAsPrimitiveResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(_bytes, _byte_size, sizeof(ErrorAsPrimitiveRequest),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL ErrorAsPrimitiveRequest _request(_txid);
        message_.LinearizeAndEncode<ErrorAsPrimitiveRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            ErrorAsPrimitiveRequest* request)
          : message_(bytes, byte_size, sizeof(ErrorAsPrimitiveRequest), nullptr,
                     0, 0) {
        message_.LinearizeAndEncode<ErrorAsPrimitiveRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      ErrorAsPrimitiveRequest& Message() {
        return *reinterpret_cast<ErrorAsPrimitiveRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(ErrorAsPrimitiveRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<ErrorAsPrimitiveRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<ErrorAsPrimitiveRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      ErrorAsPrimitiveRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ErrorAsPrimitiveRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<ErrorAsPrimitiveRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct ErrorAsEnumResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result result;
    explicit ErrorAsEnumResponse(
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result&
            result)
        : result(std::move(result)) {
      _InitHeader();
    }
    ErrorAsEnumResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(
          uint8_t* _bytes, uint32_t _byte_size,
          ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result&
              result)
          : message_(_bytes, _byte_size, sizeof(ErrorAsEnumResponse), nullptr,
                     0, 0) {
        FIDL_ALIGNDECL ErrorAsEnumResponse _response{result};
        message_.LinearizeAndEncode<ErrorAsEnumResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            ErrorAsEnumResponse* response)
          : message_(bytes, byte_size, sizeof(ErrorAsEnumResponse), nullptr, 0,
                     0) {
        message_.LinearizeAndEncode<ErrorAsEnumResponse>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      ErrorAsEnumResponse& Message() {
        return *reinterpret_cast<ErrorAsEnumResponse*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(
          ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result&
              result)
          : message_(bytes_, sizeof(bytes_), result) {}
      explicit OwnedEncodedMessage(ErrorAsEnumResponse* response)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<ErrorAsEnumResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<ErrorAsEnumResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      ErrorAsEnumResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ErrorAsEnumResponse*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* outgoing_message) {
        return DecodedMessage(outgoing_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<ErrorAsEnumResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct ErrorAsEnumRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit ErrorAsEnumRequest(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;
    using ResponseType = ErrorAsEnumResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(_bytes, _byte_size, sizeof(ErrorAsEnumRequest), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL ErrorAsEnumRequest _request(_txid);
        message_.LinearizeAndEncode<ErrorAsEnumRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            ErrorAsEnumRequest* request)
          : message_(bytes, byte_size, sizeof(ErrorAsEnumRequest), nullptr, 0,
                     0) {
        message_.LinearizeAndEncode<ErrorAsEnumRequest>(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
      bool ok() const { return message_.status() == ZX_OK; }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      ErrorAsEnumRequest& Message() {
        return *reinterpret_cast<ErrorAsEnumRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(ErrorAsEnumRequest* request)
          : message_(bytes_, sizeof(bytes_), 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
      bool ok() const { return message_.ok(); }
      const char* error() const { return message_.error(); }

      ::fidl::OutgoingMessage& GetOutgoingMessage() {
        return message_.GetOutgoingMessage();
      }

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[PrimarySize + MaxOutOfLine];
      UnownedEncodedMessage message_;
    };

    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<ErrorAsEnumRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<ErrorAsEnumRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

      ErrorAsEnumRequest* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ErrorAsEnumRequest*>(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(); }

      // These methods should only be used for testing purpose.
      // They create an DecodedMessage using the bytes of an outgoing message
      // and copying the handles.
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          UnownedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }
      static DecodedMessage FromOutgoingWithRawHandleCopy(
          OwnedEncodedMessage* encoded_message) {
        return DecodedMessage(encoded_message->GetOutgoingMessage());
      }

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<ErrorAsEnumRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

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

   public:
    class ResponseAsStruct final : public ::fidl::Result {
     public:
      explicit ResponseAsStruct(zx_handle_t _client);
      ResponseAsStruct(zx_handle_t _client, zx_time_t _deadline);
      explicit ResponseAsStruct(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      ResponseAsStruct(ResponseAsStruct&&) = delete;
      ResponseAsStruct(const ResponseAsStruct&) = delete;
      ResponseAsStruct* operator=(ResponseAsStruct&&) = delete;
      ResponseAsStruct* operator=(const ResponseAsStruct&) = delete;
      ~ResponseAsStruct() = default;

      ResponseAsStructResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ResponseAsStructResponse*>(bytes_);
      }
      const ResponseAsStructResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const ResponseAsStructResponse*>(bytes_);
      }

      ResponseAsStructResponse& value() { return *Unwrap(); }
      const ResponseAsStructResponse& value() const { return *Unwrap(); }

      ResponseAsStructResponse* operator->() { return &value(); }
      const ResponseAsStructResponse* operator->() const { return &value(); }

      ResponseAsStructResponse& operator*() { return value(); }
      const ResponseAsStructResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[ResponseAsStructResponse::PrimarySize +
                     ResponseAsStructResponse::MaxOutOfLine];
    };
    class ErrorAsPrimitive final : public ::fidl::Result {
     public:
      explicit ErrorAsPrimitive(zx_handle_t _client);
      ErrorAsPrimitive(zx_handle_t _client, zx_time_t _deadline);
      explicit ErrorAsPrimitive(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      ErrorAsPrimitive(ErrorAsPrimitive&&) = delete;
      ErrorAsPrimitive(const ErrorAsPrimitive&) = delete;
      ErrorAsPrimitive* operator=(ErrorAsPrimitive&&) = delete;
      ErrorAsPrimitive* operator=(const ErrorAsPrimitive&) = delete;
      ~ErrorAsPrimitive() = default;

      ErrorAsPrimitiveResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ErrorAsPrimitiveResponse*>(bytes_);
      }
      const ErrorAsPrimitiveResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const ErrorAsPrimitiveResponse*>(bytes_);
      }

      ErrorAsPrimitiveResponse& value() { return *Unwrap(); }
      const ErrorAsPrimitiveResponse& value() const { return *Unwrap(); }

      ErrorAsPrimitiveResponse* operator->() { return &value(); }
      const ErrorAsPrimitiveResponse* operator->() const { return &value(); }

      ErrorAsPrimitiveResponse& operator*() { return value(); }
      const ErrorAsPrimitiveResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[ErrorAsPrimitiveResponse::PrimarySize +
                     ErrorAsPrimitiveResponse::MaxOutOfLine];
    };
    class ErrorAsEnum final : public ::fidl::Result {
     public:
      explicit ErrorAsEnum(zx_handle_t _client);
      ErrorAsEnum(zx_handle_t _client, zx_time_t _deadline);
      explicit ErrorAsEnum(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      ErrorAsEnum(ErrorAsEnum&&) = delete;
      ErrorAsEnum(const ErrorAsEnum&) = delete;
      ErrorAsEnum* operator=(ErrorAsEnum&&) = delete;
      ErrorAsEnum* operator=(const ErrorAsEnum&) = delete;
      ~ErrorAsEnum() = default;

      ErrorAsEnumResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ErrorAsEnumResponse*>(bytes_);
      }
      const ErrorAsEnumResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const ErrorAsEnumResponse*>(bytes_);
      }

      ErrorAsEnumResponse& value() { return *Unwrap(); }
      const ErrorAsEnumResponse& value() const { return *Unwrap(); }

      ErrorAsEnumResponse* operator->() { return &value(); }
      const ErrorAsEnumResponse* operator->() const { return &value(); }

      ErrorAsEnumResponse& operator*() { return value(); }
      const ErrorAsEnumResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[ErrorAsEnumResponse::PrimarySize +
                     ErrorAsEnumResponse::MaxOutOfLine];
    };
  };

  // 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;

   public:
    class ResponseAsStruct final : public ::fidl::Result {
     public:
      explicit ResponseAsStruct(zx_handle_t _client, uint8_t* _response_bytes,
                                uint32_t _response_byte_capacity);
      explicit ResponseAsStruct(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      ResponseAsStruct(ResponseAsStruct&&) = delete;
      ResponseAsStruct(const ResponseAsStruct&) = delete;
      ResponseAsStruct* operator=(ResponseAsStruct&&) = delete;
      ResponseAsStruct* operator=(const ResponseAsStruct&) = delete;
      ~ResponseAsStruct() = default;

      ResponseAsStructResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ResponseAsStructResponse*>(bytes_);
      }
      const ResponseAsStructResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const ResponseAsStructResponse*>(bytes_);
      }

      ResponseAsStructResponse& value() { return *Unwrap(); }
      const ResponseAsStructResponse& value() const { return *Unwrap(); }

      ResponseAsStructResponse* operator->() { return &value(); }
      const ResponseAsStructResponse* operator->() const { return &value(); }

      ResponseAsStructResponse& operator*() { return value(); }
      const ResponseAsStructResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
    class ErrorAsPrimitive final : public ::fidl::Result {
     public:
      explicit ErrorAsPrimitive(zx_handle_t _client, uint8_t* _response_bytes,
                                uint32_t _response_byte_capacity);
      explicit ErrorAsPrimitive(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      ErrorAsPrimitive(ErrorAsPrimitive&&) = delete;
      ErrorAsPrimitive(const ErrorAsPrimitive&) = delete;
      ErrorAsPrimitive* operator=(ErrorAsPrimitive&&) = delete;
      ErrorAsPrimitive* operator=(const ErrorAsPrimitive&) = delete;
      ~ErrorAsPrimitive() = default;

      ErrorAsPrimitiveResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ErrorAsPrimitiveResponse*>(bytes_);
      }
      const ErrorAsPrimitiveResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const ErrorAsPrimitiveResponse*>(bytes_);
      }

      ErrorAsPrimitiveResponse& value() { return *Unwrap(); }
      const ErrorAsPrimitiveResponse& value() const { return *Unwrap(); }

      ErrorAsPrimitiveResponse* operator->() { return &value(); }
      const ErrorAsPrimitiveResponse* operator->() const { return &value(); }

      ErrorAsPrimitiveResponse& operator*() { return value(); }
      const ErrorAsPrimitiveResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
    class ErrorAsEnum final : public ::fidl::Result {
     public:
      explicit ErrorAsEnum(zx_handle_t _client, uint8_t* _response_bytes,
                           uint32_t _response_byte_capacity);
      explicit ErrorAsEnum(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      ErrorAsEnum(ErrorAsEnum&&) = delete;
      ErrorAsEnum(const ErrorAsEnum&) = delete;
      ErrorAsEnum* operator=(ErrorAsEnum&&) = delete;
      ErrorAsEnum* operator=(const ErrorAsEnum&) = delete;
      ~ErrorAsEnum() = default;

      ErrorAsEnumResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<ErrorAsEnumResponse*>(bytes_);
      }
      const ErrorAsEnumResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const ErrorAsEnumResponse*>(bytes_);
      }

      ErrorAsEnumResponse& value() { return *Unwrap(); }
      const ErrorAsEnumResponse& value() const { return *Unwrap(); }

      ErrorAsEnumResponse* operator->() { return &value(); }
      const ErrorAsEnumResponse* operator->() const { return &value(); }

      ErrorAsEnumResponse& operator*() { return value(); }
      const ErrorAsEnumResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
  };

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

   public:
    // Allocates 80 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::ResponseAsStruct ResponseAsStruct(
        ::zx::unowned_channel _client_end) {
      return ResultOf::ResponseAsStruct(_client_end->get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::ResponseAsStruct ResponseAsStruct(
        ::zx::unowned_channel _client_end

        ,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::ResponseAsStruct(
          _client_end->get(), _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 64 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::ErrorAsPrimitive ErrorAsPrimitive(
        ::zx::unowned_channel _client_end) {
      return ResultOf::ErrorAsPrimitive(_client_end->get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::ErrorAsPrimitive ErrorAsPrimitive(
        ::zx::unowned_channel _client_end

        ,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::ErrorAsPrimitive(
          _client_end->get(), _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 64 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::ErrorAsEnum ErrorAsEnum(
        ::zx::unowned_channel _client_end) {
      return ResultOf::ErrorAsEnum(_client_end->get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::ErrorAsEnum ErrorAsEnum(
        ::zx::unowned_channel _client_end

        ,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::ErrorAsEnum(
          _client_end->get(), _response_buffer.data, _response_buffer.capacity);
    }
  };

  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 80 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::ResponseAsStruct ResponseAsStruct() {
      return ResultOf::ResponseAsStruct(this->channel().get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::ResponseAsStruct ResponseAsStruct(
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::ResponseAsStruct(this->channel().get(),
                                               _response_buffer.data,
                                               _response_buffer.capacity);
    }

    // Allocates 64 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::ErrorAsPrimitive ErrorAsPrimitive() {
      return ResultOf::ErrorAsPrimitive(this->channel().get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::ErrorAsPrimitive ErrorAsPrimitive(
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::ErrorAsPrimitive(this->channel().get(),
                                               _response_buffer.data,
                                               _response_buffer.capacity);
    }

    // Allocates 64 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::ErrorAsEnum ErrorAsEnum() {
      return ResultOf::ErrorAsEnum(this->channel().get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::ErrorAsEnum ErrorAsEnum(
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::ErrorAsEnum(this->channel().get(),
                                          _response_buffer.data,
                                          _response_buffer.capacity);
    }

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

  struct AsyncEventHandlers;
  class ResponseAsStructResponseContext;
  class ErrorAsPrimitiveResponseContext;
  class ErrorAsEnumResponseContext;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  class Interface : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    Interface() = default;
    virtual ~Interface() = default;

    // The marker protocol type within which this |Interface| class is defined.
    using _EnclosingProtocol = WithErrorSyntax;

    class ResponseAsStructCompleterBase : 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(::llcpp::fidl::test::protocols::
                               WithErrorSyntax_ResponseAsStruct_Result result);
      ::fidl::Result ReplySuccess(int64_t a, int64_t b, int64_t c);
      ::fidl::Result ReplyError(uint32_t error);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer,
                           ::llcpp::fidl::test::protocols::
                               WithErrorSyntax_ResponseAsStruct_Result result);
      ::fidl::Result ReplySuccess(::fidl::BufferSpan _buffer, int64_t a,
                                  int64_t b, int64_t c);

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

    using ResponseAsStructCompleter =
        ::fidl::Completer<ResponseAsStructCompleterBase>;

    virtual void ResponseAsStruct(
        ResponseAsStructCompleter::Sync& _completer) = 0;

    class ErrorAsPrimitiveCompleterBase : 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(::llcpp::fidl::test::protocols::
                               WithErrorSyntax_ErrorAsPrimitive_Result result);
      ::fidl::Result ReplySuccess();
      ::fidl::Result ReplyError(uint32_t error);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer,
                           ::llcpp::fidl::test::protocols::
                               WithErrorSyntax_ErrorAsPrimitive_Result result);
      ::fidl::Result ReplySuccess(::fidl::BufferSpan _buffer);

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

    using ErrorAsPrimitiveCompleter =
        ::fidl::Completer<ErrorAsPrimitiveCompleterBase>;

    virtual void ErrorAsPrimitive(
        ErrorAsPrimitiveCompleter::Sync& _completer) = 0;

    class ErrorAsEnumCompleterBase : 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(
          ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result
              result);
      ::fidl::Result ReplySuccess();
      ::fidl::Result ReplyError(ErrorEnun error);
      ::fidl::Result Reply(
          ::fidl::BufferSpan _buffer,
          ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result
              result);
      ::fidl::Result ReplySuccess(::fidl::BufferSpan _buffer);

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

    using ErrorAsEnumCompleter = ::fidl::Completer<ErrorAsEnumCompleterBase>;

    virtual void ErrorAsEnum(ErrorAsEnumCompleter::Sync& _completer) = 0;

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

  // 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 ::fidl::DispatchResult TryDispatch(Interface* impl,
                                            fidl_incoming_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 ::fidl::DispatchResult Dispatch(Interface* impl,
                                         fidl_incoming_msg_t* msg,
                                         ::fidl::Transaction* txn);

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

  class EventSender;
  class WeakEventSender;
};

}  // namespace protocols
}  // namespace test
}  // namespace fidl
}  // namespace llcpp

namespace fidl {

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::obj_type>
    : public std::true_type {};

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Response>
    : public std::true_type {};
template <>
struct IsStruct<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Response>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::llcpp::fidl::test::protocols::
                                  WithErrorSyntax_ResponseAsStruct_Response>);
static_assert(offsetof(::llcpp::fidl::test::protocols::
                           WithErrorSyntax_ResponseAsStruct_Response,
                       a) == 0);
static_assert(offsetof(::llcpp::fidl::test::protocols::
                           WithErrorSyntax_ResponseAsStruct_Response,
                       b) == 8);
static_assert(offsetof(::llcpp::fidl::test::protocols::
                           WithErrorSyntax_ResponseAsStruct_Response,
                       c) == 16);
static_assert(sizeof(::llcpp::fidl::test::protocols::
                         WithErrorSyntax_ResponseAsStruct_Response) ==
              ::llcpp::fidl::test::protocols::
                  WithErrorSyntax_ResponseAsStruct_Response::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Result>
    : public std::true_type {};
template <>
struct IsUnion<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Result>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::llcpp::fidl::test::protocols::
                                  WithErrorSyntax_ResponseAsStruct_Result>);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Response>
    : public std::true_type {};
template <>
struct IsStruct<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Response>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::llcpp::fidl::test::protocols::
                                  WithErrorSyntax_ErrorAsPrimitive_Response>);
static_assert(offsetof(::llcpp::fidl::test::protocols::
                           WithErrorSyntax_ErrorAsPrimitive_Response,
                       __reserved) == 0);
static_assert(sizeof(::llcpp::fidl::test::protocols::
                         WithErrorSyntax_ErrorAsPrimitive_Response) ==
              ::llcpp::fidl::test::protocols::
                  WithErrorSyntax_ErrorAsPrimitive_Response::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Result>
    : public std::true_type {};
template <>
struct IsUnion<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Result>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::llcpp::fidl::test::protocols::
                                  WithErrorSyntax_ErrorAsPrimitive_Result>);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response>
    : public std::true_type {};
template <>
struct IsStruct<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response>);
static_assert(
    offsetof(
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response,
        __reserved) == 0);
static_assert(
    sizeof(
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response) ==
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response::
        PrimarySize);

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::Transitional::RequestRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::Transitional::RequestRequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::Transitional::RequestRequest) ==
    ::llcpp::fidl::test::protocols::Transitional::RequestRequest::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::Transitional::RequestRequest, x) ==
    16);

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::Transitional::RequestResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::Transitional::RequestResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::Transitional::RequestResponse) ==
    ::llcpp::fidl::test::protocols::Transitional::RequestResponse::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::Transitional::RequestResponse,
             y) == 16);

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::Transitional::OneWayRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::Transitional::OneWayRequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::Transitional::OneWayRequest) ==
    ::llcpp::fidl::test::protocols::Transitional::OneWayRequest::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::Transitional::OneWayRequest, x) ==
    16);

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::Transitional::EventResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::Transitional::EventResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::Transitional::EventResponse) ==
    ::llcpp::fidl::test::protocols::Transitional::EventResponse::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::Transitional::EventResponse, x) ==
    16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodARequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodARequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::ChannelProtocol::MethodARequest) ==
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodARequest::
        PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::ChannelProtocol::MethodARequest,
             a) == 16);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::ChannelProtocol::MethodARequest,
             b) == 24);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::ChannelProtocol::EventAResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::ChannelProtocol::EventAResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::ChannelProtocol::EventAResponse) ==
    ::llcpp::fidl::test::protocols::ChannelProtocol::EventAResponse::
        PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::ChannelProtocol::EventAResponse,
             a) == 16);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::ChannelProtocol::EventAResponse,
             b) == 24);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodBRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodBRequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::ChannelProtocol::MethodBRequest) ==
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodBRequest::
        PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::ChannelProtocol::MethodBRequest,
             a) == 16);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::ChannelProtocol::MethodBRequest,
             b) == 24);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodBResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodBResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::ChannelProtocol::MethodBResponse) ==
    ::llcpp::fidl::test::protocols::ChannelProtocol::MethodBResponse::
        PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::ChannelProtocol::MethodBResponse,
             result) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleRequest>
    : public std::true_type {};
static_assert(
    sizeof(
        ::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleRequest) ==
    ::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleRequest::
        PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleRequest,
             h) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleResponse>
    : public std::true_type {};
static_assert(
    sizeof(
        ::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleResponse) ==
    ::llcpp::fidl::test::protocols::ChannelProtocol::TakeHandleResponse::
        PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MutateSocketRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MutateSocketRequest>
    : public std::true_type {};
static_assert(
    sizeof(
        ::llcpp::fidl::test::protocols::ChannelProtocol::MutateSocketRequest) ==
    ::llcpp::fidl::test::protocols::ChannelProtocol::MutateSocketRequest::
        PrimarySize);
static_assert(
    offsetof(
        ::llcpp::fidl::test::protocols::ChannelProtocol::MutateSocketRequest,
        a) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MutateSocketResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::ChannelProtocol::MutateSocketResponse>
    : public std::true_type {};
static_assert(sizeof(::llcpp::fidl::test::protocols::ChannelProtocol::
                         MutateSocketResponse) ==
              ::llcpp::fidl::test::protocols::ChannelProtocol::
                  MutateSocketResponse::PrimarySize);
static_assert(
    offsetof(
        ::llcpp::fidl::test::protocols::ChannelProtocol::MutateSocketResponse,
        b) == 16);

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::
                      WithAndWithoutRequestResponse::NoRequestNoResponseRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestNoResponseRequest> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               NoRequestNoResponseRequest) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestNoResponseRequest::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestEmptyResponseRequest> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestEmptyResponseRequest> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               NoRequestEmptyResponseRequest) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestEmptyResponseRequest::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestEmptyResponseResponse> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestEmptyResponseResponse> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               NoRequestEmptyResponseResponse) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestEmptyResponseResponse::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestWithResponseRequest> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestWithResponseRequest> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               NoRequestWithResponseRequest) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestWithResponseRequest::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestWithResponseResponse> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestWithResponseResponse> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               NoRequestWithResponseResponse) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        NoRequestWithResponseResponse::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
                 NoRequestWithResponseResponse,
             ret) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestNoResponseRequest> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestNoResponseRequest> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               WithRequestNoResponseRequest) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestNoResponseRequest::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
                 WithRequestNoResponseRequest,
             arg) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestEmptyResponseRequest> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestEmptyResponseRequest> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               WithRequestEmptyResponseRequest) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestEmptyResponseRequest::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
                 WithRequestEmptyResponseRequest,
             arg) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestEmptyResponseResponse> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestEmptyResponseResponse> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               WithRequestEmptyResponseResponse) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestEmptyResponseResponse::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestWithResponseRequest> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestWithResponseRequest> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               WithRequestWithResponseRequest) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestWithResponseRequest::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
                 WithRequestWithResponseRequest,
             arg) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestWithResponseResponse> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestWithResponseResponse> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               WithRequestWithResponseResponse) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        WithRequestWithResponseResponse::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
                 WithRequestWithResponseResponse,
             ret) == 16);

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::
                      WithAndWithoutRequestResponse::OnEmptyResponseResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fidl::test::protocols::
                         WithAndWithoutRequestResponse::OnEmptyResponseResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               OnEmptyResponseResponse) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        OnEmptyResponseResponse::PrimarySize);

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::
                      WithAndWithoutRequestResponse::OnWithResponseResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fidl::test::protocols::
                         WithAndWithoutRequestResponse::OnWithResponseResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
               OnWithResponseResponse) ==
    ::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
        OnWithResponseResponse::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocols::WithAndWithoutRequestResponse::
                 OnWithResponseResponse,
             ret) == 16);

template <>
struct IsFidlType<::llcpp::fidl::test::protocols::ErrorEnun>
    : public std::true_type {};

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result>
    : public std::true_type {};
template <>
struct IsUnion<
    ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<
        ::llcpp::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result>);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ResponseAsStructRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ResponseAsStructRequest>
    : public std::true_type {};
static_assert(sizeof(::llcpp::fidl::test::protocols::WithErrorSyntax::
                         ResponseAsStructRequest) ==
              ::llcpp::fidl::test::protocols::WithErrorSyntax::
                  ResponseAsStructRequest::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ResponseAsStructResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ResponseAsStructResponse>
    : public std::true_type {};
static_assert(sizeof(::llcpp::fidl::test::protocols::WithErrorSyntax::
                         ResponseAsStructResponse) ==
              ::llcpp::fidl::test::protocols::WithErrorSyntax::
                  ResponseAsStructResponse::PrimarySize);
static_assert(offsetof(::llcpp::fidl::test::protocols::WithErrorSyntax::
                           ResponseAsStructResponse,
                       result) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsPrimitiveRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsPrimitiveRequest>
    : public std::true_type {};
static_assert(sizeof(::llcpp::fidl::test::protocols::WithErrorSyntax::
                         ErrorAsPrimitiveRequest) ==
              ::llcpp::fidl::test::protocols::WithErrorSyntax::
                  ErrorAsPrimitiveRequest::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsPrimitiveResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsPrimitiveResponse>
    : public std::true_type {};
static_assert(sizeof(::llcpp::fidl::test::protocols::WithErrorSyntax::
                         ErrorAsPrimitiveResponse) ==
              ::llcpp::fidl::test::protocols::WithErrorSyntax::
                  ErrorAsPrimitiveResponse::PrimarySize);
static_assert(offsetof(::llcpp::fidl::test::protocols::WithErrorSyntax::
                           ErrorAsPrimitiveResponse,
                       result) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumRequest>
    : public std::true_type {};
static_assert(
    sizeof(
        ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumRequest) ==
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumRequest::
        PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumResponse>
    : public std::true_type {};
static_assert(
    sizeof(
        ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumResponse) ==
    ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumResponse::
        PrimarySize);
static_assert(
    offsetof(
        ::llcpp::fidl::test::protocols::WithErrorSyntax::ErrorAsEnumResponse,
        result) == 16);

}  // namespace fidl

namespace llcpp {

namespace fidl {
namespace test {
namespace protocols {

struct Transitional::AsyncEventHandlers {
  ::fit::function<void(EventResponse* msg)> event;
};

class Transitional::RequestResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  RequestResponseContext();

  virtual void OnReply(Transitional::RequestResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class Transitional::ClientImpl final : private ::fidl::internal::ClientBase {
 public:
  // Asynchronous variant of |Transitional.Request()|. Allocates 24 bytes of
  // request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result Request(int64_t x,
                         ::fit::callback<void(RequestResponse* response)> _cb);
  // Asynchronous variant of |Transitional.Request()|. 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 Request(::fidl::BufferSpan _request_buffer, int64_t x,
                         RequestResponseContext* _context);
  // Synchronous variant of |Transitional.Request()|. Allocates 48 bytes of
  // message buffer on the stack. No heap allocation necessary.
  ResultOf::Request Request_Sync(int64_t x);

  // Synchronous variant of |Transitional.Request()|. Caller provides the
  // backing storage for FIDL message via request and response buffers.
  UnownedResultOf::Request Request_Sync(::fidl::BufferSpan _request_buffer,
                                        int64_t x,
                                        ::fidl::BufferSpan _response_buffer);

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result OneWay(int64_t x);

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::Result OneWay(::fidl::BufferSpan _request_buffer, int64_t x);

 private:
  friend class ::fidl::Client<Transitional>;

  explicit ClientImpl(AsyncEventHandlers handlers)
      : handlers_(std::move(handlers)) {}

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

  AsyncEventHandlers handlers_;
};

// |EventSender| owns a server endpoint of a channel speaking
// the Transitional protocol, and can send events in that protocol.
class Transitional::EventSender {
 public:
  // Constructs an event sender with an invalid channel.
  EventSender() = default;

  // TODO(fxbug.dev/65212): EventSender should take a ::fidl::ServerEnd.
  explicit EventSender(::zx::channel server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::zx::channel& channel() const { return server_end_; }
  ::zx::channel& channel() { return server_end_; }

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

  zx_status_t Event(int64_t x) const;

  // Caller provides the backing storage for FIDL message via response buffers.
  zx_status_t Event(::fidl::BufferSpan _buffer, int64_t x) const;

 private:
  ::zx::channel server_end_;
};

class Transitional::WeakEventSender {
 public:
  zx_status_t Event(int64_t x) const {
    if (auto _binding = binding_.lock()) {
      return _binding->event_sender().Event(std::move(x));
    }
    return ZX_ERR_CANCELED;
  }

  // Caller provides the backing storage for FIDL message via response buffers.
  zx_status_t Event(::fidl::BufferSpan _buffer, int64_t x) const {
    if (auto _binding = binding_.lock()) {
      return _binding->event_sender().Event(std::move(_buffer), std::move(x));
    }
    return ZX_ERR_CANCELED;
  }

 private:
  friend class ::fidl::ServerBindingRef<Transitional>;

  explicit WeakEventSender(
      std::weak_ptr<::fidl::internal::AsyncServerBinding<Transitional>> binding)
      : binding_(std::move(binding)) {}

  std::weak_ptr<::fidl::internal::AsyncServerBinding<Transitional>> binding_;
};

struct ChannelProtocol::AsyncEventHandlers {
  ::fit::function<void(EventAResponse* msg)> event_a;
};

class ChannelProtocol::MethodBResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  MethodBResponseContext();

  virtual void OnReply(ChannelProtocol::MethodBResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class ChannelProtocol::TakeHandleResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  TakeHandleResponseContext();

  virtual void OnReply(ChannelProtocol::TakeHandleResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class ChannelProtocol::MutateSocketResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  MutateSocketResponseContext();

  virtual void OnReply(ChannelProtocol::MutateSocketResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class ChannelProtocol::ClientImpl final : private ::fidl::internal::ClientBase {
 public:
  // Allocates 32 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result MethodA(int64_t a, int64_t b);

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::Result MethodA(::fidl::BufferSpan _request_buffer, int64_t a,
                         int64_t b);

  // Asynchronous variant of |ChannelProtocol.MethodB()|. Allocates 32 bytes of
  // request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result MethodB(int64_t a, int64_t b,
                         ::fit::callback<void(MethodBResponse* response)> _cb);
  // Asynchronous variant of |ChannelProtocol.MethodB()|. 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 MethodB(::fidl::BufferSpan _request_buffer, int64_t a,
                         int64_t b, MethodBResponseContext* _context);
  // Synchronous variant of |ChannelProtocol.MethodB()|. Allocates 56 bytes of
  // message buffer on the stack. No heap allocation necessary.
  ResultOf::MethodB MethodB_Sync(int64_t a, int64_t b);

  // Synchronous variant of |ChannelProtocol.MethodB()|. Caller provides the
  // backing storage for FIDL message via request and response buffers.
  UnownedResultOf::MethodB MethodB_Sync(::fidl::BufferSpan _request_buffer,
                                        int64_t a, int64_t b,
                                        ::fidl::BufferSpan _response_buffer);

  // Asynchronous variant of |ChannelProtocol.TakeHandle()|. Allocates 24 bytes
  // of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result TakeHandle(
      ::zx::handle h, ::fit::callback<void(TakeHandleResponse* response)> _cb);
  // Asynchronous variant of |ChannelProtocol.TakeHandle()|. 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 TakeHandle(::fidl::BufferSpan _request_buffer, ::zx::handle h,
                            TakeHandleResponseContext* _context);
  // Synchronous variant of |ChannelProtocol.TakeHandle()|. Allocates 40 bytes
  // of message buffer on the stack. No heap allocation necessary.
  ResultOf::TakeHandle TakeHandle_Sync(::zx::handle h);

  // Synchronous variant of |ChannelProtocol.TakeHandle()|. Caller provides the
  // backing storage for FIDL message via request and response buffers.
  UnownedResultOf::TakeHandle TakeHandle_Sync(
      ::fidl::BufferSpan _request_buffer, ::zx::handle h,
      ::fidl::BufferSpan _response_buffer);

  // Asynchronous variant of |ChannelProtocol.MutateSocket()|. Allocates 24
  // bytes of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result MutateSocket(
      ::zx::socket a,
      ::fit::callback<void(MutateSocketResponse* response)> _cb);
  // Asynchronous variant of |ChannelProtocol.MutateSocket()|. 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 MutateSocket(::fidl::BufferSpan _request_buffer,
                              ::zx::socket a,
                              MutateSocketResponseContext* _context);
  // Synchronous variant of |ChannelProtocol.MutateSocket()|. Allocates 48 bytes
  // of message buffer on the stack. No heap allocation necessary.
  ResultOf::MutateSocket MutateSocket_Sync(::zx::socket a);

  // Synchronous variant of |ChannelProtocol.MutateSocket()|. Caller provides
  // the backing storage for FIDL message via request and response buffers.
  UnownedResultOf::MutateSocket MutateSocket_Sync(
      ::fidl::BufferSpan _request_buffer, ::zx::socket a,
      ::fidl::BufferSpan _response_buffer);

 private:
  friend class ::fidl::Client<ChannelProtocol>;

  explicit ClientImpl(AsyncEventHandlers handlers)
      : handlers_(std::move(handlers)) {}

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

  AsyncEventHandlers handlers_;
};

// |EventSender| owns a server endpoint of a channel speaking
// the ChannelProtocol protocol, and can send events in that protocol.
class ChannelProtocol::EventSender {
 public:
  // Constructs an event sender with an invalid channel.
  EventSender() = default;

  // TODO(fxbug.dev/65212): EventSender should take a ::fidl::ServerEnd.
  explicit EventSender(::zx::channel server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::zx::channel& channel() const { return server_end_; }
  ::zx::channel& channel() { return server_end_; }

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

  zx_status_t EventA(int64_t a, int64_t b) const;

  // Caller provides the backing storage for FIDL message via response buffers.
  zx_status_t EventA(::fidl::BufferSpan _buffer, int64_t a, int64_t b) const;

 private:
  ::zx::channel server_end_;
};

class ChannelProtocol::WeakEventSender {
 public:
  zx_status_t EventA(int64_t a, int64_t b) const {
    if (auto _binding = binding_.lock()) {
      return _binding->event_sender().EventA(std::move(a), std::move(b));
    }
    return ZX_ERR_CANCELED;
  }

  // Caller provides the backing storage for FIDL message via response buffers.
  zx_status_t EventA(::fidl::BufferSpan _buffer, int64_t a, int64_t b) const {
    if (auto _binding = binding_.lock()) {
      return _binding->event_sender().EventA(std::move(_buffer), std::move(a),
                                             std::move(b));
    }
    return ZX_ERR_CANCELED;
  }

 private:
  friend class ::fidl::ServerBindingRef<ChannelProtocol>;

  explicit WeakEventSender(
      std::weak_ptr<::fidl::internal::AsyncServerBinding<ChannelProtocol>>
          binding)
      : binding_(std::move(binding)) {}

  std::weak_ptr<::fidl::internal::AsyncServerBinding<ChannelProtocol>> binding_;
};

struct WithAndWithoutRequestResponse::AsyncEventHandlers {
  ::fit::function<void()> on_empty_response;

  ::fit::function<void(OnWithResponseResponse* msg)> on_with_response;
};

class WithAndWithoutRequestResponse::NoRequestEmptyResponseResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  NoRequestEmptyResponseResponseContext();

  virtual void OnReply(
      WithAndWithoutRequestResponse::NoRequestEmptyResponseResponse*
          message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class WithAndWithoutRequestResponse::NoRequestWithResponseResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  NoRequestWithResponseResponseContext();

  virtual void OnReply(
      WithAndWithoutRequestResponse::NoRequestWithResponseResponse*
          message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class WithAndWithoutRequestResponse::WithRequestEmptyResponseResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  WithRequestEmptyResponseResponseContext();

  virtual void OnReply(
      WithAndWithoutRequestResponse::WithRequestEmptyResponseResponse*
          message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class WithAndWithoutRequestResponse::WithRequestWithResponseResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  WithRequestWithResponseResponseContext();

  virtual void OnReply(
      WithAndWithoutRequestResponse::WithRequestWithResponseResponse*
          message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class WithAndWithoutRequestResponse::ClientImpl final
    : private ::fidl::internal::ClientBase {
 public:
  // Allocates 16 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result NoRequestNoResponse();

  // Asynchronous variant of
  // |WithAndWithoutRequestResponse.NoRequestEmptyResponse()|. Allocates 16
  // bytes of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result NoRequestEmptyResponse(
      ::fit::callback<void(NoRequestEmptyResponseResponse* response)> _cb);
  // Asynchronous variant of
  // |WithAndWithoutRequestResponse.NoRequestEmptyResponse()|. 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 NoRequestEmptyResponse(
      NoRequestEmptyResponseResponseContext* _context);
  // Synchronous variant of
  // |WithAndWithoutRequestResponse.NoRequestEmptyResponse()|. Allocates 32
  // bytes of message buffer on the stack. No heap allocation necessary.
  ResultOf::NoRequestEmptyResponse NoRequestEmptyResponse_Sync();

  // Asynchronous variant of
  // |WithAndWithoutRequestResponse.NoRequestWithResponse()|. Allocates 16 bytes
  // of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result NoRequestWithResponse(
      ::fit::callback<void(NoRequestWithResponseResponse* response)> _cb);
  // Asynchronous variant of
  // |WithAndWithoutRequestResponse.NoRequestWithResponse()|. 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 NoRequestWithResponse(
      NoRequestWithResponseResponseContext* _context);
  // Synchronous variant of
  // |WithAndWithoutRequestResponse.NoRequestWithResponse()|. Allocates 16 bytes
  // of request buffer on the stack. Response is heap-allocated.
  ResultOf::NoRequestWithResponse NoRequestWithResponse_Sync();

  // Synchronous variant of
  // |WithAndWithoutRequestResponse.NoRequestWithResponse()|. Caller provides
  // the backing storage for FIDL message via request and response buffers.
  UnownedResultOf::NoRequestWithResponse NoRequestWithResponse_Sync(
      ::fidl::BufferSpan _response_buffer);

  // Request is heap-allocated.
  ::fidl::Result WithRequestNoResponse(::fidl::StringView arg);

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::Result WithRequestNoResponse(::fidl::BufferSpan _request_buffer,
                                       ::fidl::StringView arg);

  // Asynchronous variant of
  // |WithAndWithoutRequestResponse.WithRequestEmptyResponse()|. The request and
  // callback are allocated on the heap.
  ::fidl::Result WithRequestEmptyResponse(
      ::fidl::StringView arg,
      ::fit::callback<void(WithRequestEmptyResponseResponse* response)> _cb);
  // Asynchronous variant of
  // |WithAndWithoutRequestResponse.WithRequestEmptyResponse()|. 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 WithRequestEmptyResponse(
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView arg,
      WithRequestEmptyResponseResponseContext* _context);
  // Synchronous variant of
  // |WithAndWithoutRequestResponse.WithRequestEmptyResponse()|. Allocates 16
  // bytes of response buffer on the stack. Request is heap-allocated.
  ResultOf::WithRequestEmptyResponse WithRequestEmptyResponse_Sync(
      ::fidl::StringView arg);

  // Synchronous variant of
  // |WithAndWithoutRequestResponse.WithRequestEmptyResponse()|. Caller provides
  // the backing storage for FIDL message via request and response buffers.
  UnownedResultOf::WithRequestEmptyResponse WithRequestEmptyResponse_Sync(
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView arg,
      ::fidl::BufferSpan _response_buffer);

  // Asynchronous variant of
  // |WithAndWithoutRequestResponse.WithRequestWithResponse()|. The request and
  // callback are allocated on the heap.
  ::fidl::Result WithRequestWithResponse(
      ::fidl::StringView arg,
      ::fit::callback<void(WithRequestWithResponseResponse* response)> _cb);
  // Asynchronous variant of
  // |WithAndWithoutRequestResponse.WithRequestWithResponse()|. 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 WithRequestWithResponse(
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView arg,
      WithRequestWithResponseResponseContext* _context);
  // Synchronous variant of
  // |WithAndWithoutRequestResponse.WithRequestWithResponse()|. Request is
  // heap-allocated. Response is heap-allocated.
  ResultOf::WithRequestWithResponse WithRequestWithResponse_Sync(
      ::fidl::StringView arg);

  // Synchronous variant of
  // |WithAndWithoutRequestResponse.WithRequestWithResponse()|. Caller provides
  // the backing storage for FIDL message via request and response buffers.
  UnownedResultOf::WithRequestWithResponse WithRequestWithResponse_Sync(
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView arg,
      ::fidl::BufferSpan _response_buffer);

 private:
  friend class ::fidl::Client<WithAndWithoutRequestResponse>;

  explicit ClientImpl(AsyncEventHandlers handlers)
      : handlers_(std::move(handlers)) {}

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

  AsyncEventHandlers handlers_;
};

// |EventSender| owns a server endpoint of a channel speaking
// the WithAndWithoutRequestResponse protocol, and can send events in that
// protocol.
class WithAndWithoutRequestResponse::EventSender {
 public:
  // Constructs an event sender with an invalid channel.
  EventSender() = default;

  // TODO(fxbug.dev/65212): EventSender should take a ::fidl::ServerEnd.
  explicit EventSender(::zx::channel server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::zx::channel& channel() const { return server_end_; }
  ::zx::channel& channel() { return server_end_; }

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

  zx_status_t OnEmptyResponse() const;

  zx_status_t OnWithResponse(::fidl::StringView ret) const;

  // Caller provides the backing storage for FIDL message via response buffers.
  zx_status_t OnWithResponse(::fidl::BufferSpan _buffer,
                             ::fidl::StringView ret) const;

 private:
  ::zx::channel server_end_;
};

class WithAndWithoutRequestResponse::WeakEventSender {
 public:
  zx_status_t OnEmptyResponse() const {
    if (auto _binding = binding_.lock()) {
      return _binding->event_sender().OnEmptyResponse();
    }
    return ZX_ERR_CANCELED;
  }

  zx_status_t OnWithResponse(::fidl::StringView ret) const {
    if (auto _binding = binding_.lock()) {
      return _binding->event_sender().OnWithResponse(std::move(ret));
    }
    return ZX_ERR_CANCELED;
  }

  // Caller provides the backing storage for FIDL message via response buffers.
  zx_status_t OnWithResponse(::fidl::BufferSpan _buffer,
                             ::fidl::StringView ret) const {
    if (auto _binding = binding_.lock()) {
      return _binding->event_sender().OnWithResponse(std::move(_buffer),
                                                     std::move(ret));
    }
    return ZX_ERR_CANCELED;
  }

 private:
  friend class ::fidl::ServerBindingRef<WithAndWithoutRequestResponse>;

  explicit WeakEventSender(
      std::weak_ptr<
          ::fidl::internal::AsyncServerBinding<WithAndWithoutRequestResponse>>
          binding)
      : binding_(std::move(binding)) {}

  std::weak_ptr<
      ::fidl::internal::AsyncServerBinding<WithAndWithoutRequestResponse>>
      binding_;
};

struct WithErrorSyntax::AsyncEventHandlers {};

class WithErrorSyntax::ResponseAsStructResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  ResponseAsStructResponseContext();

  virtual void OnReply(WithErrorSyntax::ResponseAsStructResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class WithErrorSyntax::ErrorAsPrimitiveResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  ErrorAsPrimitiveResponseContext();

  virtual void OnReply(WithErrorSyntax::ErrorAsPrimitiveResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class WithErrorSyntax::ErrorAsEnumResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  ErrorAsEnumResponseContext();

  virtual void OnReply(WithErrorSyntax::ErrorAsEnumResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class WithErrorSyntax::ClientImpl final : private ::fidl::internal::ClientBase {
 public:
  // Asynchronous variant of |WithErrorSyntax.ResponseAsStruct()|. Allocates 16
  // bytes of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result ResponseAsStruct(
      ::fit::callback<void(ResponseAsStructResponse* response)> _cb);
  // Asynchronous variant of |WithErrorSyntax.ResponseAsStruct()|. 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 ResponseAsStruct(ResponseAsStructResponseContext* _context);
  // Synchronous variant of |WithErrorSyntax.ResponseAsStruct()|. Allocates 80
  // bytes of message buffer on the stack. No heap allocation necessary.
  ResultOf::ResponseAsStruct ResponseAsStruct_Sync();

  // Synchronous variant of |WithErrorSyntax.ResponseAsStruct()|. Caller
  // provides the backing storage for FIDL message via request and response
  // buffers.
  UnownedResultOf::ResponseAsStruct ResponseAsStruct_Sync(
      ::fidl::BufferSpan _response_buffer);

  // Asynchronous variant of |WithErrorSyntax.ErrorAsPrimitive()|. Allocates 16
  // bytes of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result ErrorAsPrimitive(
      ::fit::callback<void(ErrorAsPrimitiveResponse* response)> _cb);
  // Asynchronous variant of |WithErrorSyntax.ErrorAsPrimitive()|. 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 ErrorAsPrimitive(ErrorAsPrimitiveResponseContext* _context);
  // Synchronous variant of |WithErrorSyntax.ErrorAsPrimitive()|. Allocates 64
  // bytes of message buffer on the stack. No heap allocation necessary.
  ResultOf::ErrorAsPrimitive ErrorAsPrimitive_Sync();

  // Synchronous variant of |WithErrorSyntax.ErrorAsPrimitive()|. Caller
  // provides the backing storage for FIDL message via request and response
  // buffers.
  UnownedResultOf::ErrorAsPrimitive ErrorAsPrimitive_Sync(
      ::fidl::BufferSpan _response_buffer);

  // Asynchronous variant of |WithErrorSyntax.ErrorAsEnum()|. Allocates 16 bytes
  // of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result ErrorAsEnum(
      ::fit::callback<void(ErrorAsEnumResponse* response)> _cb);
  // Asynchronous variant of |WithErrorSyntax.ErrorAsEnum()|. 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 ErrorAsEnum(ErrorAsEnumResponseContext* _context);
  // Synchronous variant of |WithErrorSyntax.ErrorAsEnum()|. Allocates 64 bytes
  // of message buffer on the stack. No heap allocation necessary.
  ResultOf::ErrorAsEnum ErrorAsEnum_Sync();

  // Synchronous variant of |WithErrorSyntax.ErrorAsEnum()|. Caller provides the
  // backing storage for FIDL message via request and response buffers.
  UnownedResultOf::ErrorAsEnum ErrorAsEnum_Sync(
      ::fidl::BufferSpan _response_buffer);

 private:
  friend class ::fidl::Client<WithErrorSyntax>;

  explicit ClientImpl(AsyncEventHandlers handlers)
      : handlers_(std::move(handlers)) {}

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

  AsyncEventHandlers handlers_;
};

// |EventSender| owns a server endpoint of a channel speaking
// the WithErrorSyntax protocol, and can send events in that protocol.
class WithErrorSyntax::EventSender {
 public:
  // Constructs an event sender with an invalid channel.
  EventSender() = default;

  // TODO(fxbug.dev/65212): EventSender should take a ::fidl::ServerEnd.
  explicit EventSender(::zx::channel server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::zx::channel& channel() const { return server_end_; }
  ::zx::channel& channel() { return server_end_; }

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

 private:
  ::zx::channel server_end_;
};

class WithErrorSyntax::WeakEventSender {
 public:
 private:
  friend class ::fidl::ServerBindingRef<WithErrorSyntax>;

  explicit WeakEventSender(
      std::weak_ptr<::fidl::internal::AsyncServerBinding<WithErrorSyntax>>
          binding)
      : binding_(std::move(binding)) {}

  std::weak_ptr<::fidl::internal::AsyncServerBinding<WithErrorSyntax>> binding_;
};

}  // namespace protocols
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
