chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl

{%- set data_view = union|get_qualified_name_for_kind ~ "DataView" %}
{%- set data_type = union|get_qualified_name_for_kind(internal=True) %}

namespace internal {

template <typename MaybeConstUserType>
struct Serializer<{{data_view}}, MaybeConstUserType> {
  using UserType = typename std::remove_const<MaybeConstUserType>::type;
  using Traits = UnionTraits<{{data_view}}, UserType>;

  static void Serialize(MaybeConstUserType& input,
                        MessageFragment<{{data_type}}>& fragment,
                        bool inlined) {
    if (CallIsNullIfExists<Traits>(input)) {
       if (inlined)
        fragment->set_null();
      return;
    }

    if (!inlined)
      fragment.Allocate();

    // TODO(azani): Handle unknown and objects.
    // Set the not-null flag.
    fragment->size = kUnionDataSize;
    fragment->tag = Traits::GetTag(input);
    switch (fragment->tag) {
{%- for field in union.fields %}
{%-   set name = field.name %}
{%-   set kind = field.kind %}
{%-   set serializer_type = kind|unmapped_type_for_serializer %}
      case {{data_view}}::Tag::k{{field.name|under_to_camel}}: {
        decltype(Traits::{{name}}(input))
            in_{{name}} = Traits::{{name}}(input);
{%-   if kind|is_object_kind %}
        mojo::internal::MessageFragment<
            typename decltype(fragment->data.f_{{name}})::BaseType>
            value_fragment(fragment.message());
{%-     if kind|is_union_kind %}
        mojo::internal::Serialize<{{serializer_type}}>(
            in_{{name}}, value_fragment, false);
{%-     elif kind|is_array_kind or kind|is_map_kind %}
        constexpr const mojo::internal::ContainerValidateParams& {{name}}_validate_params =
            {{kind|get_container_validate_params_ctor_args|indent(6)}};
        mojo::internal::Serialize<{{serializer_type}}>(
            in_{{name}}, value_fragment, &{{name}}_validate_params);
 {%-     else %}
        mojo::internal::Serialize<{{serializer_type}}>(
            in_{{name}}, value_fragment);
{%-     endif %}
{%-     if not kind|is_nullable_kind %}
        MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
            value_fragment.is_null(),
            mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
            "null {{name}} in {{union.name}} union");
{%-     endif %}
        fragment->data.f_{{name}}.Set(
            value_fragment.is_null() ? nullptr : value_fragment.data());

{%-   elif kind|is_any_handle_or_interface_kind %}
        mojo::internal::Serialize<{{serializer_type}}>(
            in_{{name}}, &fragment->data.f_{{name}}, &fragment.message());
{%-     if not kind|is_nullable_kind %}
        MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
            !mojo::internal::IsHandleOrInterfaceValid(fragment->data.f_{{name}}),
{%-       if kind|is_associated_kind %}
            mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID,
{%-       else %}
            mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
{%-       endif %}
            "invalid {{name}} in {{union.name}} union");
{%-     endif %}

{%-   elif kind|is_enum_kind %}
        mojo::internal::Serialize<{{serializer_type}}>(
            in_{{name}}, &fragment->data.f_{{name}});

{%-   else %}
        fragment->data.f_{{name}} = in_{{name}};
{%-   endif %}
        break;
      }
{%- endfor %}
    }
  }

  static bool Deserialize({{data_type}}* input,
                          UserType* output,
                          Message* message) {
    if (!input || input->is_null())
      return CallSetToNullIfExists<Traits>(output);

    {{data_view}} data_view(input, message);
    return Traits::Read(data_view, output);
  }
};

}  // namespace internal