// 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/object_view.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 <algorithm>
#include <cstddef>
#include <variant>
#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/client_end.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/result.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/server_end.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/sync_call.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fidl/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;
  }

  template <typename... Args>
  static Union WithPrimitive(::fidl::AnyAllocator& allocator, Args&&... args) {
    Union result;
    result.set_Primitive(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_Primitive(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPrimitive;
    set_Primitive(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static Union WithStringNeedsConstructor(::fidl::AnyAllocator& allocator,
                                          Args&&... args) {
    Union result;
    result.set_StringNeedsConstructor(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_StringNeedsConstructor(::fidl::AnyAllocator& allocator,
                                  Args&&... args) {
    ordinal_ = Ordinal::kStringNeedsConstructor;
    set_StringNeedsConstructor(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static Union WithVectorStringAlsoNeedsConstructor(
      ::fidl::AnyAllocator& allocator, Args&&... args) {
    Union result;
    result.set_VectorStringAlsoNeedsConstructor(
        ::fidl::ObjectView<::fidl::VectorView<::fidl::StringView>>(
            allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_VectorStringAlsoNeedsConstructor(::fidl::AnyAllocator& allocator,
                                            Args&&... args) {
    ordinal_ = Ordinal::kVectorStringAlsoNeedsConstructor;
    set_VectorStringAlsoNeedsConstructor(
        ::fidl::ObjectView<::fidl::VectorView<::fidl::StringView>>(
            allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static StrictUnion WithPrimitive(::fidl::AnyAllocator& allocator,
                                   Args&&... args) {
    StrictUnion result;
    result.set_Primitive(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_Primitive(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPrimitive;
    set_Primitive(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static StrictUnion WithStringNeedsConstructor(::fidl::AnyAllocator& allocator,
                                                Args&&... args) {
    StrictUnion result;
    result.set_StringNeedsConstructor(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_StringNeedsConstructor(::fidl::AnyAllocator& allocator,
                                  Args&&... args) {
    ordinal_ = Ordinal::kStringNeedsConstructor;
    set_StringNeedsConstructor(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static StrictUnion WithVectorStringAlsoNeedsConstructor(
      ::fidl::AnyAllocator& allocator, Args&&... args) {
    StrictUnion result;
    result.set_VectorStringAlsoNeedsConstructor(
        ::fidl::ObjectView<::fidl::VectorView<::fidl::StringView>>(
            allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_VectorStringAlsoNeedsConstructor(::fidl::AnyAllocator& allocator,
                                            Args&&... args) {
    ordinal_ = Ordinal::kVectorStringAlsoNeedsConstructor;
    set_VectorStringAlsoNeedsConstructor(
        ::fidl::ObjectView<::fidl::VectorView<::fidl::StringView>>(
            allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static StrictSimpleXUnion WithI(::fidl::AnyAllocator& allocator,
                                  Args&&... args) {
    StrictSimpleXUnion result;
    result.set_i(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_i(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kI;
    set_i(::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static StrictSimpleXUnion WithF(::fidl::AnyAllocator& allocator,
                                  Args&&... args) {
    StrictSimpleXUnion result;
    result.set_f(
        ::fidl::ObjectView<float>(allocator, std::forward<Args>(args)...));
    return result;
  }

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

  template <typename... Args>
  void set_f(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kF;
    set_f(::fidl::ObjectView<float>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static StrictSimpleXUnion WithS(::fidl::AnyAllocator& allocator,
                                  Args&&... args) {
    StrictSimpleXUnion result;
    result.set_s(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_s(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kS;
    set_s(::fidl::ObjectView<::fidl::StringView>(allocator,
                                                 std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static StrictFoo WithS(::fidl::AnyAllocator& allocator, Args&&... args) {
    StrictFoo result;
    result.set_s(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_s(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kS;
    set_s(::fidl::ObjectView<::fidl::StringView>(allocator,
                                                 std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static StrictFoo WithI(::fidl::AnyAllocator& allocator, Args&&... args) {
    StrictFoo result;
    result.set_i(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_i(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kI;
    set_i(::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static StrictBoundedXUnion WithV(::fidl::AnyAllocator& allocator,
                                   Args&&... args) {
    StrictBoundedXUnion result;
    result.set_v(::fidl::ObjectView<::fidl::VectorView<uint8_t>>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_v(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kV;
    set_v(::fidl::ObjectView<::fidl::VectorView<uint8_t>>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static ReverseOrdinalUnion WithSecond(::fidl::AnyAllocator& allocator,
                                        Args&&... args) {
    ReverseOrdinalUnion result;
    result.set_second(
        ::fidl::ObjectView<uint32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_second(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kSecond;
    set_second(
        ::fidl::ObjectView<uint32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static ReverseOrdinalUnion WithFirst(::fidl::AnyAllocator& allocator,
                                       Args&&... args) {
    ReverseOrdinalUnion result;
    result.set_first(
        ::fidl::ObjectView<uint32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_first(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kFirst;
    set_first(
        ::fidl::ObjectView<uint32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static StrictPizzaOrPasta WithPizza(::fidl::AnyAllocator& allocator,
                                      Args&&... args) {
    StrictPizzaOrPasta result;
    result.set_pizza(::fidl::ObjectView<::llcpp::fidl::test::union_::Pizza>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_pizza(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPizza;
    set_pizza(::fidl::ObjectView<::llcpp::fidl::test::union_::Pizza>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static StrictPizzaOrPasta WithPasta(::fidl::AnyAllocator& allocator,
                                      Args&&... args) {
    StrictPizzaOrPasta result;
    result.set_pasta(::fidl::ObjectView<::llcpp::fidl::test::union_::Pasta>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_pasta(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPasta;
    set_pasta(::fidl::ObjectView<::llcpp::fidl::test::union_::Pasta>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static PizzaOrPasta WithPizza(::fidl::AnyAllocator& allocator,
                                Args&&... args) {
    PizzaOrPasta result;
    result.set_pizza(::fidl::ObjectView<::llcpp::fidl::test::union_::Pizza>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_pizza(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPizza;
    set_pizza(::fidl::ObjectView<::llcpp::fidl::test::union_::Pizza>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static PizzaOrPasta WithPasta(::fidl::AnyAllocator& allocator,
                                Args&&... args) {
    PizzaOrPasta result;
    result.set_pasta(::fidl::ObjectView<::llcpp::fidl::test::union_::Pasta>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_pasta(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPasta;
    set_pasta(::fidl::ObjectView<::llcpp::fidl::test::union_::Pasta>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static FlexiblePizzaOrPasta WithPizza(::fidl::AnyAllocator& allocator,
                                        Args&&... args) {
    FlexiblePizzaOrPasta result;
    result.set_pizza(::fidl::ObjectView<::llcpp::fidl::test::union_::Pizza>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_pizza(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPizza;
    set_pizza(::fidl::ObjectView<::llcpp::fidl::test::union_::Pizza>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static FlexiblePizzaOrPasta WithPasta(::fidl::AnyAllocator& allocator,
                                        Args&&... args) {
    FlexiblePizzaOrPasta result;
    result.set_pasta(::fidl::ObjectView<::llcpp::fidl::test::union_::Pasta>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_pasta(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPasta;
    set_pasta(::fidl::ObjectView<::llcpp::fidl::test::union_::Pasta>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static ExplicitPizzaOrPasta WithPizza(::fidl::AnyAllocator& allocator,
                                        Args&&... args) {
    ExplicitPizzaOrPasta result;
    result.set_pizza(::fidl::ObjectView<::llcpp::fidl::test::union_::Pizza>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_pizza(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPizza;
    set_pizza(::fidl::ObjectView<::llcpp::fidl::test::union_::Pizza>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static ExplicitPizzaOrPasta WithPasta(::fidl::AnyAllocator& allocator,
                                        Args&&... args) {
    ExplicitPizzaOrPasta result;
    result.set_pasta(::fidl::ObjectView<::llcpp::fidl::test::union_::Pasta>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_pasta(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPasta;
    set_pasta(::fidl::ObjectView<::llcpp::fidl::test::union_::Pasta>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static OlderSimpleUnion WithI(::fidl::AnyAllocator& allocator,
                                Args&&... args) {
    OlderSimpleUnion result;
    result.set_i(
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_i(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kI;
    set_i(::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static OlderSimpleUnion WithF(::fidl::AnyAllocator& allocator,
                                Args&&... args) {
    OlderSimpleUnion result;
    result.set_f(
        ::fidl::ObjectView<float>(allocator, std::forward<Args>(args)...));
    return result;
  }

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

  template <typename... Args>
  void set_f(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kF;
    set_f(::fidl::ObjectView<float>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static NewerSimpleUnion WithI(::fidl::AnyAllocator& allocator,
                                Args&&... args) {
    NewerSimpleUnion result;
    result.set_i(
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_i(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kI;
    set_i(::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static NewerSimpleUnion WithS(::fidl::AnyAllocator& allocator,
                                Args&&... args) {
    NewerSimpleUnion result;
    result.set_s(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_s(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kS;
    set_s(::fidl::ObjectView<::fidl::StringView>(allocator,
                                                 std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static NewerSimpleUnion WithV(::fidl::AnyAllocator& allocator,
                                Args&&... args) {
    NewerSimpleUnion result;
    result.set_v(::fidl::ObjectView<::fidl::VectorView<::fidl::StringView>>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_v(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kV;
    set_v(::fidl::ObjectView<::fidl::VectorView<::fidl::StringView>>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static FlexibleUnion WithPrimitive(::fidl::AnyAllocator& allocator,
                                     Args&&... args) {
    FlexibleUnion result;
    result.set_Primitive(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_Primitive(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPrimitive;
    set_Primitive(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static FlexibleUnion WithStringNeedsConstructor(
      ::fidl::AnyAllocator& allocator, Args&&... args) {
    FlexibleUnion result;
    result.set_StringNeedsConstructor(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_StringNeedsConstructor(::fidl::AnyAllocator& allocator,
                                  Args&&... args) {
    ordinal_ = Ordinal::kStringNeedsConstructor;
    set_StringNeedsConstructor(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static FlexibleUnion WithVectorStringAlsoNeedsConstructor(
      ::fidl::AnyAllocator& allocator, Args&&... args) {
    FlexibleUnion result;
    result.set_VectorStringAlsoNeedsConstructor(
        ::fidl::ObjectView<::fidl::VectorView<::fidl::StringView>>(
            allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_VectorStringAlsoNeedsConstructor(::fidl::AnyAllocator& allocator,
                                            Args&&... args) {
    ordinal_ = Ordinal::kVectorStringAlsoNeedsConstructor;
    set_VectorStringAlsoNeedsConstructor(
        ::fidl::ObjectView<::fidl::VectorView<::fidl::StringView>>(
            allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static FlexibleFoo WithS(::fidl::AnyAllocator& allocator, Args&&... args) {
    FlexibleFoo result;
    result.set_s(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_s(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kS;
    set_s(::fidl::ObjectView<::fidl::StringView>(allocator,
                                                 std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static FlexibleFoo WithI(::fidl::AnyAllocator& allocator, Args&&... args) {
    FlexibleFoo result;
    result.set_i(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_i(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kI;
    set_i(::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static FieldCollision WithFieldCollisionTag(::fidl::AnyAllocator& allocator,
                                              Args&&... args) {
    FieldCollision result;
    result.set_field_collision_tag(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_field_collision_tag(::fidl::AnyAllocator& allocator,
                               Args&&... args) {
    ordinal_ = Ordinal::kFieldCollisionTag;
    set_field_collision_tag(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static ExplicitXUnion WithI(::fidl::AnyAllocator& allocator, Args&&... args) {
    ExplicitXUnion result;
    result.set_i(
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_i(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kI;
    set_i(::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static ExplicitXUnion WithF(::fidl::AnyAllocator& allocator, Args&&... args) {
    ExplicitXUnion result;
    result.set_f(
        ::fidl::ObjectView<float>(allocator, std::forward<Args>(args)...));
    return result;
  }

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

  template <typename... Args>
  void set_f(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kF;
    set_f(::fidl::ObjectView<float>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static ExplicitUnion WithPrimitive(::fidl::AnyAllocator& allocator,
                                     Args&&... args) {
    ExplicitUnion result;
    result.set_Primitive(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_Primitive(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kPrimitive;
    set_Primitive(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static ExplicitUnion WithStringNeedsConstructor(
      ::fidl::AnyAllocator& allocator, Args&&... args) {
    ExplicitUnion result;
    result.set_StringNeedsConstructor(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_StringNeedsConstructor(::fidl::AnyAllocator& allocator,
                                  Args&&... args) {
    ordinal_ = Ordinal::kStringNeedsConstructor;
    set_StringNeedsConstructor(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static ExplicitStrictFoo WithS(::fidl::AnyAllocator& allocator,
                                 Args&&... args) {
    ExplicitStrictFoo result;
    result.set_s(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_s(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kS;
    set_s(::fidl::ObjectView<::fidl::StringView>(allocator,
                                                 std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static ExplicitStrictFoo WithI(::fidl::AnyAllocator& allocator,
                                 Args&&... args) {
    ExplicitStrictFoo result;
    result.set_i(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_i(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kI;
    set_i(::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static ExplicitFoo WithS(::fidl::AnyAllocator& allocator, Args&&... args) {
    ExplicitFoo result;
    result.set_s(::fidl::ObjectView<::fidl::StringView>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_s(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kS;
    set_s(::fidl::ObjectView<::fidl::StringView>(allocator,
                                                 std::forward<Args>(args)...));
  }

  ::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;
  }

  template <typename... Args>
  static ExplicitFoo WithI(::fidl::AnyAllocator& allocator, Args&&... args) {
    ExplicitFoo result;
    result.set_i(
        ::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_i(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kI;
    set_i(::fidl::ObjectView<int32_t>(allocator, std::forward<Args>(args)...));
  }

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

  template <typename... Args>
  static XUnionContainingEmptyStruct WithEmpty(::fidl::AnyAllocator& allocator,
                                               Args&&... args) {
    XUnionContainingEmptyStruct result;
    result.set_empty(::fidl::ObjectView<::llcpp::fidl::test::union_::Empty>(
        allocator, std::forward<Args>(args)...));
    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)));
  }

  template <typename... Args>
  void set_empty(::fidl::AnyAllocator& allocator, Args&&... args) {
    ordinal_ = Ordinal::kEmpty;
    set_empty(::fidl::ObjectView<::llcpp::fidl::test::union_::Empty>(
        allocator, std::forward<Args>(args)...));
  }

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

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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);
  };

  class EventHandlerInterface {
   public:
    EventHandlerInterface() = default;
    virtual ~EventHandlerInterface() = default;
  };

  // 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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::union_::TestProtocol>
              _client);
      StrictXUnionHenceResponseMayBeStackAllocated(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::union_::TestProtocol>
              _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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::union_::TestProtocol>
              _client);
      FlexibleXUnionHenceResponseMustBeHeapAllocated(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::union_::TestProtocol>
              _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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::union_::TestProtocol>
              _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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::union_::TestProtocol>
              _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 or a
  // const reference to a
  // |fidl::ClientEnd<::llcpp::fidl::test::union_::TestProtocol>|, 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(
        ::fidl::UnownedClientEnd<TestProtocol> _client_end) {
      return ResultOf::StrictXUnionHenceResponseMayBeStackAllocated(
          _client_end);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::StrictXUnionHenceResponseMayBeStackAllocated
    StrictXUnionHenceResponseMayBeStackAllocated(
        ::fidl::UnownedClientEnd<TestProtocol> _client_end,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::StrictXUnionHenceResponseMayBeStackAllocated(
          _client_end, _response_buffer.data, _response_buffer.capacity);
    }

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

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::FlexibleXUnionHenceResponseMustBeHeapAllocated
    FlexibleXUnionHenceResponseMustBeHeapAllocated(
        ::fidl::UnownedClientEnd<TestProtocol> _client_end,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::FlexibleXUnionHenceResponseMustBeHeapAllocated(
          _client_end, _response_buffer.data, _response_buffer.capacity);
    }
  };

  class SyncClient final {
   public:
    SyncClient() = default;

    explicit SyncClient(::fidl::ClientEnd<TestProtocol> client_end)
        : client_end_(std::move(client_end)) {}

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

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

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

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

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::StrictXUnionHenceResponseMayBeStackAllocated
    StrictXUnionHenceResponseMayBeStackAllocated(
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::StrictXUnionHenceResponseMayBeStackAllocated(
          this->client_end(), _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->client_end());
    }

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

   private:
    ::fidl::ClientEnd<TestProtocol> client_end_;
  };

  class AsyncEventHandler;
  class StrictXUnionHenceResponseMayBeStackAllocatedResponseContext;
  class FlexibleXUnionHenceResponseMustBeHeapAllocatedResponseContext;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  // This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
  // and |fidl::ServerEnd<SomeProtocol>|).
  // TODO(fxbug.dev/65212): Rename this to |Interface| after all users have
  // migrated to the typed channels API.
  class TypedChannelInterface
      : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    TypedChannelInterface() = default;
    virtual ~TypedChannelInterface() = default;

    // The marker protocol type within which this |TypedChannelInterface| 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;
  };

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

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

    using TypedChannelInterface::
        FlexibleXUnionHenceResponseMustBeHeapAllocatedCompleter;
  };

  // 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(TypedChannelInterface* 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(TypedChannelInterface* impl,
                                         fidl_incoming_msg_t* msg,
                                         ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of
  // |TypedChannelInterface*|. 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<TypedChannelInterface*>(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_ {

class TestProtocol::AsyncEventHandler
    : public TestProtocol::EventHandlerInterface {
 public:
  AsyncEventHandler() = default;

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

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

  AsyncEventHandler* event_handler() const { return event_handler_.get(); }

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

  explicit ClientImpl(std::shared_ptr<AsyncEventHandler> event_handler)
      : event_handler_(std::move(event_handler)) {}

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

  std::shared_ptr<AsyncEventHandler> event_handler_;
};

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

  explicit EventSender(
      ::fidl::ServerEnd<::llcpp::fidl::test::union_::TestProtocol> server_end)
      : server_end_(std::move(server_end)) {}

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

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

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

 private:
  ::fidl::ServerEnd<TestProtocol> 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
