| // This file is generated |
| |
| // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| // 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 %} |
| #include {{format_include(config.protocol.package, name)}} |
| {% 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}} { |
| |
| // ------------- Forward and enum declarations. |
| {% for type in domain.types %} |
| {% if type.type == "object" %} |
| {% if "properties" in type %} |
| // {{type.description}} |
| class {{type.id}}; |
| {% else %} |
| // {{type.description}} |
| using {{type.id}} = Object; |
| {% endif %} |
| {% elif type.type != "array" %} |
| // {{type.description}} |
| using {{type.id}} = {{protocol.resolve_type(type).type}}; |
| {% endif %} |
| {% endfor %} |
| {% for type in domain.types %} |
| {% 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 (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %} |
| |
| // {{type.description}} |
| class {{config.protocol.export_macro}} {{type.id}} : public Serializable{% if protocol.is_exported(domain.domain, type.id) %}, public API::{{type.id}}{% endif %}{ |
| PROTOCOL_DISALLOW_COPY({{type.id}}); |
| public: |
| static std::unique_ptr<{{type.id}}> fromValue(protocol::Value* value, ErrorSupport* errors); |
| |
| ~{{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}}.isJust(); } |
| {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}({{property_type.raw_pass_type}} defaultValue) { return {{property_field}}.isJust() ? {{property_field}}.fromJust() : defaultValue; } |
| {% 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 %} |
| |
| std::unique_ptr<protocol::DictionaryValue> toValue() const; |
| String serialize() override { return toValue()->serialize(); } |
| std::unique_ptr<{{type.id}}> clone() const; |
| {% if protocol.is_exported(domain.domain, type.id) %} |
| {{config.exported.string_out}} toJSONString() const override; |
| {% endif %} |
| |
| template<int STATE> |
| class {{type.id}}Builder { |
| public: |
| enum { |
| NoFieldsSet = 0, |
| {% set count = 0 %} |
| {% for property in type.properties %} |
| {% if not(property.optional) %} |
| {# "count = count + 1" does not work with our version of jinja, use the loop index instead. #} |
| {% set count = loop.index + 1 %} |
| {{property.name | to_title_case}}Set = 1 << {{count}}, |
| {% endif %} |
| {% 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: |
| {{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::OK(); |
| } |
| {% endif %} |
| }; |
| |
| // ------------- Frontend interface. |
| |
| class {{config.protocol.export_macro}} Frontend { |
| public: |
| explicit Frontend(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { } |
| {% 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(const String&); |
| private: |
| FrontendChannel* m_frontendChannel; |
| }; |
| |
| // ------------- 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) |