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

#pragma once

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

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

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

namespace fidl_test_error {
namespace wire {
struct Example_foo_Response;

class Example_foo_Result;
}  // namespace wire
class Example;
namespace wire {

extern "C" const fidl_type_t fidl_test_error_Example_foo_ResultTable;

class Example_foo_Result {
 public:
  Example_foo_Result()
      : ordinal_(::fidl_test_error::wire::Example_foo_Result::Ordinal::Invalid),
        envelope_{} {}

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

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

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

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

  static Example_foo_Result WithResponse(
      ::fidl::ObjectView<::fidl_test_error::wire::Example_foo_Response> val) {
    Example_foo_Result result;
    result.set_response(val);
    return result;
  }

  template <typename... Args>
  static Example_foo_Result WithResponse(::fidl::AnyAllocator& allocator,
                                         Args&&... args) {
    Example_foo_Result result;
    result.set_response(
        ::fidl::ObjectView<::fidl_test_error::wire::Example_foo_Response>(
            allocator, std::forward<Args>(args)...));
    return result;
  }

  void set_response(
      ::fidl::ObjectView<::fidl_test_error::wire::Example_foo_Response> elem) {
    ordinal_ = ::fidl_test_error::wire::Example_foo_Result::Ordinal::kResponse;
    envelope_.data =
        ::fidl::ObjectView<void>::FromExternal(static_cast<void*>(elem.get()));
  }

  template <typename... Args>
  void set_response(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = ::fidl_test_error::wire::Example_foo_Result::Ordinal::kResponse;
    set_response(
        ::fidl::ObjectView<::fidl_test_error::wire::Example_foo_Response>(
            allocator, std::forward<Args>(args)...));
  }

  ::fidl_test_error::wire::Example_foo_Response& mutable_response() {
    ZX_ASSERT(ordinal_ ==
              ::fidl_test_error::wire::Example_foo_Result::Ordinal::kResponse);
    return *static_cast<::fidl_test_error::wire::Example_foo_Response*>(
        envelope_.data.get());
  }
  const ::fidl_test_error::wire::Example_foo_Response& response() const {
    ZX_ASSERT(ordinal_ ==
              ::fidl_test_error::wire::Example_foo_Result::Ordinal::kResponse);
    return *static_cast<::fidl_test_error::wire::Example_foo_Response*>(
        envelope_.data.get());
  }

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

  static Example_foo_Result WithErr(::fidl::ObjectView<uint32_t> val) {
    Example_foo_Result result;
    result.set_err(val);
    return result;
  }

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

  void set_err(::fidl::ObjectView<uint32_t> elem) {
    ordinal_ = ::fidl_test_error::wire::Example_foo_Result::Ordinal::kErr;
    envelope_.data =
        ::fidl::ObjectView<void>::FromExternal(static_cast<void*>(elem.get()));
  }

  template <typename... Args>
  void set_err(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = ::fidl_test_error::wire::Example_foo_Result::Ordinal::kErr;
    set_err(
        ::fidl::ObjectView<uint32_t>(allocator, std::forward<Args>(args)...));
  }

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

  static constexpr const fidl_type_t* Type =
      &fidl_test_error_Example_foo_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
  };

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

extern "C" const fidl_type_t fidl_test_error_Example_foo_ResponseTable;

struct Example_foo_Response {
  static constexpr const fidl_type_t* Type =
      &fidl_test_error_Example_foo_ResponseTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 8;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 0;
  static constexpr bool HasPointer = false;

