1{%- set union_prefix = "%s.%s"|format(module_prefix, union.name) %}
2
3{{ kythe_annotation(union_prefix) }}
4class {{export_attribute}} {{union.name}} {
5 public:
6  using DataView = {{union.name}}DataView;
7  using Data_ = internal::{{union.name}}_Data;
8  using Tag = Data_::{{union.name}}_Tag;
9
10  static {{union.name}}Ptr New() {
11    return {{union.name}}Ptr(base::in_place);
12  }
13
14{%-  for field in union.fields %}
15  // Construct an instance holding |{{field.name}}|.
16  static {{union.name}}Ptr
17  New{{field.name|under_to_camel}}(
18      {{field.kind|cpp_wrapper_param_type_new}} {{field.name}}) {
19    auto result = {{union.name}}Ptr(base::in_place);
20    result->set_{{field.name}}(std::move({{field.name}}));
21    return result;
22  }
23{%- endfor %}
24
25  template <typename U>
26  static {{union.name}}Ptr From(const U& u) {
27    return mojo::TypeConverter<{{union.name}}Ptr, U>::Convert(u);
28  }
29
30  template <typename U>
31  U To() const {
32    return mojo::TypeConverter<U, {{union.name}}>::Convert(*this);
33  }
34
35  {{union.name}}();
36  ~{{union.name}}();
37
38  // Clone() is a template so it is only instantiated if it is used. Thus, the
39  // bindings generator does not need to know whether Clone() or copy
40  // constructor/assignment are available for members.
41  template <typename UnionPtrType = {{union.name}}Ptr>
42  {{union.name}}Ptr Clone() const;
43
44  // Equals() is a template so it is only instantiated if it is used. Thus, the
45  // bindings generator does not need to know whether Equals() or == operator
46  // are available for members.
47  template <typename T,
48            typename std::enable_if<std::is_same<
49                T, {{union.name}}>::value>::type* = nullptr>
50  bool Equals(const T& other) const;
51
52{%- if union|is_hashable %}
53  size_t Hash(size_t seed) const;
54{%- endif %}
55
56  Tag which() const {
57    return tag_;
58  }
59
60{%  for field in union.fields %}
61  {{ kythe_annotation("%s.%s"|format(union_prefix, field.name)) }}
62  bool is_{{field.name}}() const { return tag_ == Tag::{{field.name|upper}}; }
63
64  {{ kythe_annotation("%s.%s"|format(union_prefix, field.name)) }}
65  {{field.kind|cpp_union_getter_return_type}} get_{{field.name}}() const {
66    DCHECK(tag_ == Tag::{{field.name|upper}});
67{%-   if field.kind|is_object_kind or
68         field.kind|is_any_handle_or_interface_kind %}
69    return *(data_.{{field.name}});
70{%-   else %}
71    return data_.{{field.name}};
72{%-   endif %}
73  }
74
75  {{ kythe_annotation("%s.%s"|format(union_prefix, field.name)) }}
76  void set_{{field.name}}(
77      {{field.kind|cpp_wrapper_param_type_new}} {{field.name}});
78{%- endfor %}
79
80  template <typename UserType>
81  static mojo::Message SerializeAsMessage(UserType* input) {
82    return mojo::internal::SerializeAsMessageImpl<
83        {{union.name}}::DataView>(input);
84  }
85
86  template <typename UserType>
87  static bool DeserializeFromMessage(mojo::Message input,
88                                     UserType* output) {
89    return mojo::internal::DeserializeImpl<{{union.name}}::DataView>(
90        input.payload(), input.payload_num_bytes(),
91        std::move(*input.mutable_handles()), output, Validate);
92  }
93
94 private:
95  union Union_ {
96    Union_() {}
97    ~Union_() {}
98
99{%- for field in union.fields %}
100{%-   if field.kind|is_object_kind or
101         field.kind|is_any_handle_or_interface_kind %}
102    {{field.kind|cpp_wrapper_type}}* {{field.name}};
103{%-   else %}
104    {{field.kind|cpp_wrapper_type}} {{field.name}};
105{%-   endif %}
106{%- endfor %}
107  };
108
109  static bool Validate(const void* data,
110                       mojo::internal::ValidationContext* validation_context);
111
112  void DestroyActive();
113  Tag tag_;
114  Union_ data_;
115};
116