{%- set union_prefix = "%s.%s"|format(module_prefix, union.name) %}
{{ kythe_annotation(union_prefix) }}
class {{export_attribute}} {{union.name}} {
public:
using DataView = {{union.name}}DataView;
using Data_ = internal::{{union.name}}_Data;
using Tag = Data_::{{union.name}}_Tag;
template <typename... Args>
static {{union.name}}Ptr New(Args&&... args) {
static_assert(
sizeof...(args) < 0,
"Do not use Union::New(); to create a union of a given subtype, use "
"New<SubType>(), not New() followed by set_<sub_type>(). To represent "
"an empty union, mark the field or parameter as nullable in the mojom "
"definition.");
return nullptr;
}
{%- for field in union.fields %}
// Construct an instance holding |{{field.name}}|.
static {{union.name}}Ptr
New{{field.name|under_to_camel}}(
{{field.kind|cpp_wrapper_param_type_new}} value) {
auto result = {{union.name}}Ptr(std::in_place);
result->set_{{field.name}}(std::move(value));
return result;
}
{%- endfor %}
template <typename U>
static {{union.name}}Ptr From(const U& u) {
return mojo::TypeConverter<{{union.name}}Ptr, U>::Convert(u);
}
template <typename U>
U To() const {
return mojo::TypeConverter<U, {{union.name}}>::Convert(*this);
}
{{union.name}}();
~{{union.name}}();
{%- if not union|should_inline_union %}
// Delete the copy constructor and copy assignment operators because `data_`
// contains raw pointers that must not be copied.
{{union.name}}(const {{union.name}}& other) = delete;
{{union.name}}& operator=(const {{union.name}}& other) = delete;
{%- endif %}
// Clone() is a template so it is only instantiated if it is used. Thus, the
// bindings generator does not need to know whether Clone() or copy
// constructor/assignment are available for members.
template <typename UnionPtrType = {{union.name}}Ptr>
{{union.name}}Ptr Clone() const;
// Equals() is a template so it is only instantiated if it is used. Thus, the
// bindings generator does not need to know whether Equals() or == operator
// are available for members.
template <typename T,
typename std::enable_if<std::is_same<
T, {{union.name}}>::value>::type* = nullptr>
bool Equals(const T& other) const;
template <typename T,
typename std::enable_if<std::is_same<
T, {{union.name}}>::value>::type* = nullptr>
bool operator==(const T& rhs) const { return Equals(rhs); }
{%- if union|is_hashable %}
size_t Hash(size_t seed) const;
{%- endif %}
Tag which() const {
return tag_;
}
{% for field in union.fields %}
{{ kythe_annotation("%s.%s"|format(union_prefix, field.name)) }}
bool is_{{field.name}}() const { return tag_ == Tag::k{{field.name|under_to_camel}}; }
{{ kythe_annotation("%s.%s"|format(union_prefix, field.name)) }}
{{field.kind|cpp_union_getter_return_type}} get_{{field.name}}() const {
CHECK(tag_ == Tag::k{{field.name|under_to_camel}});
{%- if field.kind|is_object_kind or
field.kind|is_any_handle_or_interface_kind %}
return *(data_.{{field.name}});
{%- else %}
return data_.{{field.name}};
{%- endif %}
}
{{ kythe_annotation("%s.%s"|format(union_prefix, field.name)) }}
void set_{{field.name}}(
{{field.kind|cpp_wrapper_param_type_new}} {{field.name}});
{%- endfor %}
template <typename UserType>
static mojo::Message SerializeAsMessage(UserType* input) {
return mojo::internal::SerializeAsMessageImpl<
{{union.name}}::DataView>(input);
}
template <typename UserType>
static bool DeserializeFromMessage(mojo::Message input,
UserType* output) {
return mojo::internal::DeserializeImpl<{{union.name}}::DataView>(
input, input.payload(), input.payload_num_bytes(), output, Validate);
}
private:
union Union_ {
Union_() = default;
~Union_() = default;
{%- for field in union.fields %}
{%- if field.kind|is_object_kind or
field.kind|is_any_handle_or_interface_kind %}
{{field.kind|cpp_wrapper_type}}* {{field.name}};
{%- else %}
{{field.kind|cpp_wrapper_type}} {{field.name}};
{%- endif %}
{%- endfor %}
};
static bool Validate(const void* data,
mojo::internal::ValidationContext* validation_context);
void DestroyActive();
Tag tag_;
Union_ data_;
};