  int64_t y = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          Example_foo_Response* value)
        : message_(bytes, byte_size, sizeof(Example_foo_Response), nullptr, 0,
                   0) {
      message_.Encode<Example_foo_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  // __Fuchsia__
    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(Example_foo_Response* value)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

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

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

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

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

extern "C" const fidl_type_t fidl_test_error_ExamplefooResponseTable;

class Example final {
  Example() = delete;

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

template <>
struct ::fidl::internal::ProtocolDetails<::fidl_test_error::Example> {};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct ::fidl::internal::WireDispatcher<::fidl_test_error::Example> final {
  WireDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireInterface<::fidl_test_error::Example>* impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
  static ::fidl::DispatchResult Dispatch(
      ::fidl::WireInterface<::fidl_test_error::Example>* impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
};
#endif  // __Fuchsia__

template <>
struct ::fidl::WireRequest<::fidl_test_error::Example::foo> final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  ::fidl::StringView s;
  explicit WireRequest(zx_txid_t _txid, ::fidl::StringView s) : s(s) {
    _InitHeader(_txid);
  }
  explicit WireRequest(zx_txid_t _txid) { _InitHeader(_txid); }

  static constexpr const fidl_type_t* Type =
      &::fidl_test_error::fidl_test_error_ExamplefooRequestTable;
  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 = ::fidl::WireResponse<::fidl_test_error::Example::foo>;

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size, zx_txid_t _txid,
                          ::fidl::StringView s)
        : message_(_bytes, _byte_size, sizeof(WireRequest), nullptr, 0, 0) {
      FIDL_ALIGNDECL WireRequest _request(_txid, s);
      message_.Encode<WireRequest>(&_request);
    }
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          WireRequest* request)
        : message_(bytes, byte_size, sizeof(WireRequest), nullptr, 0, 0) {
      message_.Encode<WireRequest>(request);
    }
    UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
    UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

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

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

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

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

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

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

 private:
  void _InitHeader(zx_txid_t _txid);
};
template <>
struct ::fidl::WireResponse<::fidl_test_error::Example::foo> final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  ::fidl_test_error::wire::Example_foo_Result result;
  explicit WireResponse(::fidl_test_error::wire::Example_foo_Result result)
      : result(result) {
    _InitHeader();
  }
  WireResponse() { _InitHeader(); }

  static constexpr const fidl_type_t* Type =
      &::fidl_test_error::fidl_test_error_ExamplefooResponseTable;
  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,
                          ::fidl_test_error::wire::Example_foo_Result result)
        : message_(_bytes, _byte_size, sizeof(WireResponse), nullptr, 0, 0) {
      FIDL_ALIGNDECL WireResponse _response{result};
      message_.Encode<::fidl::WireResponse<::fidl_test_error::Example::foo>>(
          &_response);
    }
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          WireResponse* response)
        : message_(bytes, byte_size, sizeof(WireResponse), nullptr, 0, 0) {
      message_.Encode<::fidl::WireResponse<::fidl_test_error::Example::foo>>(
          response);
    }
    UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
    UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(
        ::fidl_test_error::wire::Example_foo_Result result)
        : message_(bytes_.data(), bytes_.size(), result) {}
    explicit OwnedEncodedMessage(
        ::fidl::WireResponse<::fidl_test_error::Example::foo>* response)
        : message_(bytes_.data(), bytes_.size(), response) {}
    OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
    OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

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

    WireResponse* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<
          ::fidl::WireResponse<::fidl_test_error::Example::foo>*>(bytes());
    }

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

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

  ::fidl::WireResponse<::fidl_test_error::Example::foo>* Unwrap() {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<
        ::fidl::WireResponse<::fidl_test_error::Example::foo>*>(bytes_.data());
  }
  const ::fidl::WireResponse<::fidl_test_error::Example::foo>* Unwrap() const {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<
        const ::fidl::WireResponse<::fidl_test_error::Example::foo>*>(
        bytes_.data());
  }

  ::fidl::WireResponse<::fidl_test_error::Example::foo>& value() {
    return *Unwrap();
  }
  const ::fidl::WireResponse<::fidl_test_error::Example::foo>& value() const {
    return *Unwrap();
  }

  ::fidl::WireResponse<::fidl_test_error::Example::foo>* operator->() {
    return &value();
  }
  const ::fidl::WireResponse<::fidl_test_error::Example::foo>* operator->()
      const {
    return &value();
  }

  ::fidl::WireResponse<::fidl_test_error::Example::foo>& operator*() {
    return value();
  }
  const ::fidl::WireResponse<::fidl_test_error::Example::foo>& operator*()
      const {
    return value();
  }

 private:
  ::fidl::internal::InlineMessageBuffer<48> bytes_;
};
template <>
class ::fidl::WireUnownedResult<::fidl_test_error::Example::foo> final
    : public ::fidl::Result {
 public:
  explicit WireUnownedResult(
      ::fidl::UnownedClientEnd<::fidl_test_error::Example> _client,
      uint8_t* _request_bytes, uint32_t _request_byte_capacity,
      ::fidl::StringView s, uint8_t* _response_bytes,
      uint32_t _response_byte_capacity);
  explicit WireUnownedResult(const ::fidl::Result& result)
      : ::fidl::Result(result) {}
  WireUnownedResult(WireUnownedResult&&) = delete;
  WireUnownedResult(const WireUnownedResult&) = delete;
  WireUnownedResult* operator=(WireUnownedResult&&) = delete;
  WireUnownedResult* operator=(const WireUnownedResult&) = delete;
  ~WireUnownedResult() = default;

  ::fidl::WireResponse<::fidl_test_error::Example::foo>* Unwrap() {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<
        ::fidl::WireResponse<::fidl_test_error::Example::foo>*>(bytes_);
  }
  const ::fidl::WireResponse<::fidl_test_error::Example::foo>* Unwrap() const {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<
        const ::fidl::WireResponse<::fidl_test_error::Example::foo>*>(bytes_);
  }

  ::fidl::WireResponse<::fidl_test_error::Example::foo>& value() {
    return *Unwrap();
  }
  const ::fidl::WireResponse<::fidl_test_error::Example::foo>& value() const {
    return *Unwrap();
  }

  ::fidl::WireResponse<::fidl_test_error::Example::foo>* operator->() {
    return &value();
  }
  const ::fidl::WireResponse<::fidl_test_error::Example::foo>* operator->()
      const {
    return &value();
  }

  ::fidl::WireResponse<::fidl_test_error::Example::foo>& operator*() {
    return value();
  }
  const ::fidl::WireResponse<::fidl_test_error::Example::foo>& operator*()
      const {
    return value();
  }

 private:
  uint8_t* bytes_;
};

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

  // Allocates 48 bytes of response buffer on the stack. Request is
  // heap-allocated.
  static ::fidl::WireResult<::fidl_test_error::Example::foo> foo(
      ::fidl::UnownedClientEnd<::fidl_test_error::Example> _client_end,
      ::fidl::StringView s) {
    return ::fidl::WireResult<::fidl_test_error::Example::foo>(_client_end, s);
  }
  // Allocates 48 bytes of response buffer on the stack. Request is
  // heap-allocated.
  ::fidl::WireResult<::fidl_test_error::Example::foo> foo(
      ::fidl::StringView s) && {
    return ::fidl::WireResult<::fidl_test_error::Example::foo>(client_end_, s);
  }

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  static ::fidl::WireUnownedResult<::fidl_test_error::Example::foo> foo(
      ::fidl::UnownedClientEnd<::fidl_test_error::Example> _client_end,
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView s,
      ::fidl::BufferSpan _response_buffer) {
    return ::fidl::WireUnownedResult<::fidl_test_error::Example::foo>(
        _client_end, _request_buffer.data, _request_buffer.capacity, s,
        _response_buffer.data, _response_buffer.capacity);
  }
  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<::fidl_test_error::Example::foo> foo(
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView s,
      ::fidl::BufferSpan _response_buffer) && {
    return ::fidl::WireUnownedResult<::fidl_test_error::Example::foo>(
        client_end_, _request_buffer.data, _request_buffer.capacity, s,
        _response_buffer.data, _response_buffer.capacity);
  }

 private:
  ::fidl::UnownedClientEnd<::fidl_test_error::Example> client_end_;
};
#ifdef __Fuchsia__

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

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

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

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

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

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

