// 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 union_ {

class Union;
struct StructWithNullableXUnion;
class StrictUnion;
class StrictSimpleXUnion;
class StrictFoo;
class StrictBoundedXUnion;
class ReverseOrdinalUnion;
struct Pizza;
struct Pasta;
class StrictPizzaOrPasta;
class PizzaOrPasta;
class FlexiblePizzaOrPasta;
class ExplicitPizzaOrPasta;
class OlderSimpleUnion;
class TestProtocol;
struct NullableUnionStruct;
class NewerSimpleUnion;
class FlexibleUnion;
class FlexibleFoo;
class FieldCollision;
class ExplicitXUnion;
class ExplicitUnion;
class ExplicitStrictFoo;
class ExplicitFoo;
struct Empty;
class XUnionContainingEmptyStruct;

extern "C" const fidl_type_t fidl_test_union_UnionTable;

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

  Union(Union&&) = default;
  Union& operator=(Union&&) = default;

  ~Union() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kPrimitive = 1,                         // 0x1
    kStringNeedsConstructor = 2,            // 0x2
    kVectorStringAlsoNeedsConstructor = 3,  // 0x3
  };

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

  bool is_Primitive() const { return ordinal_ == Ordinal::kPrimitive; }

  static Union WithPrimitive(::fidl::tracking_ptr<int32_t>&& val) {
    Union result;
    result.set_Primitive(std::move(val));
    return result;
  }

  void set_Primitive(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kPrimitive;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_Primitive() {
    ZX_ASSERT(ordinal_ == Ordinal::kPrimitive);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& Primitive() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPrimitive);
    return *static_cast<int32_t*>(envelope_.data.get());
  }

  bool is_StringNeedsConstructor() const {
    return ordinal_ == Ordinal::kStringNeedsConstructor;
  }

  static Union WithStringNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::StringView>&& val) {
    Union result;
    result.set_StringNeedsConstructor(std::move(val));
    return result;
  }

  void set_StringNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kStringNeedsConstructor;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_StringNeedsConstructor() {
    ZX_ASSERT(ordinal_ == Ordinal::kStringNeedsConstructor);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& StringNeedsConstructor() const {
    ZX_ASSERT(ordinal_ == Ordinal::kStringNeedsConstructor);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }

  bool is_VectorStringAlsoNeedsConstructor() const {
    return ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor;
  }

  static Union WithVectorStringAlsoNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>&& val) {
    Union result;
    result.set_VectorStringAlsoNeedsConstructor(std::move(val));
    return result;
  }

  void set_VectorStringAlsoNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>&& elem) {
    ordinal_ = Ordinal::kVectorStringAlsoNeedsConstructor;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::VectorView<::fidl::StringView>&
  mutable_VectorStringAlsoNeedsConstructor() {
    ZX_ASSERT(ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor);
    return *static_cast<::fidl::VectorView<::fidl::StringView>*>(
        envelope_.data.get());
  }
  const ::fidl::VectorView<::fidl::StringView>&
  VectorStringAlsoNeedsConstructor() const {
    ZX_ASSERT(ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor);
    return *static_cast<::fidl::VectorView<::fidl::StringView>*>(
        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_union_UnionTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kPrimitive = 1,                         // 0x1
    kStringNeedsConstructor = 2,            // 0x2
    kVectorStringAlsoNeedsConstructor = 3,  // 0x3
  };

  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;
      }
      case 2: {
        ::fidl::tracking_ptr<::fidl::StringView> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::StringView>>(
                std::move(envelope_.data));
        break;
      }
      case 3: {
        ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>
            to_destroy = static_cast<
                ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>>(
                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_union_StrictUnionTable;

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 {
    kPrimitive = 1,                         // 0x1
    kStringNeedsConstructor = 2,            // 0x2
    kVectorStringAlsoNeedsConstructor = 3,  // 0x3
  };

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

  bool is_Primitive() const { return ordinal_ == Ordinal::kPrimitive; }

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

  void set_Primitive(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kPrimitive;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_Primitive() {
    ZX_ASSERT(ordinal_ == Ordinal::kPrimitive);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& Primitive() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPrimitive);
    return *static_cast<int32_t*>(envelope_.data.get());
  }

  bool is_StringNeedsConstructor() const {
    return ordinal_ == Ordinal::kStringNeedsConstructor;
  }

  static StrictUnion WithStringNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::StringView>&& val) {
    StrictUnion result;
    result.set_StringNeedsConstructor(std::move(val));
    return result;
  }

  void set_StringNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kStringNeedsConstructor;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_StringNeedsConstructor() {
    ZX_ASSERT(ordinal_ == Ordinal::kStringNeedsConstructor);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& StringNeedsConstructor() const {
    ZX_ASSERT(ordinal_ == Ordinal::kStringNeedsConstructor);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }

  bool is_VectorStringAlsoNeedsConstructor() const {
    return ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor;
  }

  static StrictUnion WithVectorStringAlsoNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>&& val) {
    StrictUnion result;
    result.set_VectorStringAlsoNeedsConstructor(std::move(val));
    return result;
  }

  void set_VectorStringAlsoNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>&& elem) {
    ordinal_ = Ordinal::kVectorStringAlsoNeedsConstructor;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::VectorView<::fidl::StringView>&
  mutable_VectorStringAlsoNeedsConstructor() {
    ZX_ASSERT(ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor);
    return *static_cast<::fidl::VectorView<::fidl::StringView>*>(
        envelope_.data.get());
  }
  const ::fidl::VectorView<::fidl::StringView>&
  VectorStringAlsoNeedsConstructor() const {
    ZX_ASSERT(ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor);
    return *static_cast<::fidl::VectorView<::fidl::StringView>*>(
        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_union_StrictUnionTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kPrimitive = 1,                         // 0x1
    kStringNeedsConstructor = 2,            // 0x2
    kVectorStringAlsoNeedsConstructor = 3,  // 0x3
  };

  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;
      }
      case 2: {
        ::fidl::tracking_ptr<::fidl::StringView> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::StringView>>(
                std::move(envelope_.data));
        break;
      }
      case 3: {
        ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>
            to_destroy = static_cast<
                ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>>(
                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_union_StrictSimpleXUnionTable;

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

  StrictSimpleXUnion(StrictSimpleXUnion&&) = default;
  StrictSimpleXUnion& operator=(StrictSimpleXUnion&&) = default;

  ~StrictSimpleXUnion() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kI = 1,  // 0x1
    kF = 2,  // 0x2
    kS = 3,  // 0x3
  };

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

  bool is_i() const { return ordinal_ == Ordinal::kI; }

  static StrictSimpleXUnion WithI(::fidl::tracking_ptr<int32_t>&& val) {
    StrictSimpleXUnion result;
    result.set_i(std::move(val));
    return result;
  }

  void set_i(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kI;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_i() {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& i() const {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int32_t*>(envelope_.data.get());
  }

  bool is_f() const { return ordinal_ == Ordinal::kF; }

  static StrictSimpleXUnion WithF(::fidl::tracking_ptr<float>&& val) {
    StrictSimpleXUnion result;
    result.set_f(std::move(val));
    return result;
  }

  void set_f(::fidl::tracking_ptr<float>&& elem) {
    ordinal_ = Ordinal::kF;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  float& mutable_f() {
    ZX_ASSERT(ordinal_ == Ordinal::kF);
    return *static_cast<float*>(envelope_.data.get());
  }
  const float& f() const {
    ZX_ASSERT(ordinal_ == Ordinal::kF);
    return *static_cast<float*>(envelope_.data.get());
  }

  bool is_s() const { return ordinal_ == Ordinal::kS; }

  static StrictSimpleXUnion WithS(
      ::fidl::tracking_ptr<::fidl::StringView>&& val) {
    StrictSimpleXUnion result;
    result.set_s(std::move(val));
    return result;
  }

  void set_s(::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kS;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_s() {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& s() const {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(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_union_StrictSimpleXUnionTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kI = 1,  // 0x1
    kF = 2,  // 0x2
    kS = 3,  // 0x3
  };

  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;
      }
      case 2: {
        ::fidl::tracking_ptr<float> to_destroy =
            static_cast<::fidl::tracking_ptr<float>>(std::move(envelope_.data));
        break;
      }
      case 3: {
        ::fidl::tracking_ptr<::fidl::StringView> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::StringView>>(
                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_union_StrictFooTable;

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

  StrictFoo(StrictFoo&&) = default;
  StrictFoo& operator=(StrictFoo&&) = default;

  ~StrictFoo() { reset_ptr(nullptr); }

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

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

  bool is_s() const { return ordinal_ == Ordinal::kS; }

  static StrictFoo WithS(::fidl::tracking_ptr<::fidl::StringView>&& val) {
    StrictFoo result;
    result.set_s(std::move(val));
    return result;
  }

  void set_s(::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kS;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_s() {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& s() const {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }

  bool is_i() const { return ordinal_ == Ordinal::kI; }

  static StrictFoo WithI(::fidl::tracking_ptr<int32_t>&& val) {
    StrictFoo result;
    result.set_i(std::move(val));
    return result;
  }

  void set_i(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kI;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_i() {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& i() const {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    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_union_StrictFooTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

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

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

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

  StrictBoundedXUnion(StrictBoundedXUnion&&) = default;
  StrictBoundedXUnion& operator=(StrictBoundedXUnion&&) = default;

  ~StrictBoundedXUnion() { reset_ptr(nullptr); }

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

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

  bool is_v() const { return ordinal_ == Ordinal::kV; }

  static StrictBoundedXUnion WithV(
      ::fidl::tracking_ptr<::fidl::VectorView<uint8_t>>&& val) {
    StrictBoundedXUnion result;
    result.set_v(std::move(val));
    return result;
  }

  void set_v(::fidl::tracking_ptr<::fidl::VectorView<uint8_t>>&& elem) {
    ordinal_ = Ordinal::kV;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::VectorView<uint8_t>& mutable_v() {
    ZX_ASSERT(ordinal_ == Ordinal::kV);
    return *static_cast<::fidl::VectorView<uint8_t>*>(envelope_.data.get());
  }
  const ::fidl::VectorView<uint8_t>& v() const {
    ZX_ASSERT(ordinal_ == Ordinal::kV);
    return *static_cast<::fidl::VectorView<uint8_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_union_StrictBoundedXUnionTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 32;
  static constexpr bool HasPointer = true;

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kV = 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<::fidl::VectorView<uint8_t>> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::VectorView<uint8_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_union_ReverseOrdinalUnionTable;

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

  ReverseOrdinalUnion(ReverseOrdinalUnion&&) = default;
  ReverseOrdinalUnion& operator=(ReverseOrdinalUnion&&) = default;

  ~ReverseOrdinalUnion() { reset_ptr(nullptr); }

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

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

  bool is_second() const { return ordinal_ == Ordinal::kSecond; }

  static ReverseOrdinalUnion WithSecond(::fidl::tracking_ptr<uint32_t>&& val) {
    ReverseOrdinalUnion result;
    result.set_second(std::move(val));
    return result;
  }

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

  uint32_t& mutable_second() {
    ZX_ASSERT(ordinal_ == Ordinal::kSecond);
    return *static_cast<uint32_t*>(envelope_.data.get());
  }
  const uint32_t& second() const {
    ZX_ASSERT(ordinal_ == Ordinal::kSecond);
    return *static_cast<uint32_t*>(envelope_.data.get());
  }

  bool is_first() const { return ordinal_ == Ordinal::kFirst; }

  static ReverseOrdinalUnion WithFirst(::fidl::tracking_ptr<uint32_t>&& val) {
    ReverseOrdinalUnion result;
    result.set_first(std::move(val));
    return result;
  }

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

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

  static constexpr const fidl_type_t* Type =
      &fidl_test_union_ReverseOrdinalUnionTable;
  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,
    kSecond = 2,  // 0x2
    kFirst = 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 2: {
        ::fidl::tracking_ptr<uint32_t> to_destroy =
            static_cast<::fidl::tracking_ptr<uint32_t>>(
                std::move(envelope_.data));
        break;
      }
      case 1: {
        ::fidl::tracking_ptr<uint32_t> to_destroy =
            static_cast<::fidl::tracking_ptr<uint32_t>>(
                std::move(envelope_.data));
        break;
      }
    }

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

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

extern "C" const fidl_type_t fidl_test_union_StrictPizzaOrPastaTable;

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

  StrictPizzaOrPasta(StrictPizzaOrPasta&&) = default;
  StrictPizzaOrPasta& operator=(StrictPizzaOrPasta&&) = default;

  ~StrictPizzaOrPasta() { reset_ptr(nullptr); }

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

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

  bool is_pizza() const { return ordinal_ == Ordinal::kPizza; }

  static StrictPizzaOrPasta WithPizza(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>&& val) {
    StrictPizzaOrPasta result;
    result.set_pizza(std::move(val));
    return result;
  }

  void set_pizza(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>&& elem) {
    ordinal_ = Ordinal::kPizza;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Pizza& mutable_pizza() {
    ZX_ASSERT(ordinal_ == Ordinal::kPizza);
    return *static_cast<::llcpp::fidl::test::union_::Pizza*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Pizza& pizza() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPizza);
    return *static_cast<::llcpp::fidl::test::union_::Pizza*>(
        envelope_.data.get());
  }

  bool is_pasta() const { return ordinal_ == Ordinal::kPasta; }

  static StrictPizzaOrPasta WithPasta(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>&& val) {
    StrictPizzaOrPasta result;
    result.set_pasta(std::move(val));
    return result;
  }

  void set_pasta(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>&& elem) {
    ordinal_ = Ordinal::kPasta;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Pasta& mutable_pasta() {
    ZX_ASSERT(ordinal_ == Ordinal::kPasta);
    return *static_cast<::llcpp::fidl::test::union_::Pasta*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Pasta& pasta() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPasta);
    return *static_cast<::llcpp::fidl::test::union_::Pasta*>(
        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_union_StrictPizzaOrPastaTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

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

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>>(
                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_union_PizzaOrPastaTable;

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

  PizzaOrPasta(PizzaOrPasta&&) = default;
  PizzaOrPasta& operator=(PizzaOrPasta&&) = default;

  ~PizzaOrPasta() { reset_ptr(nullptr); }

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

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

  bool is_pizza() const { return ordinal_ == Ordinal::kPizza; }

  static PizzaOrPasta WithPizza(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>&& val) {
    PizzaOrPasta result;
    result.set_pizza(std::move(val));
    return result;
  }

  void set_pizza(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>&& elem) {
    ordinal_ = Ordinal::kPizza;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Pizza& mutable_pizza() {
    ZX_ASSERT(ordinal_ == Ordinal::kPizza);
    return *static_cast<::llcpp::fidl::test::union_::Pizza*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Pizza& pizza() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPizza);
    return *static_cast<::llcpp::fidl::test::union_::Pizza*>(
        envelope_.data.get());
  }

  bool is_pasta() const { return ordinal_ == Ordinal::kPasta; }

  static PizzaOrPasta WithPasta(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>&& val) {
    PizzaOrPasta result;
    result.set_pasta(std::move(val));
    return result;
  }

  void set_pasta(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>&& elem) {
    ordinal_ = Ordinal::kPasta;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Pasta& mutable_pasta() {
    ZX_ASSERT(ordinal_ == Ordinal::kPasta);
    return *static_cast<::llcpp::fidl::test::union_::Pasta*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Pasta& pasta() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPasta);
    return *static_cast<::llcpp::fidl::test::union_::Pasta*>(
        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_union_PizzaOrPastaTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

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

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>>(
                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_union_FlexiblePizzaOrPastaTable;

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

  FlexiblePizzaOrPasta(FlexiblePizzaOrPasta&&) = default;
  FlexiblePizzaOrPasta& operator=(FlexiblePizzaOrPasta&&) = default;

  ~FlexiblePizzaOrPasta() { reset_ptr(nullptr); }

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

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

  bool is_pizza() const { return ordinal_ == Ordinal::kPizza; }

  static FlexiblePizzaOrPasta WithPizza(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>&& val) {
    FlexiblePizzaOrPasta result;
    result.set_pizza(std::move(val));
    return result;
  }

  void set_pizza(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>&& elem) {
    ordinal_ = Ordinal::kPizza;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Pizza& mutable_pizza() {
    ZX_ASSERT(ordinal_ == Ordinal::kPizza);
    return *static_cast<::llcpp::fidl::test::union_::Pizza*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Pizza& pizza() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPizza);
    return *static_cast<::llcpp::fidl::test::union_::Pizza*>(
        envelope_.data.get());
  }

  bool is_pasta() const { return ordinal_ == Ordinal::kPasta; }

  static FlexiblePizzaOrPasta WithPasta(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>&& val) {
    FlexiblePizzaOrPasta result;
    result.set_pasta(std::move(val));
    return result;
  }

  void set_pasta(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>&& elem) {
    ordinal_ = Ordinal::kPasta;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Pasta& mutable_pasta() {
    ZX_ASSERT(ordinal_ == Ordinal::kPasta);
    return *static_cast<::llcpp::fidl::test::union_::Pasta*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Pasta& pasta() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPasta);
    return *static_cast<::llcpp::fidl::test::union_::Pasta*>(
        envelope_.data.get());
  }
  Tag which() const;

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

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

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>>(
                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_union_ExplicitPizzaOrPastaTable;

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

  ExplicitPizzaOrPasta(ExplicitPizzaOrPasta&&) = default;
  ExplicitPizzaOrPasta& operator=(ExplicitPizzaOrPasta&&) = default;

  ~ExplicitPizzaOrPasta() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kPizza = 1,  // 0x1
    kPasta = 4,  // 0x4
  };

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

  bool is_pizza() const { return ordinal_ == Ordinal::kPizza; }

  static ExplicitPizzaOrPasta WithPizza(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>&& val) {
    ExplicitPizzaOrPasta result;
    result.set_pizza(std::move(val));
    return result;
  }

  void set_pizza(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>&& elem) {
    ordinal_ = Ordinal::kPizza;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Pizza& mutable_pizza() {
    ZX_ASSERT(ordinal_ == Ordinal::kPizza);
    return *static_cast<::llcpp::fidl::test::union_::Pizza*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Pizza& pizza() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPizza);
    return *static_cast<::llcpp::fidl::test::union_::Pizza*>(
        envelope_.data.get());
  }

  bool is_pasta() const { return ordinal_ == Ordinal::kPasta; }

  static ExplicitPizzaOrPasta WithPasta(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>&& val) {
    ExplicitPizzaOrPasta result;
    result.set_pasta(std::move(val));
    return result;
  }

  void set_pasta(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>&& elem) {
    ordinal_ = Ordinal::kPasta;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Pasta& mutable_pasta() {
    ZX_ASSERT(ordinal_ == Ordinal::kPasta);
    return *static_cast<::llcpp::fidl::test::union_::Pasta*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Pasta& pasta() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPasta);
    return *static_cast<::llcpp::fidl::test::union_::Pasta*>(
        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_union_ExplicitPizzaOrPastaTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kPizza = 1,  // 0x1
    kPasta = 4,  // 0x4
  };

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pizza>>(
                std::move(envelope_.data));
        break;
      }
      case 4: {
        ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Pasta>>(
                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_union_OlderSimpleUnionTable;

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

  OlderSimpleUnion(OlderSimpleUnion&&) = default;
  OlderSimpleUnion& operator=(OlderSimpleUnion&&) = default;

  ~OlderSimpleUnion() { reset_ptr(nullptr); }

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

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

  bool is_i() const { return ordinal_ == Ordinal::kI; }

  static OlderSimpleUnion WithI(::fidl::tracking_ptr<int64_t>&& val) {
    OlderSimpleUnion result;
    result.set_i(std::move(val));
    return result;
  }

  void set_i(::fidl::tracking_ptr<int64_t>&& elem) {
    ordinal_ = Ordinal::kI;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int64_t& mutable_i() {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int64_t*>(envelope_.data.get());
  }
  const int64_t& i() const {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int64_t*>(envelope_.data.get());
  }

  bool is_f() const { return ordinal_ == Ordinal::kF; }

  static OlderSimpleUnion WithF(::fidl::tracking_ptr<float>&& val) {
    OlderSimpleUnion result;
    result.set_f(std::move(val));
    return result;
  }

  void set_f(::fidl::tracking_ptr<float>&& elem) {
    ordinal_ = Ordinal::kF;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  float& mutable_f() {
    ZX_ASSERT(ordinal_ == Ordinal::kF);
    return *static_cast<float*>(envelope_.data.get());
  }
  const float& f() const {
    ZX_ASSERT(ordinal_ == Ordinal::kF);
    return *static_cast<float*>(envelope_.data.get());
  }
  Tag which() const;

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

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<int64_t> to_destroy =
            static_cast<::fidl::tracking_ptr<int64_t>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::fidl::tracking_ptr<float> to_destroy =
            static_cast<::fidl::tracking_ptr<float>>(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_union_NewerSimpleUnionTable;

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

  NewerSimpleUnion(NewerSimpleUnion&&) = default;
  NewerSimpleUnion& operator=(NewerSimpleUnion&&) = default;

  ~NewerSimpleUnion() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kI = 1,  // 0x1
    kS = 2,  // 0x2
    kV = 3,  // 0x3
    kUnknown = ::std::numeric_limits<::fidl_union_tag_t>::max(),
  };

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

  bool is_i() const { return ordinal_ == Ordinal::kI; }

  static NewerSimpleUnion WithI(::fidl::tracking_ptr<int64_t>&& val) {
    NewerSimpleUnion result;
    result.set_i(std::move(val));
    return result;
  }

  void set_i(::fidl::tracking_ptr<int64_t>&& elem) {
    ordinal_ = Ordinal::kI;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int64_t& mutable_i() {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int64_t*>(envelope_.data.get());
  }
  const int64_t& i() const {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int64_t*>(envelope_.data.get());
  }

  bool is_s() const { return ordinal_ == Ordinal::kS; }

  static NewerSimpleUnion WithS(
      ::fidl::tracking_ptr<::fidl::StringView>&& val) {
    NewerSimpleUnion result;
    result.set_s(std::move(val));
    return result;
  }

  void set_s(::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kS;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_s() {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& s() const {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }

  bool is_v() const { return ordinal_ == Ordinal::kV; }

  static NewerSimpleUnion WithV(
      ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>&& val) {
    NewerSimpleUnion result;
    result.set_v(std::move(val));
    return result;
  }

  void set_v(
      ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>&& elem) {
    ordinal_ = Ordinal::kV;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::VectorView<::fidl::StringView>& mutable_v() {
    ZX_ASSERT(ordinal_ == Ordinal::kV);
    return *static_cast<::fidl::VectorView<::fidl::StringView>*>(
        envelope_.data.get());
  }
  const ::fidl::VectorView<::fidl::StringView>& v() const {
    ZX_ASSERT(ordinal_ == Ordinal::kV);
    return *static_cast<::fidl::VectorView<::fidl::StringView>*>(
        envelope_.data.get());
  }
  Tag which() const;

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

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kI = 1,  // 0x1
    kS = 2,  // 0x2
    kV = 3,  // 0x3
  };

  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<int64_t> to_destroy =
            static_cast<::fidl::tracking_ptr<int64_t>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::fidl::tracking_ptr<::fidl::StringView> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::StringView>>(
                std::move(envelope_.data));
        break;
      }
      case 3: {
        ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>
            to_destroy = static_cast<
                ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>>(
                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_union_FlexibleUnionTable;

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 {
    kPrimitive = 1,                         // 0x1
    kStringNeedsConstructor = 2,            // 0x2
    kVectorStringAlsoNeedsConstructor = 3,  // 0x3
    kUnknown = ::std::numeric_limits<::fidl_union_tag_t>::max(),
  };

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

  bool is_Primitive() const { return ordinal_ == Ordinal::kPrimitive; }

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

  void set_Primitive(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kPrimitive;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_Primitive() {
    ZX_ASSERT(ordinal_ == Ordinal::kPrimitive);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& Primitive() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPrimitive);
    return *static_cast<int32_t*>(envelope_.data.get());
  }

  bool is_StringNeedsConstructor() const {
    return ordinal_ == Ordinal::kStringNeedsConstructor;
  }

  static FlexibleUnion WithStringNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::StringView>&& val) {
    FlexibleUnion result;
    result.set_StringNeedsConstructor(std::move(val));
    return result;
  }

  void set_StringNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kStringNeedsConstructor;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_StringNeedsConstructor() {
    ZX_ASSERT(ordinal_ == Ordinal::kStringNeedsConstructor);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& StringNeedsConstructor() const {
    ZX_ASSERT(ordinal_ == Ordinal::kStringNeedsConstructor);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }

  bool is_VectorStringAlsoNeedsConstructor() const {
    return ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor;
  }

  static FlexibleUnion WithVectorStringAlsoNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>&& val) {
    FlexibleUnion result;
    result.set_VectorStringAlsoNeedsConstructor(std::move(val));
    return result;
  }

  void set_VectorStringAlsoNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>&& elem) {
    ordinal_ = Ordinal::kVectorStringAlsoNeedsConstructor;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::VectorView<::fidl::StringView>&
  mutable_VectorStringAlsoNeedsConstructor() {
    ZX_ASSERT(ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor);
    return *static_cast<::fidl::VectorView<::fidl::StringView>*>(
        envelope_.data.get());
  }
  const ::fidl::VectorView<::fidl::StringView>&
  VectorStringAlsoNeedsConstructor() const {
    ZX_ASSERT(ordinal_ == Ordinal::kVectorStringAlsoNeedsConstructor);
    return *static_cast<::fidl::VectorView<::fidl::StringView>*>(
        envelope_.data.get());
  }
  Tag which() const;

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

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kPrimitive = 1,                         // 0x1
    kStringNeedsConstructor = 2,            // 0x2
    kVectorStringAlsoNeedsConstructor = 3,  // 0x3
  };

  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;
      }
      case 2: {
        ::fidl::tracking_ptr<::fidl::StringView> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::StringView>>(
                std::move(envelope_.data));
        break;
      }
      case 3: {
        ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>
            to_destroy = static_cast<
                ::fidl::tracking_ptr<::fidl::VectorView<::fidl::StringView>>>(
                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_union_FlexibleFooTable;

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

  FlexibleFoo(FlexibleFoo&&) = default;
  FlexibleFoo& operator=(FlexibleFoo&&) = default;

  ~FlexibleFoo() { reset_ptr(nullptr); }

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

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

  bool is_s() const { return ordinal_ == Ordinal::kS; }

  static FlexibleFoo WithS(::fidl::tracking_ptr<::fidl::StringView>&& val) {
    FlexibleFoo result;
    result.set_s(std::move(val));
    return result;
  }

  void set_s(::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kS;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_s() {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& s() const {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }

  bool is_i() const { return ordinal_ == Ordinal::kI; }

  static FlexibleFoo WithI(::fidl::tracking_ptr<int32_t>&& val) {
    FlexibleFoo result;
    result.set_i(std::move(val));
    return result;
  }

  void set_i(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kI;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_i() {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& i() const {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  Tag which() const;

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

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

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

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

  FieldCollision(FieldCollision&&) = default;
  FieldCollision& operator=(FieldCollision&&) = default;

  ~FieldCollision() { reset_ptr(nullptr); }

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

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

  bool is_field_collision_tag() const {
    return ordinal_ == Ordinal::kFieldCollisionTag;
  }

  static FieldCollision WithFieldCollisionTag(
      ::fidl::tracking_ptr<int32_t>&& val) {
    FieldCollision result;
    result.set_field_collision_tag(std::move(val));
    return result;
  }

  void set_field_collision_tag(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kFieldCollisionTag;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_field_collision_tag() {
    ZX_ASSERT(ordinal_ == Ordinal::kFieldCollisionTag);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& field_collision_tag() const {
    ZX_ASSERT(ordinal_ == Ordinal::kFieldCollisionTag);
    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_union_FieldCollisionTable;
  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,
    kFieldCollisionTag = 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_union_ExplicitXUnionTable;

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

  ExplicitXUnion(ExplicitXUnion&&) = default;
  ExplicitXUnion& operator=(ExplicitXUnion&&) = default;

  ~ExplicitXUnion() { reset_ptr(nullptr); }

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

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

  bool is_i() const { return ordinal_ == Ordinal::kI; }

  static ExplicitXUnion WithI(::fidl::tracking_ptr<int64_t>&& val) {
    ExplicitXUnion result;
    result.set_i(std::move(val));
    return result;
  }

  void set_i(::fidl::tracking_ptr<int64_t>&& elem) {
    ordinal_ = Ordinal::kI;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int64_t& mutable_i() {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int64_t*>(envelope_.data.get());
  }
  const int64_t& i() const {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int64_t*>(envelope_.data.get());
  }

  bool is_f() const { return ordinal_ == Ordinal::kF; }

  static ExplicitXUnion WithF(::fidl::tracking_ptr<float>&& val) {
    ExplicitXUnion result;
    result.set_f(std::move(val));
    return result;
  }

  void set_f(::fidl::tracking_ptr<float>&& elem) {
    ordinal_ = Ordinal::kF;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  float& mutable_f() {
    ZX_ASSERT(ordinal_ == Ordinal::kF);
    return *static_cast<float*>(envelope_.data.get());
  }
  const float& f() const {
    ZX_ASSERT(ordinal_ == Ordinal::kF);
    return *static_cast<float*>(envelope_.data.get());
  }
  Tag which() const;

  static constexpr const fidl_type_t* Type =
      &fidl_test_union_ExplicitXUnionTable;
  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,
    kI = 1,  // 0x1
    kF = 4,  // 0x4
  };

  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<int64_t> to_destroy =
            static_cast<::fidl::tracking_ptr<int64_t>>(
                std::move(envelope_.data));
        break;
      }
      case 4: {
        ::fidl::tracking_ptr<float> to_destroy =
            static_cast<::fidl::tracking_ptr<float>>(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_union_ExplicitUnionTable;

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

  ExplicitUnion(ExplicitUnion&&) = default;
  ExplicitUnion& operator=(ExplicitUnion&&) = default;

  ~ExplicitUnion() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kPrimitive = 1,               // 0x1
    kStringNeedsConstructor = 3,  // 0x3
  };

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

  bool is_Primitive() const { return ordinal_ == Ordinal::kPrimitive; }

  static ExplicitUnion WithPrimitive(::fidl::tracking_ptr<int32_t>&& val) {
    ExplicitUnion result;
    result.set_Primitive(std::move(val));
    return result;
  }

  void set_Primitive(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kPrimitive;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_Primitive() {
    ZX_ASSERT(ordinal_ == Ordinal::kPrimitive);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& Primitive() const {
    ZX_ASSERT(ordinal_ == Ordinal::kPrimitive);
    return *static_cast<int32_t*>(envelope_.data.get());
  }

  bool is_StringNeedsConstructor() const {
    return ordinal_ == Ordinal::kStringNeedsConstructor;
  }

  static ExplicitUnion WithStringNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::StringView>&& val) {
    ExplicitUnion result;
    result.set_StringNeedsConstructor(std::move(val));
    return result;
  }

  void set_StringNeedsConstructor(
      ::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kStringNeedsConstructor;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_StringNeedsConstructor() {
    ZX_ASSERT(ordinal_ == Ordinal::kStringNeedsConstructor);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& StringNeedsConstructor() const {
    ZX_ASSERT(ordinal_ == Ordinal::kStringNeedsConstructor);
    return *static_cast<::fidl::StringView*>(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_union_ExplicitUnionTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kPrimitive = 1,               // 0x1
    kStringNeedsConstructor = 3,  // 0x3
  };

  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;
      }
      case 3: {
        ::fidl::tracking_ptr<::fidl::StringView> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::StringView>>(
                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_union_ExplicitStrictFooTable;

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

  ExplicitStrictFoo(ExplicitStrictFoo&&) = default;
  ExplicitStrictFoo& operator=(ExplicitStrictFoo&&) = default;

  ~ExplicitStrictFoo() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kS = 3,  // 0x3
    kI = 2,  // 0x2
  };

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

  bool is_s() const { return ordinal_ == Ordinal::kS; }

  static ExplicitStrictFoo WithS(
      ::fidl::tracking_ptr<::fidl::StringView>&& val) {
    ExplicitStrictFoo result;
    result.set_s(std::move(val));
    return result;
  }

  void set_s(::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kS;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_s() {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& s() const {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }

  bool is_i() const { return ordinal_ == Ordinal::kI; }

  static ExplicitStrictFoo WithI(::fidl::tracking_ptr<int32_t>&& val) {
    ExplicitStrictFoo result;
    result.set_i(std::move(val));
    return result;
  }

  void set_i(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kI;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_i() {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& i() const {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    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_union_ExplicitStrictFooTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kS = 3,  // 0x3
    kI = 2,  // 0x2
  };

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 3: {
        ::fidl::tracking_ptr<::fidl::StringView> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::StringView>>(
                std::move(envelope_.data));
        break;
      }
      case 2: {
        ::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_union_ExplicitFooTable;

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

  ExplicitFoo(ExplicitFoo&&) = default;
  ExplicitFoo& operator=(ExplicitFoo&&) = default;

  ~ExplicitFoo() { reset_ptr(nullptr); }

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

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

  bool is_s() const { return ordinal_ == Ordinal::kS; }

  static ExplicitFoo WithS(::fidl::tracking_ptr<::fidl::StringView>&& val) {
    ExplicitFoo result;
    result.set_s(std::move(val));
    return result;
  }

  void set_s(::fidl::tracking_ptr<::fidl::StringView>&& elem) {
    ordinal_ = Ordinal::kS;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::fidl::StringView& mutable_s() {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }
  const ::fidl::StringView& s() const {
    ZX_ASSERT(ordinal_ == Ordinal::kS);
    return *static_cast<::fidl::StringView*>(envelope_.data.get());
  }

  bool is_i() const { return ordinal_ == Ordinal::kI; }

  static ExplicitFoo WithI(::fidl::tracking_ptr<int32_t>&& val) {
    ExplicitFoo result;
    result.set_i(std::move(val));
    return result;
  }

  void set_i(::fidl::tracking_ptr<int32_t>&& elem) {
    ordinal_ = Ordinal::kI;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  int32_t& mutable_i() {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  const int32_t& i() const {
    ZX_ASSERT(ordinal_ == Ordinal::kI);
    return *static_cast<int32_t*>(envelope_.data.get());
  }
  Tag which() const;

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

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kS = 2,  // 0x2
    kI = 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 2: {
        ::fidl::tracking_ptr<::fidl::StringView> to_destroy =
            static_cast<::fidl::tracking_ptr<::fidl::StringView>>(
                std::move(envelope_.data));
        break;
      }
      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_union_XUnionContainingEmptyStructTable;

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

  XUnionContainingEmptyStruct(XUnionContainingEmptyStruct&&) = default;
  XUnionContainingEmptyStruct& operator=(XUnionContainingEmptyStruct&&) =
      default;

  ~XUnionContainingEmptyStruct() { reset_ptr(nullptr); }

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

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

  bool is_empty() const { return ordinal_ == Ordinal::kEmpty; }

  static XUnionContainingEmptyStruct WithEmpty(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Empty>&& val) {
    XUnionContainingEmptyStruct result;
    result.set_empty(std::move(val));
    return result;
  }

  void set_empty(
      ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Empty>&& elem) {
    ordinal_ = Ordinal::kEmpty;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::llcpp::fidl::test::union_::Empty& mutable_empty() {
    ZX_ASSERT(ordinal_ == Ordinal::kEmpty);
    return *static_cast<::llcpp::fidl::test::union_::Empty*>(
        envelope_.data.get());
  }
  const ::llcpp::fidl::test::union_::Empty& empty() const {
    ZX_ASSERT(ordinal_ == Ordinal::kEmpty);
    return *static_cast<::llcpp::fidl::test::union_::Empty*>(
        envelope_.data.get());
  }
  Tag which() const;

  static constexpr const fidl_type_t* Type =
      &fidl_test_union_XUnionContainingEmptyStructTable;
  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,
    kEmpty = 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<::llcpp::fidl::test::union_::Empty> to_destroy =
            static_cast<
                ::fidl::tracking_ptr<::llcpp::fidl::test::union_::Empty>>(
                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_union_StructWithNullableXUnionTable;

struct StructWithNullableXUnion {
  static constexpr const fidl_type_t* Type =
      &fidl_test_union_StructWithNullableXUnionTable;
  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;

  ::llcpp::fidl::test::union_::OlderSimpleUnion x1 = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          StructWithNullableXUnion* value)
        : message_(bytes, byte_size, sizeof(StructWithNullableXUnion), nullptr,
                   0, 0) {
      message_.LinearizeAndEncode<StructWithNullableXUnion>(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(StructWithNullableXUnion* 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 StructWithNullableXUnion>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct StructWithNullableXUnion>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

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

extern "C" const fidl_type_t fidl_test_union_PizzaTable;

struct Pizza {
  static constexpr const fidl_type_t* Type = &fidl_test_union_PizzaTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 16;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

  ::fidl::VectorView<::fidl::StringView> toppings = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size, Pizza* value)
        : message_(bytes, byte_size, sizeof(Pizza), nullptr, 0, 0) {
      message_.LinearizeAndEncode<Pizza>(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(Pizza* value)
        : bytes_(std::make_unique<
                 ::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>()),
          message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_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:
    std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
        bytes_;
    UnownedEncodedMessage message_;
  };

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

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

extern "C" const fidl_type_t fidl_test_union_PastaTable;

struct Pasta {
  static constexpr const fidl_type_t* Type = &fidl_test_union_PastaTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 16;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 16;
  static constexpr bool HasPointer = true;

  ::fidl::StringView sauce = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size, Pasta* value)
        : message_(bytes, byte_size, sizeof(Pasta), nullptr, 0, 0) {
      message_.LinearizeAndEncode<Pasta>(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(Pasta* 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 Pasta>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct Pasta>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

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

extern "C" const fidl_type_t
    fidl_test_union_TestProtocolStrictXUnionHenceResponseMayBeStackAllocatedRequestTable;
extern "C" const fidl_type_t
    fidl_test_union_TestProtocolStrictXUnionHenceResponseMayBeStackAllocatedResponseTable;
extern "C" const fidl_type_t
    fidl_test_union_TestProtocolFlexibleXUnionHenceResponseMustBeHeapAllocatedRequestTable;
extern "C" const fidl_type_t
    fidl_test_union_TestProtocolFlexibleXUnionHenceResponseMustBeHeapAllocatedResponseTable;

class TestProtocol final {
  TestProtocol() = delete;

 public:
  struct StrictXUnionHenceResponseMayBeStackAllocatedResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::llcpp::fidl::test::union_::StrictBoundedXUnion xu;
    explicit StrictXUnionHenceResponseMayBeStackAllocatedResponse(
        ::llcpp::fidl::test::union_::StrictBoundedXUnion& xu)
        : xu(std::move(xu)) {
      _InitHeader();
    }
    StrictXUnionHenceResponseMayBeStackAllocatedResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(
          uint8_t* _bytes, uint32_t _byte_size,
          ::llcpp::fidl::test::union_::StrictBoundedXUnion& xu)
          : message_(
                _bytes, _byte_size,
                sizeof(StrictXUnionHenceResponseMayBeStackAllocatedResponse),
                nullptr, 0, 0) {
        FIDL_ALIGNDECL StrictXUnionHenceResponseMayBeStackAllocatedResponse
            _response{xu};
        message_.LinearizeAndEncode<
            StrictXUnionHenceResponseMayBeStackAllocatedResponse>(&_response);
      }
      UnownedEncodedMessage(
          uint8_t* bytes, uint32_t byte_size,
          StrictXUnionHenceResponseMayBeStackAllocatedResponse* response)
          : message_(
                bytes, byte_size,
                sizeof(StrictXUnionHenceResponseMayBeStackAllocatedResponse),
                nullptr, 0, 0) {
        message_.LinearizeAndEncode<
            StrictXUnionHenceResponseMayBeStackAllocatedResponse>(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:
      StrictXUnionHenceResponseMayBeStackAllocatedResponse& Message() {
        return *reinterpret_cast<
            StrictXUnionHenceResponseMayBeStackAllocatedResponse*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(
          ::llcpp::fidl::test::union_::StrictBoundedXUnion& xu)
          : message_(bytes_, sizeof(bytes_), xu) {}
      explicit OwnedEncodedMessage(
          StrictXUnionHenceResponseMayBeStackAllocatedResponse* 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<StrictXUnionHenceResponseMayBeStackAllocatedResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<StrictXUnionHenceResponseMayBeStackAllocatedResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

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

   private:
    void _InitHeader();
  };
  struct StrictXUnionHenceResponseMayBeStackAllocatedRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit StrictXUnionHenceResponseMayBeStackAllocatedRequest(
        zx_txid_t _txid) {
      _InitHeader(_txid);
    }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(
                _bytes, _byte_size,
                sizeof(StrictXUnionHenceResponseMayBeStackAllocatedRequest),
                nullptr, 0, 0) {
        FIDL_ALIGNDECL StrictXUnionHenceResponseMayBeStackAllocatedRequest
            _request(_txid);
        message_.LinearizeAndEncode<
            StrictXUnionHenceResponseMayBeStackAllocatedRequest>(&_request);
      }
      UnownedEncodedMessage(
          uint8_t* bytes, uint32_t byte_size,
          StrictXUnionHenceResponseMayBeStackAllocatedRequest* request)
          : message_(
                bytes, byte_size,
                sizeof(StrictXUnionHenceResponseMayBeStackAllocatedRequest),
                nullptr, 0, 0) {
        message_.LinearizeAndEncode<
            StrictXUnionHenceResponseMayBeStackAllocatedRequest>(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:
      StrictXUnionHenceResponseMayBeStackAllocatedRequest& Message() {
        return *reinterpret_cast<
            StrictXUnionHenceResponseMayBeStackAllocatedRequest*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(
          StrictXUnionHenceResponseMayBeStackAllocatedRequest* 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<StrictXUnionHenceResponseMayBeStackAllocatedRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<StrictXUnionHenceResponseMayBeStackAllocatedRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

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

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::llcpp::fidl::test::union_::OlderSimpleUnion xu;
    explicit FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse(
        ::llcpp::fidl::test::union_::OlderSimpleUnion& xu)
        : xu(std::move(xu)) {
      _InitHeader();
    }
    FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse() { _InitHeader(); }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            ::llcpp::fidl::test::union_::OlderSimpleUnion& xu)
          : message_(
                _bytes, _byte_size,
                sizeof(FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse),
                nullptr, 0, 0) {
        FIDL_ALIGNDECL FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse
            _response{xu};
        message_.LinearizeAndEncode<
            FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse>(&_response);
      }
      UnownedEncodedMessage(
          uint8_t* bytes, uint32_t byte_size,
          FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse* response)
          : message_(
                bytes, byte_size,
                sizeof(FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse),
                nullptr, 0, 0) {
        message_.LinearizeAndEncode<
            FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse>(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:
      FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse& Message() {
        return *reinterpret_cast<
            FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(
          ::llcpp::fidl::test::union_::OlderSimpleUnion& xu)
          : message_(bytes_, sizeof(bytes_), xu) {}
      explicit OwnedEncodedMessage(
          FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse* 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<FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

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

   private:
    void _InitHeader();
  };
  struct FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest(
        zx_txid_t _txid) {
      _InitHeader(_txid);
    }

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

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(
                _bytes, _byte_size,
                sizeof(FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest),
                nullptr, 0, 0) {
        FIDL_ALIGNDECL FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest
            _request(_txid);
        message_.LinearizeAndEncode<
            FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest>(&_request);
      }
      UnownedEncodedMessage(
          uint8_t* bytes, uint32_t byte_size,
          FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest* request)
          : message_(
                bytes, byte_size,
                sizeof(FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest),
                nullptr, 0, 0) {
        message_.LinearizeAndEncode<
            FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest>(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:
      FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest& Message() {
        return *reinterpret_cast<
            FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest*>(
            message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(
          FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest* 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<FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

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

   private:
    void _InitHeader(zx_txid_t _txid);
  };

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

     private:
      uint8_t* bytes_;
    };
  };

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  struct AsyncEventHandlers;
  class StrictXUnionHenceResponseMayBeStackAllocatedResponseContext;
  class FlexibleXUnionHenceResponseMustBeHeapAllocatedResponseContext;
  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 = TestProtocol;

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

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

    using StrictXUnionHenceResponseMayBeStackAllocatedCompleter =
        ::fidl::Completer<
            StrictXUnionHenceResponseMayBeStackAllocatedCompleterBase>;

    virtual void StrictXUnionHenceResponseMayBeStackAllocated(
        StrictXUnionHenceResponseMayBeStackAllocatedCompleter::Sync&
            _completer) = 0;

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

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

    using FlexibleXUnionHenceResponseMustBeHeapAllocatedCompleter =
        ::fidl::Completer<
            FlexibleXUnionHenceResponseMustBeHeapAllocatedCompleterBase>;

    virtual void FlexibleXUnionHenceResponseMustBeHeapAllocated(
        FlexibleXUnionHenceResponseMustBeHeapAllocatedCompleter::Sync&
            _completer) = 0;

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

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

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

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

  class EventSender;
  class WeakEventSender;
};

extern "C" const fidl_type_t fidl_test_union_NullableUnionStructTable;

struct NullableUnionStruct {
  static constexpr const fidl_type_t* Type =
      &fidl_test_union_NullableUnionStructTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

  ::llcpp::fidl::test::union_::Union the_union = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          NullableUnionStruct* value)
        : message_(bytes, byte_size, sizeof(NullableUnionStruct), nullptr, 0,
                   0) {
      message_.LinearizeAndEncode<NullableUnionStruct>(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(NullableUnionStruct* value)
        : bytes_(std::make_unique<
                 ::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>()),
          message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_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:
    std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
        bytes_;
    UnownedEncodedMessage message_;
  };

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

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

extern "C" const fidl_type_t fidl_test_union_EmptyTable;

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

  uint8_t __reserved = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size, Empty* value)
        : message_(bytes, byte_size, sizeof(Empty), nullptr, 0, 0) {
      message_.LinearizeAndEncode<Empty>(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(Empty* 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 Empty>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct Empty>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

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

}  // namespace union_
}  // namespace test
}  // namespace fidl
}  // namespace llcpp

namespace fidl {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

template <>
struct IsFidlType<::llcpp::fidl::test::union_::TestProtocol::
                      StrictXUnionHenceResponseMayBeStackAllocatedRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fidl::test::union_::TestProtocol::
                         StrictXUnionHenceResponseMayBeStackAllocatedRequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::union_::TestProtocol::
               StrictXUnionHenceResponseMayBeStackAllocatedRequest) ==
    ::llcpp::fidl::test::union_::TestProtocol::
        StrictXUnionHenceResponseMayBeStackAllocatedRequest::PrimarySize);

template <>
struct IsFidlType<::llcpp::fidl::test::union_::TestProtocol::
                      StrictXUnionHenceResponseMayBeStackAllocatedResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fidl::test::union_::TestProtocol::
                         StrictXUnionHenceResponseMayBeStackAllocatedResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::union_::TestProtocol::
               StrictXUnionHenceResponseMayBeStackAllocatedResponse) ==
    ::llcpp::fidl::test::union_::TestProtocol::
        StrictXUnionHenceResponseMayBeStackAllocatedResponse::PrimarySize);
static_assert(offsetof(::llcpp::fidl::test::union_::TestProtocol::
                           StrictXUnionHenceResponseMayBeStackAllocatedResponse,
                       xu) == 16);

template <>
struct IsFidlType<::llcpp::fidl::test::union_::TestProtocol::
                      FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fidl::test::union_::TestProtocol::
                         FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::union_::TestProtocol::
               FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest) ==
    ::llcpp::fidl::test::union_::TestProtocol::
        FlexibleXUnionHenceResponseMustBeHeapAllocatedRequest::PrimarySize);

template <>
struct IsFidlType<::llcpp::fidl::test::union_::TestProtocol::
                      FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fidl::test::union_::TestProtocol::
                         FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::union_::TestProtocol::
               FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse) ==
    ::llcpp::fidl::test::union_::TestProtocol::
        FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::union_::TestProtocol::
                 FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse,
             xu) == 16);

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

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

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

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

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

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

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

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

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

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

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

}  // namespace fidl

namespace llcpp {

namespace fidl {
namespace test {
namespace union_ {

struct TestProtocol::AsyncEventHandlers {};

class TestProtocol::StrictXUnionHenceResponseMayBeStackAllocatedResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  StrictXUnionHenceResponseMayBeStackAllocatedResponseContext();

  virtual void OnReply(
      TestProtocol::StrictXUnionHenceResponseMayBeStackAllocatedResponse*
          message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class TestProtocol::
    FlexibleXUnionHenceResponseMustBeHeapAllocatedResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  FlexibleXUnionHenceResponseMustBeHeapAllocatedResponseContext();

  virtual void OnReply(
      TestProtocol::FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse*
          message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class TestProtocol::ClientImpl final : private ::fidl::internal::ClientBase {
 public:
  // Asynchronous variant of
  // |TestProtocol.StrictXUnionHenceResponseMayBeStackAllocated()|. Allocates 16
  // bytes of request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result StrictXUnionHenceResponseMayBeStackAllocated(
      ::fit::callback<
          void(StrictXUnionHenceResponseMayBeStackAllocatedResponse* response)>
          _cb);
  // Asynchronous variant of
  // |TestProtocol.StrictXUnionHenceResponseMayBeStackAllocated()|. Caller
  // provides the backing storage for FIDL message via request buffer. Ownership
  // of _context is given unsafely to the binding until OnError() or OnReply()
  // are called on it.
  ::fidl::Result StrictXUnionHenceResponseMayBeStackAllocated(
      StrictXUnionHenceResponseMayBeStackAllocatedResponseContext* _context);
  // Synchronous variant of
  // |TestProtocol.StrictXUnionHenceResponseMayBeStackAllocated()|. Allocates 88
  // bytes of message buffer on the stack. No heap allocation necessary.
  ResultOf::StrictXUnionHenceResponseMayBeStackAllocated
  StrictXUnionHenceResponseMayBeStackAllocated_Sync();

  // Synchronous variant of
  // |TestProtocol.StrictXUnionHenceResponseMayBeStackAllocated()|. Caller
  // provides the backing storage for FIDL message via request and response
  // buffers.
  UnownedResultOf::StrictXUnionHenceResponseMayBeStackAllocated
  StrictXUnionHenceResponseMayBeStackAllocated_Sync(
      ::fidl::BufferSpan _response_buffer);

  // Asynchronous variant of
  // |TestProtocol.FlexibleXUnionHenceResponseMustBeHeapAllocated()|. Allocates
  // 16 bytes of request buffer on the stack. The callback is stored on the
  // heap.
  ::fidl::Result FlexibleXUnionHenceResponseMustBeHeapAllocated(
      ::fit::callback<void(
          FlexibleXUnionHenceResponseMustBeHeapAllocatedResponse* response)>
          _cb);
  // Asynchronous variant of
  // |TestProtocol.FlexibleXUnionHenceResponseMustBeHeapAllocated()|. Caller
  // provides the backing storage for FIDL message via request buffer. Ownership
  // of _context is given unsafely to the binding until OnError() or OnReply()
  // are called on it.
  ::fidl::Result FlexibleXUnionHenceResponseMustBeHeapAllocated(
      FlexibleXUnionHenceResponseMustBeHeapAllocatedResponseContext* _context);
  // Synchronous variant of
  // |TestProtocol.FlexibleXUnionHenceResponseMustBeHeapAllocated()|. Allocates
  // 16 bytes of request buffer on the stack. Response is heap-allocated.
  ResultOf::FlexibleXUnionHenceResponseMustBeHeapAllocated
  FlexibleXUnionHenceResponseMustBeHeapAllocated_Sync();

  // Synchronous variant of
  // |TestProtocol.FlexibleXUnionHenceResponseMustBeHeapAllocated()|. Caller
  // provides the backing storage for FIDL message via request and response
  // buffers.
  UnownedResultOf::FlexibleXUnionHenceResponseMustBeHeapAllocated
  FlexibleXUnionHenceResponseMustBeHeapAllocated_Sync(
      ::fidl::BufferSpan _response_buffer);

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

  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 TestProtocol protocol, and can send events in that protocol.
class TestProtocol::EventSender {
 public:
  // Constructs an event sender with an invalid channel.
  EventSender() = default;

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

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

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

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

class TestProtocol::WeakEventSender {
 public:
 private:
  friend class ::fidl::ServerBindingRef<TestProtocol>;

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

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

}  // namespace union_
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
