class {{export_attribute}} {{struct.name}} { public: using DataView = {{struct.name}}DataView; using Data_ = internal::{{struct.name}}_Data; {#--- Enums #} {%- for enum in struct.enums -%} using {{enum.name}} = {{enum|get_name_for_kind(flatten_nested_kind=True)}}; {%- endfor %} {#--- Constants #} {%- for constant in struct.constants %} static {{constant|format_constant_declaration(nested=True)}}; {%- endfor %} template static {{struct.name}}Ptr New(Args&&... args) { return {{struct.name}}Ptr( base::in_place, std::forward(args)...); } template static {{struct.name}}Ptr From(const U& u) { return mojo::TypeConverter<{{struct.name}}Ptr, U>::Convert(u); } template U To() const { return mojo::TypeConverter::Convert(*this); } {% for constructor in struct|struct_constructors %} {% if constructor.params|length == 1 %}explicit {% endif %}{{struct.name}}( {%- for field in constructor.params %} {%- set type = field.kind|cpp_wrapper_param_type_new %} {%- set name = field.name %} {{type}} {{name}} {%- if not loop.last -%},{%- endif %} {%- endfor %}); {% endfor %} ~{{struct.name}}(); // 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 {{struct.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 ::value>::type* = nullptr> bool Equals(const T& other) const; {%- if struct|is_hashable %} size_t Hash(size_t seed) const; {%- endif %} {%- set serialization_result_type = "WTF::Vector" if for_blink else "std::vector" %} template static {{serialization_result_type}} Serialize(UserType* input) { return mojo::internal::SerializeImpl< {{struct.name}}::DataView, {{serialization_result_type}}>(input); } template static mojo::Message SerializeAsMessage(UserType* input) { return mojo::internal::SerializeAsMessageImpl< {{struct.name}}::DataView>(input); } // The returned Message is serialized only if the message is moved // cross-process or cross-language. Otherwise if the message is Deserialized // as the same UserType |input| will just be moved to |output| in // DeserializeFromMessage. template static mojo::Message WrapAsMessage(UserType input) { return mojo::Message(std::make_unique< internal::{{struct.name}}_UnserializedMessageContext< UserType, {{struct.name}}::DataView>>(0, 0, std::move(input))); } template static bool Deserialize(const void* data, size_t data_num_bytes, UserType* output) { return mojo::internal::DeserializeImpl<{{struct.name}}::DataView>( data, data_num_bytes, std::vector(), output, Validate); } template static bool Deserialize(const {{serialization_result_type}}& input, UserType* output) { return {{struct.name}}::Deserialize( input.size() == 0 ? nullptr : &input.front(), input.size(), output); } template static bool DeserializeFromMessage(mojo::Message input, UserType* output) { auto context = input.TakeUnserializedContext< internal::{{struct.name}}_UnserializedMessageContext< UserType, {{struct.name}}::DataView>>(); if (context) { *output = std::move(context->TakeData()); return true; } input.SerializeIfNecessary(); return mojo::internal::DeserializeImpl<{{struct.name}}::DataView>( input.payload(), input.payload_num_bytes(), std::move(*input.mutable_handles()), output, Validate); } {#--- Struct members #} {% for field in struct.fields %} {%- set type = field.kind|cpp_wrapper_type %} {%- set name = field.name %} {{type}} {{name}}; {%- endfor %} private: static bool Validate(const void* data, mojo::internal::ValidationContext* validation_context); {%- if struct|contains_move_only_members %} DISALLOW_COPY_AND_ASSIGN({{struct.name}}); {%- endif %} };