chromium/third_party/inspector_protocol/templates/TypeBuilder_h.template

// This file is generated by TypeBuilder_h.template.

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h
#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h

{% if config.protocol.export_header %}
#include {{format_include(config.protocol.export_header)}}
{% endif %}
#include {{format_include(config.protocol.package, "Protocol")}}
// For each imported domain we generate a ValueConversions struct instead of a full domain definition
// and include Domain::API version from there.
{% for name in domain.dependencies %}
  {% if protocol.is_imported_dependency(name) %}
#include {{format_domain_include(config.protocol.package, name)}}
  {% endif %}
{% endfor %}
{% if protocol.is_exported_domain(domain.domain) %}
#include {{format_include(config.exported.package, domain.domain)}}
{% endif %}

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
namespace {{domain.domain}} {
  {% for type in domain.types %}
    {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
    {% if type.type == "object" %}
      {% if "properties" in type %}
class {{type.id}};
      {% else %}
using {{type.id}} = Object;
      {% endif %}
    {% elif type.type != "array" %}
using {{type.id}} = {{protocol.resolve_type(type).type}};
    {% endif %}
  {% endfor %}

// ------------- Forward and enum declarations.
  {% for type in domain.types %}
    {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
    {% if "enum" in type %}

namespace {{type.id}}Enum {
      {% for literal in type.enum %}
{{config.protocol.export_macro}} extern const char {{ literal | dash_to_camelcase}}[];
      {% endfor %}
} // namespace {{type.id}}Enum
    {% endif %}
  {% endfor %}
  {% for command in join_arrays(domain, ["commands", "events"]) %}
    {% for param in join_arrays(command, ["parameters", "returns"]) %}
      {% if "enum" in param %}

namespace {{command.name | to_title_case}} {
namespace {{param.name | to_title_case}}Enum {
        {% for literal in param.enum %}
{{config.protocol.export_macro}} extern const char* {{literal | dash_to_camelcase}};
        {% endfor %}
} // {{param.name | to_title_case}}Enum
} // {{command.name | to_title_case }}
      {% endif %}
    {% endfor %}
  {% endfor %}

// ------------- Type and builder declarations.
  {% for type in domain.types %}
    {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
    {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}

class {{config.protocol.export_macro}} {{type.id}} : public ::{{config.crdtp.namespace}}::ProtocolObject<{{type.id}}>{% if protocol.is_exported(domain.domain, type.id) %},
    public API::{{type.id}}{% endif %} {
public:
    ~{{type.id}}() override { }
    {% for property in type.properties %}
      {% set property_type = protocol.resolve_type(property) %}
      {% set property_name = property.name | to_title_case %}
      {% set property_field = "m_" + property.name %}
      {% if "enum" in property %}

    struct {{config.protocol.export_macro}} {{property_name}}Enum {
        {% for literal in property.enum %}
        static const char* {{literal | dash_to_camelcase}};
        {% endfor %}
    }; // {{property_name}}Enum
      {% endif %}

      {% if property.optional %}
    bool {{"has" | to_method_case}}{{property_name}}() { return {{property_field}}.has_value(); }
    {% if property_type.is_primitive %}
    {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}({{property_type.raw_pass_type}} defaultValue) const {
       return {{property_field}}.value_or(defaultValue);
    }
    {% else %}
    {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}({{property_type.raw_pass_type}} defaultValue) {
       return {{property_field}}.has_value() ? &{{property_field}}.value() : defaultValue;
    }
    {% endif %}
      {% else %}
    {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}() { return {{property_type.to_raw_type % property_field}}; }
      {% endif %}
    void {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value) { {{property_field}} = {{property_type.to_rvalue % "value"}}; }
    {% endfor %}

    template<int STATE>
    class {{type.id}}Builder {
    public:
        enum {
            NoFieldsSet = 0,
    {% for property in type.properties|rejectattr("optional") %}
            {{property.name | to_title_case}}Set = 1 << {{loop.index}},
    {% endfor %}
            AllFieldsSet = (
    {%- for property in type.properties %}
      {% if not(property.optional) %}{{property.name | to_title_case}}Set | {%endif %}
    {% endfor %}0)};

    {% for property in type.properties %}
      {% set property_type = protocol.resolve_type(property) %}
      {% set property_name = property.name | to_title_case %}

      {% if property.optional %}
        {{type.id}}Builder<STATE>& {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value)
        {
            m_result->{{"set" | to_method_case}}{{property_name}}({{property_type.to_rvalue % "value"}});
            return *this;
        }
      {% else %}
        {{type.id}}Builder<STATE | {{property_name}}Set>& {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value)
        {
            static_assert(!(STATE & {{property_name}}Set), "property {{property.name}} should not be set yet");
            m_result->{{"set" | to_method_case}}{{property_name}}({{property_type.to_rvalue % "value"}});
            return castState<{{property_name}}Set>();
        }
      {% endif %}
    {% endfor %}

        std::unique_ptr<{{type.id}}> {{"build" | to_method_case}}()
        {
            static_assert(STATE == AllFieldsSet, "state should be AllFieldsSet");
            return std::move(m_result);
        }

    private:
        friend class {{type.id}};
        {{type.id}}Builder() : m_result(new {{type.id}}()) { }

        template<int STEP> {{type.id}}Builder<STATE | STEP>& castState()
        {
            return *reinterpret_cast<{{type.id}}Builder<STATE | STEP>*>(this);
        }

        {{protocol.type_definition(domain.domain + "." + type.id).type}} m_result;
    };

    static {{type.id}}Builder<0> {{"create" | to_method_case}}()
    {
        return {{type.id}}Builder<0>();
    }

private:
    DECLARE_SERIALIZATION_SUPPORT();

    {{type.id}}()
    {
    {% for property in type.properties %}
      {% if not(property.optional) and "default_value" in protocol.resolve_type(property) %}
          m_{{property.name}} = {{protocol.resolve_type(property).default_value}};
      {%endif %}
    {% endfor %}
    }

    {% for property in type.properties %}
      {% if property.optional %}
    Maybe<{{protocol.resolve_type(property).raw_type}}> m_{{property.name}};
      {% else %}
    {{protocol.resolve_type(property).type}} m_{{property.name}};
      {% endif %}
    {% endfor %}
};

  {% endfor %}

// ------------- Backend interface.

class {{config.protocol.export_macro}} Backend {
public:
    virtual ~Backend() { }

  {% for command in domain.commands %}
    {% if "redirect" in command %}{% continue %}{% endif %}
    {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
    {% if protocol.is_async_command(domain.domain, command.name) %}
    class {{config.protocol.export_macro}} {{command.name | to_title_case}}Callback {
    public:
        virtual void sendSuccess(
      {%- for parameter in command.returns -%}
        {%- if "optional" in parameter -%}
            Maybe<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}}
        {%- else -%}
                {{protocol.resolve_type(parameter).pass_type}} {{parameter.name}}
        {%- endif -%}
        {%- if not loop.last -%}, {% endif -%}
      {%- endfor -%}
        ) = 0;
        virtual void sendFailure(const DispatchResponse&) = 0;
        virtual void fallThrough() = 0;
        virtual ~{{command.name | to_title_case}}Callback() { }
    };
    {% endif %}
    {%- if not protocol.is_async_command(domain.domain, command.name) %}
    virtual DispatchResponse {{command.name | to_method_case}}(
    {%- else %}
    virtual void {{command.name | to_method_case}}(
    {%- endif %}
    {%- for parameter in command.parameters -%}
      {%- if not loop.first -%}, {% endif -%}
      {%- if "optional" in parameter -%}
        Maybe<{{protocol.resolve_type(parameter).raw_type}}> in_{{parameter.name}}
      {%- else -%}
        {{protocol.resolve_type(parameter).pass_type}} in_{{parameter.name}}
      {%- endif -%}
    {%- endfor -%}
    {%- if protocol.is_async_command(domain.domain, command.name) -%}
      {%- if command.parameters -%}, {% endif -%}
        std::unique_ptr<{{command.name | to_title_case}}Callback> callback
    {%- else -%}
      {%- for parameter in command.returns -%}
        {%- if (not loop.first) or command.parameters -%}, {% endif -%}
        {%- if "optional" in parameter -%}
        Maybe<{{protocol.resolve_type(parameter).raw_type}}>* out_{{parameter.name}}
        {%- else -%}
        {{protocol.resolve_type(parameter).type}}* out_{{parameter.name}}
        {%- endif -%}
      {%- endfor -%}
    {%- endif -%}
    ) = 0;
  {% endfor %}

  {% if protocol.generate_disable(domain) %}
    virtual DispatchResponse {{"disable" | to_method_case}}()
    {
        return DispatchResponse::Success();
    }
  {% endif %}
};

// ------------- Frontend interface.

class {{config.protocol.export_macro}} Frontend {
public:
  explicit Frontend(FrontendChannel* frontend_channel) : frontend_channel_(frontend_channel) {}
  {% for event in domain.events %}
    {% if not protocol.generate_event(domain.domain, event.name) %}{% continue %}{% endif %}
    void {{event.name | to_method_case}}(
    {%- for parameter in event.parameters -%}
      {%- if "optional" in parameter -%}
        Maybe<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}} = Maybe<{{protocol.resolve_type(parameter).raw_type}}>()
      {%- else -%}
        {{protocol.resolve_type(parameter).pass_type}} {{parameter.name}}
      {%- endif -%}{%- if not loop.last -%}, {% endif -%}
    {%- endfor -%}
    );
  {% endfor %}

  void flush();
  void sendRawNotification(std::unique_ptr<Serializable>);
 private:
  FrontendChannel* frontend_channel_;
};

// ------------- Dispatcher.

class {{config.protocol.export_macro}} Dispatcher {
public:
    static void wire(UberDispatcher*, Backend*);

private:
    Dispatcher() { }
};

// ------------- Metainfo.

class {{config.protocol.export_macro}} Metainfo {
public:
    using BackendClass = Backend;
    using FrontendClass = Frontend;
    using DispatcherClass = Dispatcher;
    static const char domainName[];
    static const char commandPrefix[];
    static const char version[];
};

} // namespace {{domain.domain}}
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}

#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h)