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

#pragma once

#include <lib/fidl/internal.h>
#include <lib/fidl/llcpp/array.h>
#include <lib/fidl/llcpp/buffer_allocator.h>
#include <lib/fidl/llcpp/buffer_then_heap_allocator.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/fidl/llcpp/envelope.h>
#include <lib/fidl/llcpp/errors.h>
#include <lib/fidl/llcpp/memory.h>
#include <lib/fidl/llcpp/message.h>
#include <lib/fidl/llcpp/message_storage.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/tracking_ptr.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fit/function.h>
#include <lib/fit/optional.h>

#include <variant>
#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/result.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/sync_call.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fidl/txn_header.h>
#include <lib/zx/channel.h>
#endif  // __Fuchsia__
#include <zircon/fidl.h>

namespace llcpp {

namespace fidl {
namespace test {
namespace doccomments {

class Table;
struct Struct;
class StrictUnion;
class Interface;
class Service;

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

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

  // BAR member comment #1
  //
  // BAR member comment #3
  BAR = 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 MY_FIRST_BIT;
  const static MyStrictBits MY_OTHER_BIT;
  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 |fit::nullopt|.
  constexpr inline static fit::optional<MyStrictBits> TryFrom(uint32_t value) {
    if (value & ~kMask.value_) {
      return fit::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 ::llcpp::fidl::test::doccomments::MyStrictBits
    MyStrictBits::MY_FIRST_BIT =
        ::llcpp::fidl::test::doccomments::MyStrictBits(1u);
constexpr const ::llcpp::fidl::test::doccomments::MyStrictBits
    MyStrictBits::MY_OTHER_BIT =
        ::llcpp::fidl::test::doccomments::MyStrictBits(2u);
constexpr const ::llcpp::fidl::test::doccomments::MyStrictBits
    MyStrictBits::kMask = ::llcpp::fidl::test::doccomments::MyStrictBits(3u);

constexpr inline ::llcpp::fidl::test::doccomments::MyStrictBits
MyStrictBits::operator~() const {
  return ::llcpp::fidl::test::doccomments::MyStrictBits(
      static_cast<uint32_t>(~this->value_ & kMask.value_));
}

constexpr inline ::llcpp::fidl::test::doccomments::MyStrictBits
MyStrictBits::operator|(
    const ::llcpp::fidl::test::doccomments::MyStrictBits& other) const {
  return ::llcpp::fidl::test::doccomments::MyStrictBits(
      static_cast<uint32_t>(this->value_ | other.value_));
}

constexpr inline ::llcpp::fidl::test::doccomments::MyStrictBits
MyStrictBits::operator&(
    const ::llcpp::fidl::test::doccomments::MyStrictBits& other) const {
  return ::llcpp::fidl::test::doccomments::MyStrictBits(
      static_cast<uint32_t>(this->value_ & other.value_));
}

constexpr inline ::llcpp::fidl::test::doccomments::MyStrictBits
MyStrictBits::operator^(
    const ::llcpp::fidl::test::doccomments::MyStrictBits& other) const {
  return ::llcpp::fidl::test::doccomments::MyStrictBits(
      static_cast<uint32_t>(this->value_ ^ other.value_));
}

constexpr inline void MyStrictBits::operator|=(
    const ::llcpp::fidl::test::doccomments::MyStrictBits& other) {
  this->value_ |= other.value_;
}

constexpr inline void MyStrictBits::operator&=(
    const ::llcpp::fidl::test::doccomments::MyStrictBits& other) {
  this->value_ &= other.value_;
}

constexpr inline void MyStrictBits::operator^=(
    const ::llcpp::fidl::test::doccomments::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 FOO;

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

 private:
  uint32_t value_;
};
constexpr const ::llcpp::fidl::test::doccomments::MyFlexibleEnum
    MyFlexibleEnum::FOO = ::llcpp::fidl::test::doccomments::MyFlexibleEnum(1u);
constexpr const ::llcpp::fidl::test::doccomments::MyFlexibleEnum
    MyFlexibleEnum::BAR = ::llcpp::fidl::test::doccomments::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 MY_FIRST_BIT;
  const static MyFlexibleBits MY_OTHER_BIT;
  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 |fit::nullopt|.
  constexpr inline static fit::optional<MyFlexibleBits> TryFrom(
      uint32_t value) {
    if (value & ~kMask.value_) {
      return fit::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 ::llcpp::fidl::test::doccomments::MyFlexibleBits
    MyFlexibleBits::MY_FIRST_BIT =
        ::llcpp::fidl::test::doccomments::MyFlexibleBits(1u);
constexpr const ::llcpp::fidl::test::doccomments::MyFlexibleBits
    MyFlexibleBits::MY_OTHER_BIT =
        ::llcpp::fidl::test::doccomments::MyFlexibleBits(2u);
constexpr const ::llcpp::fidl::test::doccomments::MyFlexibleBits
    MyFlexibleBits::kMask =
        ::llcpp::fidl::test::doccomments::MyFlexibleBits(3u);

constexpr inline ::llcpp::fidl::test::doccomments::MyFlexibleBits
MyFlexibleBits::operator~() const {
  return ::llcpp::fidl::test::doccomments::MyFlexibleBits(
      static_cast<uint32_t>(~this->value_ & kMask.value_));
}

constexpr inline ::llcpp::fidl::test::doccomments::MyFlexibleBits
MyFlexibleBits::operator|(
    const ::llcpp::fidl::test::doccomments::MyFlexibleBits& other) const {
  return ::llcpp::fidl::test::doccomments::MyFlexibleBits(
      static_cast<uint32_t>(this->value_ | other.value_));
}

constexpr inline ::llcpp::fidl::test::doccomments::MyFlexibleBits
MyFlexibleBits::operator&(
    const ::llcpp::fidl::test::doccomments::MyFlexibleBits& other) const {
  return ::llcpp::fidl::test::doccomments::MyFlexibleBits(
      static_cast<uint32_t>(this->value_ & other.value_));
}

constexpr inline ::llcpp::fidl::test::doccomments::MyFlexibleBits
MyFlexibleBits::operator^(
    const ::llcpp::fidl::test::doccomments::MyFlexibleBits& other) const {
  return ::llcpp::fidl::test::doccomments::MyFlexibleBits(
      static_cast<uint32_t>(this->value_ ^ other.value_));
}

constexpr inline void MyFlexibleBits::operator|=(
    const ::llcpp::fidl::test::doccomments::MyFlexibleBits& other) {
  this->value_ |= other.value_;
}

constexpr inline void MyFlexibleBits::operator&=(
    const ::llcpp::fidl::test::doccomments::MyFlexibleBits& other) {
  this->value_ &= other.value_;
}

constexpr inline void MyFlexibleBits::operator^=(
    const ::llcpp::fidl::test::doccomments::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; }

  // 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() = default;
  ~Table() = 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;

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size, Table* value)
        : message_(bytes, byte_size, sizeof(Table), nullptr, 0, 0) {
      message_.LinearizeAndEncode<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
    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(Table* value)
        : message_(bytes_, sizeof(bytes_), value) {}
    OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
    OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

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

  class DecodedMessage final : public ::fidl::internal::IncomingMessage {
   public:
    DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                   zx_handle_info_t* handles = nullptr,
                   uint32_t handle_actual = 0)
        : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                            handle_actual) {
      Decode<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(); }

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

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

  class Builder;
  class UnownedBuilder;

  class Frame final {
   public:
    Frame() = default;
    // In its intended usage, Frame will be referenced by a tracking_ptr. If the
    // tracking_ptr 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;
    friend class Table::Builder;
    friend class Table::UnownedBuilder;
  };

 private:
  Table(uint64_t max_ordinal, ::fidl::tracking_ptr<Frame>&& frame_ptr)
      : max_ordinal_(max_ordinal), frame_ptr_(std::move(frame_ptr)) {}
  uint64_t max_ordinal_ = 0;
  ::fidl::tracking_ptr<Frame> frame_ptr_;
};

// Table::Builder builds Table.
// Usage:
// Table val = Table::Builder(std::make_unique<Table::Frame>())
// .set_Field(ptr)
// .build();
class Table::Builder final {
 public:
  ~Builder() = default;
  Builder() = delete;
  Builder(::fidl::tracking_ptr<Table::Frame>&& frame_ptr)
      : max_ordinal_(0), frame_ptr_(std::move(frame_ptr)) {}

  Builder(Builder&& other) noexcept = default;
  Builder& operator=(Builder&& other) noexcept = default;

  Builder(const Builder& other) = delete;
  Builder& operator=(const Builder& other) = delete;

  // Returns whether no field is set.
  bool IsEmpty() const { return max_ordinal_ == 0; }

  // table field comment #1
  //
  // table field comment #3
  Builder&& set_Field(::fidl::tracking_ptr<int32_t> elem) {
    frame_ptr_->Field_.data = std::move(elem);
    if (max_ordinal_ < 1) {
      // Note: the table size is not currently reduced if nullptr is set.
      // This is possible to reconsider in the future.
      max_ordinal_ = 1;
    }
    return std::move(*this);
  }
  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 build() { return Table(max_ordinal_, std::move(frame_ptr_)); }

 private:
  uint64_t max_ordinal_ = 0;
  ::fidl::tracking_ptr<Table::Frame> frame_ptr_;
};

// UnownedBuilder acts like Builder but directly owns its Frame, simplifying
// working with unowned data.
class Table::UnownedBuilder final {
 public:
  ~UnownedBuilder() = default;
  UnownedBuilder() noexcept = default;
  UnownedBuilder(UnownedBuilder&& other) noexcept = default;
  UnownedBuilder& operator=(UnownedBuilder&& other) noexcept = default;

  // Returns whether no field is set.
  bool IsEmpty() const { return max_ordinal_ == 0; }

  // table field comment #1
  //
  // table field comment #3
  UnownedBuilder&& set_Field(::fidl::tracking_ptr<int32_t> elem) {
    ZX_ASSERT(elem);
    frame_.Field_.data = std::move(elem);
    if (max_ordinal_ < 1) {
      max_ordinal_ = 1;
    }
    return std::move(*this);
  }
  const int32_t& Field() const {
    ZX_ASSERT(has_Field());
    return *frame_.Field_.data;
  }
  int32_t& Field() {
    ZX_ASSERT(has_Field());
    return *frame_.Field_.data;
  }
  bool has_Field() const {
    return max_ordinal_ >= 1 && frame_.Field_.data != nullptr;
  }

  Table build() { return Table(max_ordinal_, ::fidl::unowned_ptr(&frame_)); }

 private:
  uint64_t max_ordinal_ = 0;
  Table::Frame frame_;
};

extern "C" const fidl_type_t fidl_test_doccomments_StrictUnionTable;

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

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

  ~StrictUnion() { reset_ptr(nullptr); }

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

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

  bool is_Field() const { return ordinal_ == Ordinal::kField; }

  static StrictUnion WithField(::fidl::tracking_ptr<int32_t>&& val) {
    StrictUnion result;
    result.set_Field(std::move(val));
    return result;
  }

  // union member comment #1
  //
  // union member comment #3
  void set_Field(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kField;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

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

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

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

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

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

extern "C" const fidl_type_t fidl_test_doccomments_FlexibleUnionTable;

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

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

  ~FlexibleUnion() { reset_ptr(nullptr); }

  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_ == Ordinal::Invalid; }

  bool is_Field() const { return ordinal_ == Ordinal::kField; }

  static FlexibleUnion WithField(::fidl::tracking_ptr<int32_t>&& val) {
    FlexibleUnion result;
    result.set_Field(std::move(val));
    return result;
  }

  // union member comment #1
  //
  // union member comment #3
  void set_Field(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kField;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  // union member comment #1
  //
  // union member comment #3
  int32_t& mutable_Field() {
    ZX_ASSERT(ordinal_ == Ordinal::kField);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& Field() const {
    ZX_ASSERT(ordinal_ == Ordinal::kField);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  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
  };

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

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

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

extern "C" const fidl_type_t fidl_test_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* bytes, uint32_t byte_size, Struct* value)
        : message_(bytes, byte_size, sizeof(Struct), nullptr, 0, 0) {
      message_.LinearizeAndEncode<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
    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(Struct* value)
        : message_(bytes_, sizeof(bytes_), value) {}
    OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
    OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

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

  class DecodedMessage final : public ::fidl::internal::IncomingMessage {
   public:
    DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                   zx_handle_info_t* handles = nullptr,
                   uint32_t handle_actual = 0)
        : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                            handle_actual) {
      Decode<struct 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(); }

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

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

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:
  struct MethodRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit MethodRequest(zx_txid_t _txid) { _InitHeader(_txid); }

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

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

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

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

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

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

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(MethodRequest* request)
          : message_(bytes_, sizeof(bytes_), request) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

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

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

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

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

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

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

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

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct OnEventResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    OnEventResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size)
          : message_(_bytes, _byte_size, sizeof(OnEventResponse), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL OnEventResponse _response{};
        message_.LinearizeAndEncode<OnEventResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            OnEventResponse* response)
          : message_(bytes, byte_size, sizeof(OnEventResponse), nullptr, 0, 0) {
        message_.LinearizeAndEncode<OnEventResponse>(response);
      }
      UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
      UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

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

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

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage() : message_(bytes_, sizeof(bytes_)) {}
      explicit OwnedEncodedMessage(OnEventResponse* response)
          : message_(bytes_, sizeof(bytes_), response) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

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

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

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

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

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

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

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

   private:
    void _InitHeader();
  };

  class EventHandler {
   public:
    EventHandler() = default;
    virtual ~EventHandler() = default;
    // event comment #1
    //
    // event comment #3
    virtual void OnEvent(OnEventResponse* event) = 0;

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

    // Handle all possible events defined in this protocol.
    // Blocks to consume exactly one message from the channel, then call the
    // corresponding virtual method.
    ::fidl::Result HandleOneEvent(::zx::unowned_channel client_end);
  };

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

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

     private:
    };
  };

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

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

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

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

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

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

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