template <>
class ::fidl::WireSyncClient<::fidl_test_error::Example> final {
 public:
  WireSyncClient() = default;

  explicit WireSyncClient(
      ::fidl::ClientEnd<::fidl_test_error::Example> client_end)
      : client_end_(std::move(client_end)) {}

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

  const ::fidl::ClientEnd<::fidl_test_error::Example>& client_end() const {
    return client_end_;
  }
  ::fidl::ClientEnd<::fidl_test_error::Example>& client_end() {
    return client_end_;
  }

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

  // Allocates 48 bytes of response buffer on the stack. Request is
  // heap-allocated.
  ::fidl::WireResult<::fidl_test_error::Example::foo> foo(
      ::fidl::StringView s) {
    return ::fidl::WireResult<::fidl_test_error::Example::foo>(
        this->client_end(), s);
  }

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<::fidl_test_error::Example::foo> foo(
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView s,
      ::fidl::BufferSpan _response_buffer) {
    return ::fidl::WireUnownedResult<::fidl_test_error::Example::foo>(
        this->client_end(), _request_buffer.data, _request_buffer.capacity, s,
        _response_buffer.data, _response_buffer.capacity);
  }

 private:
  ::fidl::ClientEnd<::fidl_test_error::Example> client_end_;
};

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

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

  class fooCompleterBase : 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_test_error::wire::Example_foo_Result result);
    ::fidl::Result ReplySuccess(int64_t y);
    ::fidl::Result ReplyError(uint32_t error);
    ::fidl::Result Reply(::fidl::BufferSpan _buffer,
                         ::fidl_test_error::wire::Example_foo_Result result);
    ::fidl::Result ReplySuccess(::fidl::BufferSpan _buffer, int64_t y);

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

  using fooCompleter = ::fidl::Completer<fooCompleterBase>;

  virtual void foo(::fidl::StringView s, fooCompleter::Sync& _completer) = 0;

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

