// 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_doccomments {
namespace wire {
class Table;

struct Struct;

class StrictUnion;
}  // namespace wire
class Interface;

class Service;
namespace wire {

/// strict enum comment #1.
///
/// strict enum comment #2.
enum class MyStrictEnum : uint32_t {

  /// FOO member comment #1
  ///
  /// FOO member comment #3
  kFoo = 1u,

  /// BAR member comment #1
  ///
  /// BAR member comment #3
  kBar = 2u,
};

/// strict bits comment #1
///
/// strict bits comment #2
// |MyStrictBits| is strict, hence is guaranteed to only contain
// members defined in the FIDL schema when receiving it in a message.
// Sending unknown members will fail at runtime.
class MyStrictBits final {
 public:
  constexpr MyStrictBits() = default;
  constexpr MyStrictBits(const MyStrictBits& other) = default;

  // Constructs an instance of |MyStrictBits| from an underlying primitive
  // value, preserving any bit member not defined in the FIDL schema.
  explicit constexpr MyStrictBits(uint32_t value) : value_(value) {}
  const static MyStrictBits kMyFirstBit;
  const static MyStrictBits kMyOtherBit;
  const static MyStrictBits kMask;

  explicit constexpr inline operator uint32_t() const { return value_; }
  explicit constexpr inline operator bool() const {
    return static_cast<bool>(value_);
  }
  constexpr inline bool operator==(const MyStrictBits& other) const {
    return value_ == other.value_;
  }
  constexpr inline bool operator!=(const MyStrictBits& other) const {
    return value_ != other.value_;
  }
  constexpr inline MyStrictBits operator~() const;
  constexpr inline MyStrictBits operator|(const MyStrictBits& other) const;
  constexpr inline MyStrictBits operator&(const MyStrictBits& other) const;
  constexpr inline MyStrictBits operator^(const MyStrictBits& other) const;
  constexpr inline void operator|=(const MyStrictBits& other);
  constexpr inline void operator&=(const MyStrictBits& other);
  constexpr inline void operator^=(const MyStrictBits& other);

  // Constructs an instance of |MyStrictBits| from an underlying primitive value
  // if the primitive does not contain any unknown members not defined in the
  // FIDL schema. Otherwise, returns |cpp17::nullopt|.
  constexpr inline static cpp17::optional<MyStrictBits> TryFrom(
      uint32_t value) {
    if (value & ~kMask.value_) {
      return cpp17::nullopt;
    }
    return MyStrictBits(value & MyStrictBits::kMask.value_);
  }

  // Constructs an instance of |MyStrictBits| from an underlying primitive
  // value, clearing any bit member not defined in the FIDL schema.
  constexpr inline static MyStrictBits TruncatingUnknown(uint32_t value) {
    return MyStrictBits(value & MyStrictBits::kMask.value_);
  }

 private:
  uint32_t value_ = 0;
};
constexpr const ::fidl_test_doccomments::wire::MyStrictBits
    MyStrictBits::kMyFirstBit = ::fidl_test_doccomments::wire::MyStrictBits(1u);
constexpr const ::fidl_test_doccomments::wire::MyStrictBits
    MyStrictBits::kMyOtherBit = ::fidl_test_doccomments::wire::MyStrictBits(2u);
constexpr const ::fidl_test_doccomments::wire::MyStrictBits
    MyStrictBits::kMask = ::fidl_test_doccomments::wire::MyStrictBits(3u);

constexpr inline ::fidl_test_doccomments::wire::MyStrictBits
MyStrictBits::operator~() const {
  return ::fidl_test_doccomments::wire::MyStrictBits(
      static_cast<uint32_t>(~this->value_ & kMask.value_));
}

constexpr inline ::fidl_test_doccomments::wire::MyStrictBits
MyStrictBits::operator|(
    const ::fidl_test_doccomments::wire::MyStrictBits& other) const {
  return ::fidl_test_doccomments::wire::MyStrictBits(
      static_cast<uint32_t>(this->value_ | other.value_));
}

constexpr inline ::fidl_test_doccomments::wire::MyStrictBits
MyStrictBits::operator&(
    const ::fidl_test_doccomments::wire::MyStrictBits& other) const {
  return ::fidl_test_doccomments::wire::MyStrictBits(
      static_cast<uint32_t>(this->value_ & other.value_));
}

constexpr inline ::fidl_test_doccomments::wire::MyStrictBits
MyStrictBits::operator^(
    const ::fidl_test_doccomments::wire::MyStrictBits& other) const {
  return ::fidl_test_doccomments::wire::MyStrictBits(
      static_cast<uint32_t>(this->value_ ^ other.value_));
}

constexpr inline void MyStrictBits::operator|=(
    const ::fidl_test_doccomments::wire::MyStrictBits& other) {
  this->value_ |= other.value_;
}

constexpr inline void MyStrictBits::operator&=(
    const ::fidl_test_doccomments::wire::MyStrictBits& other) {
  this->value_ &= other.value_;
}

constexpr inline void MyStrictBits::operator^=(
    const ::fidl_test_doccomments::wire::MyStrictBits& other) {
  this->value_ ^= other.value_;
}

/// flexible enum comment #1.
///
/// flexible enum comment #2.
class MyFlexibleEnum final {
 public:
  constexpr MyFlexibleEnum() : value_(0) {}
  constexpr explicit MyFlexibleEnum(uint32_t value) : value_(value) {}
  constexpr MyFlexibleEnum(const MyFlexibleEnum& other) = default;
  constexpr operator uint32_t() const { return value_; }