    // method comment #1
    //
    // method comment #3
    // Allocates 16 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::Method Method() {
      return ResultOf::Method(this->channel().get());
    }

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

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

  struct AsyncEventHandlers;
  class ClientImpl;

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

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

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

    virtual void Method(MethodCompleter::Sync& _completer) = 0;

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

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

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

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

  class EventSender;
  class WeakEventSender;
};

// 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::ClientChannel| on success, which can be used with
    // |fidl::BindSyncClient| to create a synchronous client.
    //
    // # Errors
    //
    // On failure, returns a fit::error with zx_status_t != 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 |ClientChannel| returned from this method.
    ::fidl::result<::fidl::ClientChannel<Interface>> connect_interface() {
      ::zx::channel local, remote;
      zx_status_t result = ::zx::channel::create(0, &local, &remote);
      if (result != ZX_OK) {
        return ::fit::error(result);
      }
      result =
          connect_func_(::zx::unowned_channel(dir_),
                        ::fidl::StringView("interface"), std::move(remote));
      if (result != ZX_OK) {
        return ::fit::error(result);
      }
      return ::fit::ok(::fidl::ClientChannel<Interface>(std::move(local)));
    }

   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(::llcpp::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_t add_interface(
        ::llcpp::fidl::ServiceHandlerInterface::MemberHandler handler) {
      return service_handler_->AddMember("interface", std::move(handler));
    }

   private:
    ::llcpp::fidl::ServiceHandlerInterface* service_handler_;  // Not owned.
  };
};

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

}  // namespace doccomments
}  // namespace test
}  // namespace fidl
}  // namespace llcpp

