123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- // This file is generated by TypeBuilder_cpp.template.
- // 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.
- #include {{format_domain_include(config.protocol.package, domain.domain)}}
- #include {{format_include(config.protocol.package, "Protocol")}}
- #include "{{config.crdtp.dir}}/cbor.h"
- #include "{{config.crdtp.dir}}/find_by_first.h"
- #include "{{config.crdtp.dir}}/span.h"
- {% for namespace in config.protocol.namespace %}
- namespace {{namespace}} {
- {% endfor %}
- namespace {{domain.domain}} {
- using {{config.crdtp.namespace}}::DeserializerState;
- using {{config.crdtp.namespace}}::ProtocolTypeTraits;
- // ------------- Enum values from types.
- const char Metainfo::domainName[] = "{{domain.domain}}";
- const char Metainfo::commandPrefix[] = "{{domain.domain}}.";
- const char Metainfo::version[] = "{{domain.version}}";
- {% 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 %}
- const char {{ literal | dash_to_camelcase}}[] = "{{literal}}";
- {% endfor %}
- } // namespace {{type.id}}Enum
- {% if protocol.is_exported(domain.domain, type.id) %}
- namespace API {
- namespace {{type.id}}Enum {
- {% for literal in type.enum %}
- const char* {{ literal | dash_to_camelcase}} = "{{literal}}";
- {% endfor %}
- } // namespace {{type.id}}Enum
- } // namespace API
- {% endif %}
- {% endif %}
- {% for property in type.properties %}
- {% if "enum" in property %}
- {% for literal in property.enum %}
- const char* {{type.id}}::{{property.name | to_title_case}}Enum::{{literal | dash_to_camelcase}} = "{{literal}}";
- {% endfor %}
- {% endif %}
- {% endfor %}
- {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
- CRDTP_BEGIN_DESERIALIZER({{type.id}})
- {% for property in type.properties | sort(attribute = 'name', case_sensitive=True) %}
- {% if property.optional %}
- CRDTP_DESERIALIZE_FIELD_OPT("{{property.name}}", m_{{property.name}}),
- {% else %}
- CRDTP_DESERIALIZE_FIELD("{{property.name}}", m_{{property.name}}),
- {% endif %}
- {% endfor %}
- CRDTP_END_DESERIALIZER()
- CRDTP_BEGIN_SERIALIZER({{type.id}})
- {% for property in type.properties %}
- CRDTP_SERIALIZE_FIELD("{{property.name}}", m_{{property.name}});
- {% endfor %}
- CRDTP_END_SERIALIZER();
- {% if protocol.is_exported(domain.domain, type.id) %}
- // static
- std::unique_ptr<API::{{type.id}}> API::{{type.id}}::fromBinary(const uint8_t* data, size_t length)
- {
- return protocol::{{domain.domain}}::{{type.id}}::FromBinary(data, length);
- }
- {% endif %}
- {% endfor %}
- // ------------- Enum values from params.
- {% 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 %}
- const char* {{ literal | to_title_case}} = "{{literal}}";
- {% endfor %}
- } // namespace {{param.name | to_title_case}}Enum
- } // namespace {{command.name | to_title_case }}
- {% if protocol.is_exported(domain.domain, command.name + "." + param.name) %}
- namespace API {
- namespace {{command.name | to_title_case}} {
- namespace {{param.name | to_title_case}}Enum {
- {% for literal in param.enum %}
- const char* {{ literal | to_title_case}} = "{{literal}}";
- {% endfor %}
- } // namespace {{param.name | to_title_case}}Enum
- } // namespace {{command.name | to_title_case }}
- } // namespace API
- {% endif %}
- {% endif %}
- {% endfor %}
- {% endfor %}
- // ------------- Frontend notifications.
- {% for event in domain.events %}
- {% if not protocol.generate_event(domain.domain, event.name) %}{% continue %}{% endif %}
- void Frontend::{{event.name | to_method_case}}(
- {%- for parameter in event.parameters %}
- {% if "optional" in parameter -%}
- Maybe<{{protocol.resolve_type(parameter).raw_type}}>
- {%- else -%}
- {{protocol.resolve_type(parameter).pass_type}}
- {%- endif %} {{parameter.name}}{%- if not loop.last -%}, {% endif -%}
- {% endfor -%})
- {
- if (!frontend_channel_)
- return;
- {% if event.parameters %}
- {{config.crdtp.namespace}}::ObjectSerializer serializer;
- {% for parameter in event.parameters %}
- serializer.AddField({{config.crdtp.namespace}}::MakeSpan("{{parameter.name}}"), {{parameter.name}});
- {% endfor %}
- frontend_channel_->SendProtocolNotification({{config.crdtp.namespace}}::CreateNotification("{{domain.domain}}.{{event.name}}", serializer.Finish()));
- {% else %}
- frontend_channel_->SendProtocolNotification({{config.crdtp.namespace}}::CreateNotification("{{domain.domain}}.{{event.name}}"));
- {% endif %}
- }
- {% endfor %}
- void Frontend::flush()
- {
- frontend_channel_->FlushProtocolNotifications();
- }
- void Frontend::sendRawNotification(std::unique_ptr<Serializable> notification)
- {
- frontend_channel_->SendProtocolNotification(std::move(notification));
- }
- // --------------------- Dispatcher.
- class DomainDispatcherImpl : public protocol::DomainDispatcher {
- public:
- DomainDispatcherImpl(FrontendChannel* frontendChannel, Backend* backend)
- : DomainDispatcher(frontendChannel)
- , m_backend(backend) {}
- ~DomainDispatcherImpl() override { }
- using CallHandler = void (DomainDispatcherImpl::*)(const {{config.crdtp.namespace}}::Dispatchable& dispatchable);
- std::function<void(const {{config.crdtp.namespace}}::Dispatchable&)> Dispatch({{config.crdtp.namespace}}::span<uint8_t> command_name) override;
- {% for command in domain.commands %}
- {% if "redirect" in command %}{% continue %}{% endif %}
- {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
- void {{command.name}}(const {{config.crdtp.namespace}}::Dispatchable& dispatchable);
- {% endfor %}
- protected:
- Backend* m_backend;
- };
- namespace {
- // This helper method with a static map of command methods (instance methods
- // of DomainDispatcherImpl declared just above) by their name is used immediately below,
- // in the DomainDispatcherImpl::Dispatch method.
- DomainDispatcherImpl::CallHandler CommandByName({{config.crdtp.namespace}}::span<uint8_t> command_name) {
- static auto* commands = [](){
- auto* commands = new std::vector<std::pair<{{config.crdtp.namespace}}::span<uint8_t>,
- DomainDispatcherImpl::CallHandler>>{
- {% for command in domain.commands|sort(attribute="name",case_sensitive=True) %}
- {% if "redirect" in command %}{% continue %}{% endif %}
- {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
- {
- {{config.crdtp.namespace}}::SpanFrom("{{command.name}}"),
- &DomainDispatcherImpl::{{command.name}}
- },
- {% endfor %}
- };
- return commands;
- }();
- return {{config.crdtp.namespace}}::FindByFirst<DomainDispatcherImpl::CallHandler>(*commands, command_name, nullptr);
- }
- } // namespace
- std::function<void(const {{config.crdtp.namespace}}::Dispatchable&)> DomainDispatcherImpl::Dispatch({{config.crdtp.namespace}}::span<uint8_t> command_name) {
- CallHandler handler = CommandByName(command_name);
- if (!handler) return nullptr;
- return [this, handler](const {{config.crdtp.namespace}}::Dispatchable& dispatchable) {
- (this->*handler)(dispatchable);
- };
- }
- {% for command in domain.commands %}
- {% set command_name_title = command.name | to_title_case %}
- {% 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 {{command_name_title}}CallbackImpl : public Backend::{{command_name_title}}Callback, public DomainDispatcher::Callback {
- public:
- {{command_name_title}}CallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, int callId, {{config.crdtp.namespace}}::span<uint8_t> message)
- : DomainDispatcher::Callback(std::move(backendImpl), callId,
- {{config.crdtp.namespace}}::SpanFrom("{{domain.domain}}.{{command.name}}"), message) { }
- 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 -%}) override
- {
- {{config.crdtp.namespace}}::ObjectSerializer serializer;
- {% for parameter in command.returns %}
- serializer.AddField({{config.crdtp.namespace}}::MakeSpan("{{parameter.name}}"), {{parameter.name}});
- {% endfor %}
- sendIfActive(serializer.Finish(), DispatchResponse::Success());
- }
- void fallThrough() override
- {
- fallThroughIfActive();
- }
- void sendFailure(const DispatchResponse& response) override
- {
- DCHECK(response.IsError());
- sendIfActive(nullptr, response);
- }
- };
- {% endif %}
- namespace {
- {% if "parameters" in command %}
- struct {{command.name}}Params : public {{config.crdtp.namespace}}::DeserializableProtocolObject<{{command.name}}Params> {
- {% for parameter in command.parameters %}
- {% set parameter_type = protocol.resolve_type(parameter) %}
- {% if parameter.optional %}
- Maybe<{{parameter_type.raw_type}}> {{parameter.name}};
- {% else %}
- {{parameter_type.type}} {{parameter.name}};
- {% endif %}
- {% endfor %}
- DECLARE_DESERIALIZATION_SUPPORT();
- };
- CRDTP_BEGIN_DESERIALIZER({{command.name}}Params)
- {% for parameter in command.parameters | sort(attribute = 'name', case_sensitive=True) %}
- {% if parameter.optional %}
- CRDTP_DESERIALIZE_FIELD_OPT("{{parameter.name}}", {{parameter.name}}),
- {% else %}
- CRDTP_DESERIALIZE_FIELD("{{parameter.name}}", {{parameter.name}}),
- {% endif %}
- {% endfor %}
- CRDTP_END_DESERIALIZER()
- {% endif %}
- } // namespace
- void DomainDispatcherImpl::{{command.name}}(const {{config.crdtp.namespace}}::Dispatchable& dispatchable)
- {
- // Prepare input parameters.
- {% if "parameters" in command %}
- auto deserializer = {{config.crdtp.namespace}}::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
- {{command.name}}Params params;
- if (!{{command.name}}Params::Deserialize(&deserializer, ¶ms)) {
- ReportInvalidParams(dispatchable, deserializer);
- return;
- }
- {% endif -%}
- {% if "returns" in command and not protocol.is_async_command(domain.domain, command.name) %}
- // Declare output parameters.
- {% for parameter in command.returns %}
- {% 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 %}
- {% if not protocol.is_async_command(domain.domain, command.name) %}
- std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
- DispatchResponse response = m_backend->{{command.name | to_method_case}}(
- {%- for parameter in command.parameters -%}
- {%- if not loop.first -%}, {% endif -%}
- {%- if "optional" in parameter -%}
- std::move(params.{{parameter.name}})
- {%- else -%}
- {{protocol.resolve_type(parameter).to_pass_type % ("params." + parameter.name)}}
- {%- endif -%}
- {%- endfor %}
- {%- if "returns" in command %}
- {%- for parameter in command.returns -%}
- {%- if not loop.first or command.parameters -%}, {% endif -%}
- &out_{{parameter.name}}
- {%- endfor %}
- {% endif %});
- if (response.IsFallThrough()) {
- channel()->FallThrough(dispatchable.CallId(), {{config.crdtp.namespace}}::SpanFrom("{{domain.domain}}.{{command.name}}"), dispatchable.Serialized());
- return;
- }
- {% if "returns" in command %}
- if (weak->get()) {
- std::unique_ptr<{{config.crdtp.namespace}}::Serializable> result;
- if (response.IsSuccess()) {
- {{config.crdtp.namespace}}::ObjectSerializer serializer;
- {% for parameter in command.returns %}
- serializer.AddField({{config.crdtp.namespace}}::MakeSpan("{{parameter.name}}"), out_{{parameter.name}});
- {% endfor %}
- result = serializer.Finish();
- } else {
- result = Serializable::From({});
- }
- weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
- }
- {% else %}
- if (weak->get())
- weak->get()->sendResponse(dispatchable.CallId(), response);
- {% endif %}
- return;
- {% else %}
- m_backend->{{command.name | to_method_case}}(
- {%- for property in command.parameters -%}
- {%- if not loop.first -%}, {% endif -%}
- {%- if "optional" in property -%}
- std::move(params.{{property.name}})
- {%- else -%}
- {{protocol.resolve_type(property).to_pass_type % ("params." + property.name)}}
- {%- endif -%}
- {%- endfor -%}
- {%- if command.parameters -%}, {% endif -%}
- std::make_unique<{{command_name_title}}CallbackImpl>(weakPtr(), dispatchable.CallId(), dispatchable.Serialized()));
- {% endif %}
- }
- {% endfor %}
- namespace {
- // This helper method (with a static map of redirects) is used from Dispatcher::wire
- // immediately below.
- const std::vector<std::pair<{{config.crdtp.namespace}}::span<uint8_t>, {{config.crdtp.namespace}}::span<uint8_t>>>& SortedRedirects() {
- static auto* redirects = [](){
- auto* redirects = new std::vector<std::pair<{{config.crdtp.namespace}}::span<uint8_t>, {{config.crdtp.namespace}}::span<uint8_t>>>{
- {% for command in domain.commands|sort(attribute="name",case_sensitive=True) %}
- {% if "redirect" in command %}
- { {{config.crdtp.namespace}}::SpanFrom("{{domain.domain}}.{{command.name}}"), {{config.crdtp.namespace}}::SpanFrom("{{command.redirect}}.{{command.name}}") },
- {% endif %}
- {% endfor %}
- };
- return redirects;
- }();
- return *redirects;
- }
- } // namespace
- // static
- void Dispatcher::wire(UberDispatcher* uber, Backend* backend)
- {
- auto dispatcher = std::make_unique<DomainDispatcherImpl>(uber->channel(), backend);
- uber->WireBackend({{config.crdtp.namespace}}::SpanFrom("{{domain.domain}}"), SortedRedirects(), std::move(dispatcher));
- }
- } // {{domain.domain}}
- {% for namespace in config.protocol.namespace %}
- } // namespace {{namespace}}
- {% endfor %}
|