  constexpr bool IsUnknown() const {
    switch (value_) {
      case 1u:

      case 2u:

        return false;
      default:
        return true;
    }
  }

  constexpr static MyFlexibleEnum Unknown() {
    return MyFlexibleEnum(0xffffffff);
  }

  /// FOO member comment #1
  ///
  /// FOO member comment #3
  static const MyFlexibleEnum kFoo;

  /// BAR member comment #1
  ///
  /// BAR member comment #3
  static const MyFlexibleEnum kBar;

 private:
  uint32_t value_;
};
constexpr const ::fidl_test_doccomments::wire::MyFlexibleEnum
    MyFlexibleEnum::kFoo = ::fidl_test_doccomments::wire::MyFlexibleEnum(1u);
constexpr const ::fidl_test_doccomments::wire::MyFlexibleEnum
    MyFlexibleEnum::kBar = ::fidl_test_doccomments::wire::MyFlexibleEnum(2u);

/// flexible bits comment #1
///
/// flexible bits comment #2
// |MyFlexibleBits| is flexible, hence may contain unknown members not
// defined in the FIDL schema.
class MyFlexibleBits final {
 public:
  constexpr MyFlexibleBits() = default;
  constexpr MyFlexibleBits(const MyFlexibleBits& other) = default;

  // Constructs an instance of |MyFlexibleBits| from an underlying primitive
  // value, preserving any bit member not defined in the FIDL schema.
  explicit constexpr MyFlexibleBits(uint32_t value) : value_(value) {}
  const static MyFlexibleBits kMyFirstBit;
  const static MyFlexibleBits kMyOtherBit;
  const static MyFlexibleBits kMask;

  explicit constexpr inline operator uint32_t() const { return value_; }
  explicit constexpr inline operator bool() const {
    return static_cast<bool>(value_);
  }
  constexpr inline bool operator==(const MyFlexibleBits& other) const {
    return value_ == other.value_;
  }
  constexpr inline bool operator!=(const MyFlexibleBits& other) const {
    return value_ != other.value_;
  }
  constexpr inline MyFlexibleBits operator~() const;
  constexpr inline MyFlexibleBits operator|(const MyFlexibleBits& other) const;
  constexpr inline MyFlexibleBits operator&(const MyFlexibleBits& other) const;
  constexpr inline MyFlexibleBits operator^(const MyFlexibleBits& other) const;
  constexpr inline void operator|=(const MyFlexibleBits& other);
  constexpr inline void operator&=(const MyFlexibleBits& other);
  constexpr inline void operator^=(const MyFlexibleBits& other);

  // Constructs an instance of |MyFlexibleBits| from an underlying primitive
  // value if the primitive does not contain any unknown members not defined in
  // the FIDL schema. Otherwise, returns |cpp17::nullopt|.
  constexpr inline static cpp17::optional<MyFlexibleBits> TryFrom(
      uint32_t value) {
    if (value & ~kMask.value_) {
      return cpp17::nullopt;
    }
    return MyFlexibleBits(value & MyFlexibleBits::kMask.value_);
  }