namespace fidl {

template <>
struct IsFidlType<::fidl_test_error::wire::Example_foo_Response>
    : public std::true_type {};
template <>
struct IsStruct<::fidl_test_error::wire::Example_foo_Response>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_error::wire::Example_foo_Response>);
static_assert(offsetof(::fidl_test_error::wire::Example_foo_Response, y) == 0);
static_assert(sizeof(::fidl_test_error::wire::Example_foo_Response) ==
              ::fidl_test_error::wire::Example_foo_Response::PrimarySize);

template <>
struct IsFidlType<::fidl_test_error::wire::Example_foo_Result>
    : public std::true_type {};
template <>
struct IsUnion<::fidl_test_error::wire::Example_foo_Result>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_error::wire::Example_foo_Result>);

template <>
struct IsFidlType<::fidl::WireRequest<::fidl_test_error::Example::foo>>
    : public std::true_type {};
template <>
struct IsFidlMessage<::fidl::WireRequest<::fidl_test_error::Example::foo>>
    : public std::true_type {};
static_assert(
    sizeof(::fidl::WireRequest<::fidl_test_error::Example::foo>) ==
    ::fidl::WireRequest<::fidl_test_error::Example::foo>::PrimarySize);
static_assert(offsetof(::fidl::WireRequest<::fidl_test_error::Example::foo>,
                       s) == 16);

template <>
struct IsFidlType<::fidl::WireResponse<::fidl_test_error::Example::foo>>
    : public std::true_type {};
template <>
struct IsFidlMessage<::fidl::WireResponse<::fidl_test_error::Example::foo>>
    : public std::true_type {};
static_assert(
    sizeof(::fidl::WireResponse<::fidl_test_error::Example::foo>) ==
    ::fidl::WireResponse<::fidl_test_error::Example::foo>::PrimarySize);
static_assert(offsetof(::fidl::WireResponse<::fidl_test_error::Example::foo>,
                       result) == 16);
}  // namespace fidl
#ifdef __Fuchsia__

template <>
class ::fidl::WireResponseContext<::fidl_test_error::Example::foo>
    : public ::fidl::internal::ResponseContext {
 public:
  WireResponseContext();

  virtual void OnReply(
      ::fidl::WireResponse<::fidl_test_error::Example::foo>* message) = 0;

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

#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireClientImpl<::fidl_test_error::Example> final
    : private ::fidl::internal::ClientBase {
 public:
  // Asynchronous variant of |Example.foo()|.
  // The request and callback are allocated on the heap.
  ::fidl::Result foo(
      ::fidl::StringView s,
      ::fit::callback<
          void(::fidl::WireResponse<::fidl_test_error::Example::foo>* response)>
          _cb);

  // Asynchronous variant of |Example.foo()|.
  // 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 foo(
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView s,
      ::fidl::WireResponseContext<::fidl_test_error::Example::foo>* _context);

  // Synchronous variant of |Example.foo()|.
  // Allocates 48 bytes of response buffer on the stack. Request is
  // heap-allocated.
  ::fidl::WireResult<::fidl_test_error::Example::foo> foo_Sync(
      ::fidl::StringView s);

  // Synchronous variant of |Example.foo()|.
  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<::fidl_test_error::Example::foo> foo_Sync(
      ::fidl::BufferSpan _request_buffer, ::fidl::StringView s,
      ::fidl::BufferSpan _response_buffer);

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

 private:
  friend class ::fidl::Client<::fidl_test_error::Example>;
  friend class ::fidl::internal::ControlBlock<::fidl_test_error::Example>;

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

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

  std::shared_ptr<::fidl::WireAsyncEventHandler<::fidl_test_error::Example>>
      event_handler_;
};
#endif  // __Fuchsia__

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

  explicit WireEventSender(
      ::fidl::ServerEnd<::fidl_test_error::Example> server_end)
      : server_end_(std::move(server_end)) {}

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

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

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

 private:
  ::fidl::ServerEnd<::fidl_test_error::Example> server_end_;
};

template <>
class ::fidl::internal::WireWeakEventSender<::fidl_test_error::Example> {
 public:
 private:
  friend class ::fidl::ServerBindingRef<::fidl_test_error::Example>;

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

  std::weak_ptr<
      ::fidl::internal::AsyncServerBinding<::fidl_test_error::Example>>
      binding_;
};
#endif  // __Fuchsia__