namespace fidl {

template <>
struct IsFidlType<::llcpp::fidl::test::doccomments::Table>
    : public std::true_type {};
template <>
struct IsTable<::llcpp::fidl::test::doccomments::Table>
    : public std::true_type {};
template <>
struct IsTableBuilder<::llcpp::fidl::test::doccomments::Table::Builder>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::llcpp::fidl::test::doccomments::Table>);

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

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

template <>
struct IsFidlType<::llcpp::fidl::test::doccomments::Interface::MethodRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fidl::test::doccomments::Interface::MethodRequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::doccomments::Interface::MethodRequest) ==
    ::llcpp::fidl::test::doccomments::Interface::MethodRequest::PrimarySize);

template <>
struct IsFidlType<::llcpp::fidl::test::doccomments::Interface::OnEventResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::doccomments::Interface::OnEventResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::doccomments::Interface::OnEventResponse) ==
    ::llcpp::fidl::test::doccomments::Interface::OnEventResponse::PrimarySize);

template <>
struct IsFidlType<::llcpp::fidl::test::doccomments::MyStrictEnum>
    : public std::true_type {};

template <>
struct IsFidlType<::llcpp::fidl::test::doccomments::MyStrictBits>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::llcpp::fidl::test::doccomments::MyStrictBits>);
static_assert(sizeof(::llcpp::fidl::test::doccomments::MyStrictBits) ==
              sizeof(uint32_t));