  // Constructs an instance of |MyFlexibleBits| from an underlying primitive
  // value, clearing any bit member not defined in the FIDL schema.
  constexpr inline static MyFlexibleBits TruncatingUnknown(uint32_t value) {
    return MyFlexibleBits(value & MyFlexibleBits::kMask.value_);
  }
  constexpr inline MyFlexibleBits unknown_bits() const {
    return *this & MyFlexibleBits(~kMask.value_);
  }
  constexpr inline bool has_unknown_bits() const {
    return static_cast<bool>(unknown_bits());
  }

 private:
  uint32_t value_ = 0;
};
constexpr const ::fidl_test_doccomments::wire::MyFlexibleBits
    MyFlexibleBits::kMyFirstBit =
        ::fidl_test_doccomments::wire::MyFlexibleBits(1u);
constexpr const ::fidl_test_doccomments::wire::MyFlexibleBits
    MyFlexibleBits::kMyOtherBit =
        ::fidl_test_doccomments::wire::MyFlexibleBits(2u);
constexpr const ::fidl_test_doccomments::wire::MyFlexibleBits
    MyFlexibleBits::kMask = ::fidl_test_doccomments::wire::MyFlexibleBits(3u);

constexpr inline ::fidl_test_doccomments::wire::MyFlexibleBits
MyFlexibleBits::operator~() const {
  return ::fidl_test_doccomments::wire::MyFlexibleBits(
      static_cast<uint32_t>(~this->value_ & kMask.value_));
}

constexpr inline ::fidl_test_doccomments::wire::MyFlexibleBits
MyFlexibleBits::operator|(
    const ::fidl_test_doccomments::wire::MyFlexibleBits& other) const {
  return ::fidl_test_doccomments::wire::MyFlexibleBits(
      static_cast<uint32_t>(this->value_ | other.value_));
}

constexpr inline ::fidl_test_doccomments::wire::MyFlexibleBits
MyFlexibleBits::operator&(
    const ::fidl_test_doccomments::wire::MyFlexibleBits& other) const {
  return ::fidl_test_doccomments::wire::MyFlexibleBits(
      static_cast<uint32_t>(this->value_ & other.value_));
}

constexpr inline ::fidl_test_doccomments::wire::MyFlexibleBits
MyFlexibleBits::operator^(
    const ::fidl_test_doccomments::wire::MyFlexibleBits& other) const {
  return ::fidl_test_doccomments::wire::MyFlexibleBits(
      static_cast<uint32_t>(this->value_ ^ other.value_));
}

constexpr inline void MyFlexibleBits::operator|=(
    const ::fidl_test_doccomments::wire::MyFlexibleBits& other) {
  this->value_ |= other.value_;
}

constexpr inline void MyFlexibleBits::operator&=(
    const ::fidl_test_doccomments::wire::MyFlexibleBits& other) {
  this->value_ &= other.value_;
}

constexpr inline void MyFlexibleBits::operator^=(
    const ::fidl_test_doccomments::wire::MyFlexibleBits& other) {
  this->value_ ^= other.value_;
}

class FlexibleUnion;

extern "C" const fidl_type_t fidl_test_doccomments_TableTable;

/// table comment #1
///
/// table comment #3
class Table final {
 public:
  // Returns whether no field is set.
  bool IsEmpty() const { return max_ordinal_ == 0; }

  class Frame_;

