{%  for field in union.fields %}
{{union.name}}Ptr
{{union.name}}::New{{field.name|under_to_camel}}(
    {{field.kind|cpp_wrapper_param_type_new}} value) {
  return {{union.name}}Ptr(
      std::in_place,
      std::in_place_index<static_cast<size_t>(Tag::k{{field.name|under_to_camel}})>,
      std::move(value));
}
{%  endfor -%}

{%  for field in union.fields %}
{{union.name}}::{{union.name}}(
    std::in_place_index_t<static_cast<size_t>(Tag::k{{field.name|under_to_camel}})>,
    {{field.kind|cpp_wrapper_param_type_new}} value)
    : tag_(Tag::k{{field.name|under_to_camel}}),
      data_(std::in_place_index<static_cast<size_t>(Tag::k{{field.name|under_to_camel}})>,
            std::move(value)) {}
{%  endfor -%}

{{union.name}}::~{{union.name}}() {
  DestroyActive();
}
{%  for field in union.fields %}
void {{union.name}}::set_{{field.name}}({{field.kind|cpp_wrapper_param_type_new}} {{field.name}}) {
{%-   if field.kind|is_object_kind or
           field.kind|is_any_handle_or_interface_kind %}
  if (tag_ == Tag::k{{field.name|under_to_camel}}) {
    data_.{{field.name}} = std::move({{field.name}});
  } else {
    DestroyActive();
    tag_ = Tag::k{{field.name|under_to_camel}};
    new (&data_.{{field.name}}) {{field.kind|cpp_wrapper_type}}(
        std::move({{field.name}}));
  }
{%-   else %}
  if (tag_ != Tag::k{{field.name|under_to_camel}}) {
    DestroyActive();
    tag_ = Tag::k{{field.name|under_to_camel}};
  }
  data_.{{field.name}} = {{field.name}};
{%-   endif %}
}
{%  endfor %}
{%  for field in union.fields %}
{{union.name}}::Union_::Union_(
    std::in_place_index_t<static_cast<size_t>(Tag::k{{field.name|under_to_camel}})>,
    {{field.kind|cpp_wrapper_param_type_new}} value)
    : {{field.name}}(std::move(value)) {}
{%  endfor %}
void {{union.name}}::DestroyActive() {
  switch (tag_) {
{%  for field in union.fields %}
    case Tag::k{{field.name|under_to_camel}}:
      std::destroy_at(&data_.{{field.name}});
      break;
{%- endfor %}
  }
}

{%- if union|is_hashable %}
size_t {{union.name}}::Hash(size_t seed) const {
  seed = mojo::internal::HashCombine(seed, static_cast<uint32_t>(tag_));
  switch (tag_) {
{%  for field in union.fields %}
    case Tag::k{{field.name|under_to_camel}}:
{%-   if for_blink %}
      return mojo::internal::WTFHash(seed, data_.{{field.name}});
{%-   else %}
      return mojo::internal::Hash(seed, data_.{{field.name}});
{%-   endif %}
{%- endfor %}
    default:
      NOTREACHED();
  }
}
{%- endif %}

bool {{union.name}}::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  return Data_::Validate(data, validation_context, false);
}
