{%- set class_name = union.name ~ "_Data" -%} {%- set enum_name = union.name ~ "_Tag" -%} {%- import "struct_macros.tmpl" as struct_macros %} class {{class_name}} { public: // Used to identify Mojom Union Data Classes. typedef void MojomUnionDataType; static {{class_name}}* New(mojo::internal::Buffer* buf); {{class_name}}(); // Do nothing in the destructor since it won't be called. ~{{class_name}}() {} static bool Validate(const void* data, mojo::internal::BoundsChecker* bounds_checker, bool inlined); bool is_null() const { return size == 0; } void set_null(); enum class {{enum_name}} : uint32_t { {% for field in union.fields %} {{field.name|upper}}, {%- endfor %} }; // A note on layout: // "Each non-static data member is allocated as if it were the sole member of // a struct." - Section 9.5.2 ISO/IEC 14882:2011 (The C++ Spec) union MOJO_ALIGNAS(8) Union_ { {%- for field in union.fields %} {%- if field.kind.spec == 'b' %} uint8_t f_{{field.name}} : 1; {%- else %} {{field.kind|cpp_union_field_type}} f_{{field.name}}; {%- endif %} {%- endfor %} uint64_t unknown; }; uint32_t size; {{enum_name}} tag; Union_ data; void EncodePointersAndHandles(std::vector* handles); void DecodePointersAndHandles(std::vector* handles); }; static_assert(sizeof({{class_name}}) == 16, "Bad sizeof({{class_name}})"); static_assert(sizeof({{class_name}}::Union_) == 8, "Bad sizeof({{class_name}}::Union_)");