  /// table field comment #1
  ///
  /// table field comment #3
  const int32_t& field() const {
    ZX_ASSERT(has_Field());
    return *frame_ptr_->field_.data;
  }
  int32_t& field() {
    ZX_ASSERT(has_Field());
    return *frame_ptr_->field_.data;
  }
  bool has_Field() const {
    return max_ordinal_ >= 1 && frame_ptr_->field_.data != nullptr;
  }
  Table& set_field(::fidl::ObjectView<int32_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->field_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }
  Table& set_field(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->field_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  Table& set_field(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->field_.data =
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }

  Table() = default;
  explicit Table(::fidl::AnyAllocator& allocator)
      : frame_ptr_(::fidl::ObjectView<Frame_>(allocator)) {}
  // This constructor allows a user controlled allocation (not using a
  // FidlAllocator). It should only be used when performance is key. As soon as
  // the frame is given to the table, it must not be used directly or for
  // another table.
  explicit Table(::fidl::ObjectView<Frame_>&& frame)
      : frame_ptr_(std::move(frame)) {}
  ~Table() = default;
  Table(const Table& other) noexcept = default;
  Table& operator=(const Table& other) noexcept = default;
  Table(Table&& other) noexcept = default;
  Table& operator=(Table&& other) noexcept = default;

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

  void Allocate(::fidl::AnyAllocator& allocator) {
    max_ordinal_ = 0;
    frame_ptr_ = ::fidl::ObjectView<Frame_>(allocator);
  }
  void Init(::fidl::ObjectView<Frame_>&& frame_ptr) {
    max_ordinal_ = 0;
    frame_ptr_ = std::move(frame_ptr);
  }

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* backing_buffer, uint32_t backing_buffer_size,
                          Table* value)
        : message_(::fidl::OutgoingMessage::ConstructorArgs{
              .iovecs = iovecs_,
              .iovec_capacity = ::fidl::internal::IovecBufferSize,
              .backing_buffer = backing_buffer,
              .backing_buffer_capacity = backing_buffer_size,
          }) {
      if (backing_buffer_size < sizeof(Table)) {
        ::fidl::internal::OutgoingMessageResultSetter::SetResult(
            message_, ZX_ERR_BUFFER_TOO_SMALL, nullptr);
        return;
      }
      message_.Encode<Table>(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::internal::IovecBuffer iovecs_;
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(Table* value)
        : message_(backing_buffer_.data(), backing_buffer_.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<40> backing_buffer_;
    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<Table>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<Table>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

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

  // Frame_s are managed automatically by the FidlAllocator class.
  // The only direct usage is when performance is key and a frame needs to be
  // allocated outside a FidlAllocator. Once created, a frame can only be used
  // for one single table.
  class Frame_ final {
   public:
    Frame_() = default;
    // In its intended usage, Frame_ will be referenced by an ObjectView. If the
    // ObjectView is assigned before a move or copy, then it will reference the
    // old invalid object. Because this is unsafe, copies are disallowed and
    // moves are only allowed by friend classes that operate safely.
    Frame_(const Frame_&) = delete;
    Frame_& operator=(const Frame_&) = delete;

   private:
    Frame_(Frame_&&) noexcept = default;
    Frame_& operator=(Frame_&&) noexcept = default;
    ::fidl::Envelope<int32_t> field_;

    friend class Table;
  };

 private:
  uint64_t max_ordinal_ = 0;
  ::fidl::ObjectView<Frame_> frame_ptr_;
};

extern "C" const fidl_type_t fidl_test_doccomments_StrictUnionTable;

/// strict union comment #1
///
/// strict union comment #3
class StrictUnion {
 public:
  StrictUnion()
      : ordinal_(::fidl_test_doccomments::wire::StrictUnion::Ordinal::Invalid),
        envelope_{} {}

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

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

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

  bool is_field() const {
    return ordinal_ ==
           ::fidl_test_doccomments::wire::StrictUnion::Ordinal::kField;
  }

  static StrictUnion WithField(::fidl::ObjectView<int32_t> val) {
    StrictUnion result;
    result.set_field(val);
    return result;
  }

  template <typename... Args>
  static StrictUnion WithField(::fidl::AnyAllocator& allocator,
                               Args&&... args) {
    StrictUnion result;
    result.set_field(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    return result;
  }

  /// union member comment #1
  ///
  /// union member comment #3
  void set_field(::fidl::ObjectView<int32_t> elem) {
    ordinal_ = ::fidl_test_doccomments::wire::StrictUnion::Ordinal::kField;
    envelope_.data =
        ::fidl::ObjectView<void>::FromExternal(static_cast<void*>(elem.get()));
  }

  template <typename... Args>
  void set_field(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = ::fidl_test_doccomments::wire::StrictUnion::Ordinal::kField;
    set_field(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

  /// union member comment #1
  ///
  /// union member comment #3
  int32_t& mutable_field() {
    ZX_ASSERT(ordinal_ ==
              ::fidl_test_doccomments::wire::StrictUnion::Ordinal::kField);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& field() const {
    ZX_ASSERT(ordinal_ ==
              ::fidl_test_doccomments::wire::StrictUnion::Ordinal::kField);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  ::fidl_test_doccomments::wire::StrictUnion::Tag which() const {
    ZX_ASSERT(!has_invalid_tag());
    return static_cast<::fidl_test_doccomments::wire::StrictUnion::Tag>(
        ordinal_);
  }

  static constexpr const fidl_type_t* Type =
      &fidl_test_doccomments_StrictUnionTable;
  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,
    kField = 1,  // 0x1
  };

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

extern "C" const fidl_type_t fidl_test_doccomments_FlexibleUnionTable;

/// flexible union comment #1
///
/// flexible union comment #3
class FlexibleUnion {
 public:
  FlexibleUnion()
      : ordinal_(
            ::fidl_test_doccomments::wire::FlexibleUnion::Ordinal::Invalid),
        envelope_{} {}

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

  enum class Tag : fidl_xunion_tag_t {
    kField = 1,  // 0x1
    kUnknown = ::std::numeric_limits<::fidl_union_tag_t>::max(),
  };

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

  bool is_field() const {
    return ordinal_ ==
           ::fidl_test_doccomments::wire::FlexibleUnion::Ordinal::kField;
  }

  static FlexibleUnion WithField(::fidl::ObjectView<int32_t> val) {
    FlexibleUnion result;
    result.set_field(val);
    return result;
  }

  template <typename... Args>
  static FlexibleUnion WithField(::fidl::AnyAllocator& allocator,
                                 Args&&... args) {
    FlexibleUnion result;
    result.set_field(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    return result;
  }

  /// union member comment #1
  ///
  /// union member comment #3
  void set_field(::fidl::ObjectView<int32_t> elem) {
    ordinal_ = ::fidl_test_doccomments::wire::FlexibleUnion::Ordinal::kField;
    envelope_.data =
        ::fidl::ObjectView<void>::FromExternal(static_cast<void*>(elem.get()));
  }

  template <typename... Args>
  void set_field(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = ::fidl_test_doccomments::wire::FlexibleUnion::Ordinal::kField;
    set_field(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

  /// union member comment #1
  ///
  /// union member comment #3
  int32_t& mutable_field() {
    ZX_ASSERT(ordinal_ ==
              ::fidl_test_doccomments::wire::FlexibleUnion::Ordinal::kField);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& field() const {
    ZX_ASSERT(ordinal_ ==
              ::fidl_test_doccomments::wire::FlexibleUnion::Ordinal::kField);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  ::fidl_test_doccomments::wire::FlexibleUnion::Tag which() const;

  static constexpr const fidl_type_t* Type =
      &fidl_test_doccomments_FlexibleUnionTable;
  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,
    kField = 1,  // 0x1
  };

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

extern "C" const fidl_type_t fidl_test_doccomments_StructTable;

/// struct comment #1
///
/// struct comment #3
struct Struct {
  static constexpr const fidl_type_t* Type = &fidl_test_doccomments_StructTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 4;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 0;
  static constexpr bool HasPointer = false;

  /// struct member comment #1
  ///
  /// struct member comment #3
  int32_t field = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* backing_buffer, uint32_t backing_buffer_size,
                          Struct* value)
        : message_(::fidl::OutgoingMessage::ConstructorArgs{
              .iovecs = iovecs_,
              .iovec_capacity = ::fidl::internal::IovecBufferSize,
              .backing_buffer = backing_buffer,
              .backing_buffer_capacity = backing_buffer_size,
          }) {
      if (backing_buffer_size < sizeof(Struct)) {
        ::fidl::internal::OutgoingMessageResultSetter::SetResult(
            message_, ZX_ERR_BUFFER_TOO_SMALL, nullptr);
        return;
      }
      message_.Encode<Struct>(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::internal::IovecBuffer iovecs_;
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(Struct* value)
        : message_(backing_buffer_.data(), backing_buffer_.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> backing_buffer_;
    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 Struct>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct Struct>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

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

extern "C" const fidl_type_t fidl_test_doccomments_InterfaceMethodResponseTable;

extern "C" const fidl_type_t fidl_test_doccomments_InterfaceOnEventRequestTable;

extern "C" const fidl_type_t fidl_test_doccomments_InterfaceOnEventEventTable;

/// interface comment #1
///
/// interface comment #3
class Interface final {
  Interface() = delete;

 public:
  /// method comment #1
  ///
  /// method comment #3
  class Method final {
    Method() = delete;
  };
  /// event comment #1
  ///
  /// event comment #3
  class OnEvent final {
    OnEvent() = delete;
  };
};
}  // namespace fidl_test_doccomments
#ifdef __Fuchsia__

template <>
struct ::fidl::internal::ProtocolDetails<::fidl_test_doccomments::Interface> {};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

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

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

template <>
struct ::fidl::WireRequest<::fidl_test_doccomments::Interface::Method> final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  explicit WireRequest(zx_txid_t _txid) { _InitHeader(_txid); }

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

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

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

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

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

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

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

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

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

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

 private:
  void _InitHeader(zx_txid_t _txid);
};
template <>
struct ::fidl::WireResponse<::fidl_test_doccomments::Interface::OnEvent> final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  WireResponse() { _InitHeader(); }

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

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

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

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

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

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

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

 public:
  class DecodedMessage final : public ::fidl::internal::IncomingMessage {
   public:
    DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                   zx_handle_info_t* handles = nullptr,
                   uint32_t handle_actual = 0)
        : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                            handle_actual) {
      Decode<
          ::fidl::WireResponse<::fidl_test_doccomments::Interface::OnEvent>>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<
          ::fidl::WireResponse<::fidl_test_doccomments::Interface::OnEvent>>();
    }
    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_doccomments::Interface::OnEvent>*>(
          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_doccomments::Interface::Method> final
    : public ::fidl::Result {
 public:
  explicit WireResult(
      ::fidl::UnownedClientEnd<::fidl_test_doccomments::Interface> _client);
  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;

 private:
};
template <>
class ::fidl::WireUnownedResult<::fidl_test_doccomments::Interface::Method>
    final : public ::fidl::Result {
 public:
  explicit WireUnownedResult(
      ::fidl::UnownedClientEnd<::fidl_test_doccomments::Interface> _client);
  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;
};

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

  /// method comment #1
  ///
  /// method comment #3
  // Allocates 16 bytes of message buffer on the stack. No heap allocation
  // necessary.
  static ::fidl::WireResult<::fidl_test_doccomments::Interface::Method> Method(
      ::fidl::UnownedClientEnd<::fidl_test_doccomments::Interface>
          _client_end) {
    return ::fidl::WireResult<::fidl_test_doccomments::Interface::Method>(
        _client_end);
  }
  /// method comment #1
  ///
  /// method comment #3
  // Allocates 16 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_doccomments::Interface::Method> Method() && {
    return ::fidl::WireResult<::fidl_test_doccomments::Interface::Method>(
        client_end_);
  }

 private:
  ::fidl::UnownedClientEnd<::fidl_test_doccomments::Interface> client_end_;
};
#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireEventHandlerInterface<
    ::fidl_test_doccomments::Interface> {
 public:
  WireEventHandlerInterface() = default;
  virtual ~WireEventHandlerInterface() = default;
  /// event comment #1
  ///
  /// event comment #3
  virtual void OnEvent(
      ::fidl::WireResponse<::fidl_test_doccomments::Interface::OnEvent>*
          event) {}
};

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

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

template <>
class ::fidl::WireSyncEventHandler<::fidl_test_doccomments::Interface>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_doccomments::Interface> {
 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_doccomments::Interface> client_end);
};
#endif  // __Fuchsia__

template <>
class ::fidl::WireSyncClient<::fidl_test_doccomments::Interface> final {
 public:
  WireSyncClient() = default;

  explicit WireSyncClient(
      ::fidl::ClientEnd<::fidl_test_doccomments::Interface> client_end)
      : client_end_(std::move(client_end)) {}

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

  const ::fidl::ClientEnd<::fidl_test_doccomments::Interface>& client_end()
      const {
    return client_end_;
  }
  ::fidl::ClientEnd<::fidl_test_doccomments::Interface>& client_end() {
    return client_end_;
  }

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

  /// method comment #1
  ///
  /// method comment #3
  // Allocates 16 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_doccomments::Interface::Method> Method() {
    return ::fidl::WireResult<::fidl_test_doccomments::Interface::Method>(
        this->client_end());
  }

  // 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 |SyncEventHandler|. The return
  // status of the handler function is folded with any transport-level errors
  // and returned.
  ::fidl::Result HandleOneEvent(
      ::fidl::WireSyncEventHandler<::fidl_test_doccomments::Interface>&
          event_handler) {
    return event_handler.HandleOneEvent(client_end_);
  }

 private:
  ::fidl::ClientEnd<::fidl_test_doccomments::Interface> client_end_;
};

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

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

  using MethodCompleter = ::fidl::Completer<>;
  class MethodRequestView {
   public:
    MethodRequestView(
        ::fidl::WireRequest<::fidl_test_doccomments::Interface::Method>*
            request)
        : request_(request) {}
    ::fidl::WireRequest<::fidl_test_doccomments::Interface::Method>*
    operator->() const {
      return request_;
    }

   private:
    ::fidl::WireRequest<::fidl_test_doccomments::Interface::Method>* request_;
  };

  /// method comment #1
  ///
  /// method comment #3
  virtual void Method(MethodRequestView request,
                      MethodCompleter::Sync& _completer) = 0;

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

// Pure-virtual interface to be implemented by a server.
// This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
// and |fidl::ServerEnd<SomeProtocol>|).
template <>
class ::fidl::WireInterface<::fidl_test_doccomments::Interface>
    : 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_doccomments::Interface;

  using MethodCompleter =
      ::fidl::WireServer<::fidl_test_doccomments::Interface>::MethodCompleter;
  /// method comment #1
  ///
  /// method comment #3
  virtual void Method(MethodCompleter::Sync& _completer) = 0;

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

namespace fidl_test_doccomments {

/// service comment #1
///
/// service comment #3
class Service final {
  Service() = default;

 public:
  static constexpr char Name[] = "fidl.test.doccomments.Service";

  // Client protocol for connecting to member protocols of a service instance.
  class ServiceClient final {
    ServiceClient() = delete;

   public:
    ServiceClient(::zx::channel dir,
                  ::fidl::internal::ConnectMemberFunc connect_func)
        : dir_(std::move(dir)), connect_func_(connect_func) {}

    // Connects to the member protocol "interface".
    // Returns a |fidl::ClientEnd<::fidl_test_doccomments::Interface>| on
    // success, which can be used with |fidl::BindSyncClient| to create a
    // synchronous client, or |fidl::Client| to create a client that supports
    // both asynchronous and synchronous operations.
    //
    // # Errors
    //
    // On failure, returns a |zx::error| with status != ZX_OK.
    // Failures can occur if channel creation failed, or if there was an issue
    // making a |fuchsia.io.Directory/Open| call.
    //
    // Since the call to |Open| is asynchronous, an error sent by the remote end
    // will not result in a failure of this method. Any errors sent by the
    // remote will appear on the |ClientEnd| returned from this method.
    ::zx::status<::fidl::ClientEnd<::fidl_test_doccomments::Interface>>
    connect_interface() {
      auto endpoints =
          ::fidl::CreateEndpoints<::fidl_test_doccomments::Interface>();
      if (endpoints.is_error()) {
        return endpoints.take_error();
      }
      auto connection = connect_func_(::zx::unowned_channel(dir_),
                                      ::fidl::StringView("interface"),
                                      endpoints->server.TakeChannel());
      if (connection.is_error()) {
        return connection.take_error();
      }
      return ::zx::ok(std::move(endpoints->client));
    }

   private:
    ::zx::channel dir_;
    ::fidl::internal::ConnectMemberFunc connect_func_;
  };

  // Facilitates member protocol registration for servers.
  class Handler final {
   public:
    // Constructs a FIDL Service-typed handler. Does not take ownership of
    // |service_handler|.
    explicit Handler(::fidl::ServiceHandlerInterface* service_handler)
        : service_handler_(service_handler) {}

    // Adds member "interface" to the service instance. |handler| will be
    // invoked on connection attempts.
    //
    // # Errors
    //
    // Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
    ::zx::status<> add_interface(::fidl::ServiceHandlerInterface::MemberHandler<
                                 ::fidl_test_doccomments::Interface>
                                     handler) {
      return service_handler_->AddMember("interface", std::move(handler));
    }

   private:
    ::fidl::ServiceHandlerInterface* service_handler_;  // Not owned.
  };
};
namespace wire {

/// const comment #1
///
/// const comment #3
constexpr int32_t kC = 4u;

}  // namespace wire
}  // namespace fidl_test_doccomments
namespace fidl {

template <>
struct IsFidlType<::fidl_test_doccomments::wire::Table>
    : public std::true_type {};
template <>
struct IsTable<::fidl_test_doccomments::wire::Table> : public std::true_type {};
static_assert(std::is_standard_layout_v<::fidl_test_doccomments::wire::Table>);

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

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

template <>
struct IsFidlType<
    ::fidl::WireRequest<::fidl_test_doccomments::Interface::Method>>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::fidl::WireRequest<::fidl_test_doccomments::Interface::Method>>
    : public std::true_type {};
static_assert(
    sizeof(::fidl::WireRequest<::fidl_test_doccomments::Interface::Method>) ==
    ::fidl::WireRequest<
        ::fidl_test_doccomments::Interface::Method>::PrimarySize);

template <>
struct IsFidlType<
    ::fidl::WireResponse<::fidl_test_doccomments::Interface::OnEvent>>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::fidl::WireResponse<::fidl_test_doccomments::Interface::OnEvent>>
    : public std::true_type {};
static_assert(
    sizeof(::fidl::WireResponse<::fidl_test_doccomments::Interface::OnEvent>) ==
    ::fidl::WireResponse<
        ::fidl_test_doccomments::Interface::OnEvent>::PrimarySize);

template <>
struct IsFidlType<::fidl_test_doccomments::wire::MyStrictEnum>
    : public std::true_type {};

template <>
struct IsFidlType<::fidl_test_doccomments::wire::MyStrictBits>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_doccomments::wire::MyStrictBits>);
static_assert(sizeof(::fidl_test_doccomments::wire::MyStrictBits) ==
              sizeof(uint32_t));

template <>
struct IsFidlType<::fidl_test_doccomments::wire::MyFlexibleEnum>
    : public std::true_type {};

template <>
struct IsFidlType<::fidl_test_doccomments::wire::MyFlexibleBits>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_doccomments::wire::MyFlexibleBits>);
static_assert(sizeof(::fidl_test_doccomments::wire::MyFlexibleBits) ==
              sizeof(uint32_t));

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

#ifdef __Fuchsia__
}  // namespace fidl
template <>
class ::fidl::internal::WireClientImpl<::fidl_test_doccomments::Interface> final
    : private ::fidl::internal::ClientBase {
 public:
  /// method comment #1
  ///
  /// method comment #3
  //
  // Allocates 16 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result Method();

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

 private:
  friend class ::fidl::Client<::fidl_test_doccomments::Interface>;
  friend class ::fidl::internal::ControlBlock<
      ::fidl_test_doccomments::Interface>;

  explicit WireClientImpl(
      std::shared_ptr<
          ::fidl::WireAsyncEventHandler<::fidl_test_doccomments::Interface>>
          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_doccomments::Interface>>
      event_handler_;
};
namespace fidl {
#endif  // __Fuchsia__

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

  explicit WireEventSender(
      ::fidl::ServerEnd<::fidl_test_doccomments::Interface> 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_doccomments::Interface>& server_end()
      const {
    return server_end_;
  }
  ::fidl::ServerEnd<::fidl_test_doccomments::Interface>& 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(); }

  /// event comment #1
  ///
  /// event comment #3
  zx_status_t OnEvent() const;

 private:
  ::fidl::ServerEnd<::fidl_test_doccomments::Interface> server_end_;
};

template <>
class ::fidl::internal::WireWeakEventSender<
    ::fidl_test_doccomments::Interface> {
 public:
  /// event comment #1
  ///
  /// event comment #3
  zx_status_t OnEvent() const {
    if (auto _binding = binding_.lock()) {
      return _binding->event_sender().OnEvent();
    }
    return ZX_ERR_CANCELED;
  }

 private:
  friend class ::fidl::ServerBindingRef<::fidl_test_doccomments::Interface>;

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

  std::weak_ptr<
      ::fidl::internal::AsyncServerBinding<::fidl_test_doccomments::Interface>>
      binding_;
};
#endif  // __Fuchsia__