template <>
struct IsFidlType<::llcpp::fidl::test::doccomments::MyFlexibleEnum>
    : public std::true_type {};

template <>
struct IsFidlType<::llcpp::fidl::test::doccomments::MyFlexibleBits>
    : public std::true_type {};
static_assert(std::is_standard_layout_v<
              ::llcpp::fidl::test::doccomments::MyFlexibleBits>);
static_assert(sizeof(::llcpp::fidl::test::doccomments::MyFlexibleBits) ==
              sizeof(uint32_t));

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

}  // namespace fidl

namespace llcpp {

namespace fidl {
namespace test {
namespace doccomments {

struct Interface::AsyncEventHandlers {
  // event comment #1
  //
  // event comment #3
  ::fit::function<void()> on_event;
};

class Interface::ClientImpl 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();

 private:
  friend class ::fidl::Client<Interface>;

  explicit ClientImpl(AsyncEventHandlers handlers)
      : handlers_(std::move(handlers)) {}

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

  AsyncEventHandlers handlers_;
};

// |EventSender| owns a server endpoint of a channel speaking
// the Interface protocol, and can send events in that protocol.
class Interface::EventSender {
 public:
  // Constructs an event sender with an invalid channel.
  EventSender() = default;

  // TODO(fxbug.dev/65212): EventSender should take a ::fidl::ServerEnd.
  explicit EventSender(::zx::channel server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::zx::channel& channel() const { return server_end_; }
  ::zx::channel& channel() { return server_end_; }

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

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

 private:
  ::zx::channel server_end_;
};

class Interface::WeakEventSender {
 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<Interface>;

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

  std::weak_ptr<::fidl::internal::AsyncServerBinding<Interface>> binding_;
};

}  // namespace doccomments
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
