Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,74 @@
// This file is generated by Exported_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}}_api_h
#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_api_h
{% if config.exported.export_header %}
#include {{format_include(config.exported.export_header)}}
{% endif %}
#include {{format_include(config.exported.string_header)}}
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
#ifndef {{"_".join(config.protocol.namespace)}}_exported_api_h
#define {{"_".join(config.protocol.namespace)}}_exported_api_h
class {{config.exported.export_macro}} Exported {
public:
virtual void AppendSerialized(std::vector<uint8_t>* out) const = 0;
virtual ~Exported() { }
};
#endif // !defined({{"_".join(config.protocol.namespace)}}_exported_api_h)
namespace {{domain.domain}} {
namespace API {
// ------------- Enums.
{% for type in domain.types %}
{% if ("enum" in type) and protocol.is_exported(domain.domain, type.id) %}
namespace {{type.id}}Enum {
{% for literal in type.enum %}
{{config.exported.export_macro}} extern const char* {{ literal | dash_to_camelcase}};
{% endfor %}
} // {{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) and protocol.is_exported(domain.domain, command.name + "." + param.name) %}
namespace {{command.name | to_title_case}} {
namespace {{param.name | to_title_case}}Enum {
{% for literal in param.enum %}
{{config.exported.export_macro}} extern const char* {{ literal | dash_to_camelcase}};
{% endfor %}
} // {{param.name | to_title_case}}Enum
} // {{command.name | to_title_case }}
{% endif %}
{% endfor %}
{% endfor %}
// ------------- Types.
{% for type in domain.types %}
{% if not (type.type == "object") or not ("properties" in type) or not protocol.is_exported(domain.domain, type.id) %}{% continue %}{% endif %}
class {{config.exported.export_macro}} {{type.id}} : public Exported {
public:
static std::unique_ptr<protocol::{{domain.domain}}::API::{{type.id}}> fromBinary(const uint8_t* data, size_t length);
};
{% endfor %}
} // namespace API
} // namespace {{domain.domain}}
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_api_h)

View File

@ -0,0 +1,126 @@
// This file is generated by Imported_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}}_imported_h
#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h
#include {{format_include(config.protocol.package, "Protocol")}}
{% if config.imported.header %}
#include {{format_include(config.imported.header)}}
{% else %}
#include {{format_include(config.imported.package, domain.domain)}}
{% endif %}
#ifndef {{"_".join(config.protocol.namespace)}}_imported_imported_h
namespace {{config.crdtp.namespace}} {
template <typename T>
struct ProtocolTypeTraits<
std::unique_ptr<T>,
typename std::enable_if<
std::is_base_of<{{"::".join(config.imported.namespace)}}::Exported, T>::value>::type> {
static bool Deserialize(DeserializerState* state, std::unique_ptr<T>* value) {
if (state->tokenizer()->TokenTag() != cbor::CBORTokenTag::ENVELOPE) {
state->RegisterError(Error::CBOR_INVALID_ENVELOPE);
return false;
}
span<uint8_t> env = state->tokenizer()->GetEnvelope();
auto res = T::fromBinary(env.data(), env.size());
if (!res) {
// TODO(caseq): properly plumb an error rather than returning a bogus code.
state->RegisterError(Error::MESSAGE_MUST_BE_AN_OBJECT);
return false;
}
*value = std::move(res);
return true;
}
static void Serialize(const std::unique_ptr<T>& value, std::vector<uint8_t>* bytes) {
// Use virtual method, so that outgoing protocol objects could be retained
// by a pointer to ProtocolObject.
value->AppendSerialized(bytes);
}
};
template <typename T>
struct ProtocolTypeTraits<
T,
typename std::enable_if<
std::is_base_of<{{"::".join(config.imported.namespace)}}::Exported, T>::value>::type> {
static void Serialize(const T& value, std::vector<uint8_t>* bytes) {
// Use virtual method, so that outgoing protocol objects could be retained
// by a pointer to ProtocolObject.
value.AppendSerialized(bytes);
}
};
} // namespace {{config.crdtp.namespace}}
#endif // {{"_".join(config.protocol.namespace)}}_imported_imported_h
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
using Exported = {{"::".join(config.imported.namespace)}}::Exported;
#ifndef {{"_".join(config.protocol.namespace)}}_imported_imported_h
#define {{"_".join(config.protocol.namespace)}}_imported_imported_h
class {{config.lib.export_macro}} ImportedValue : public Value {
public:
static std::unique_ptr<ImportedValue> fromExported(const Exported* value) {
return std::unique_ptr<ImportedValue>(new ImportedValue(value));
}
void AppendSerialized(std::vector<uint8_t>* output) const override {
m_exported->AppendSerialized(output);
}
std::unique_ptr<Value> clone() const override {
return std::unique_ptr<Value>(new ImportedValue(m_exported));
}
private:
explicit ImportedValue(const Exported* exported) : Value(TypeImported), m_exported(exported) { }
const Exported* m_exported;
};
#endif // !defined({{"_".join(config.protocol.namespace)}}_imported_imported_h)
{% for type in domain.types %}
{% if not (type.type == "object") or not ("properties" in type) or not protocol.is_imported(domain.domain, type.id) %}{% continue %}{% endif %}
template<>
struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> {
static std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> fromValue(protocol::Value* value, ErrorSupport* errors)
{
if (!value) {
errors->AddError("value expected");
return nullptr;
}
std::vector<uint8_t> binary;
value->AppendSerialized(&binary);
auto result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromBinary(binary.data(), binary.size());
if (!result)
errors->AddError("cannot parse");
return result;
}
static std::unique_ptr<protocol::Value> toValue(const {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}* exported)
{
return ImportedValue::fromExported(exported);
}
};
{% endfor %}
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h)

View File

@ -0,0 +1,380 @@
// This file is generated by TypeBuilder_cpp.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.
#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 %}
V8_CRDTP_BEGIN_DESERIALIZER({{type.id}})
{% for property in type.properties | sort(attribute = 'name', case_sensitive=True) %}
{% if property.optional %}
V8_CRDTP_DESERIALIZE_FIELD_OPT("{{property.name}}", m_{{property.name}}),
{% else %}
V8_CRDTP_DESERIALIZE_FIELD("{{property.name}}", m_{{property.name}}),
{% endif %}
{% endfor %}
V8_CRDTP_END_DESERIALIZER()
V8_CRDTP_BEGIN_SERIALIZER({{type.id}})
{% for property in type.properties %}
V8_CRDTP_SERIALIZE_FIELD("{{property.name}}", m_{{property.name}});
{% endfor %}
V8_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 -%}
{{protocol.optional_type(parameter)}}
{%- 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 -%}
{{protocol.optional_type(parameter)}} {{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 %}
{{protocol.optional_type(parameter)}} {{parameter.name}};
{% else %}
{{parameter_type.type}} {{parameter.name}};
{% endif %}
{% endfor %}
DECLARE_DESERIALIZATION_SUPPORT();
};
V8_CRDTP_BEGIN_DESERIALIZER({{command.name}}Params)
{% for parameter in command.parameters | sort(attribute = 'name', case_sensitive=True) %}
{% if parameter.optional %}
V8_CRDTP_DESERIALIZE_FIELD_OPT("{{parameter.name}}", {{parameter.name}}),
{% else %}
V8_CRDTP_DESERIALIZE_FIELD("{{parameter.name}}", {{parameter.name}}),
{% endif %}
{% endfor %}
V8_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, &params)) {
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 %}
{{protocol.optional_type(parameter)}} 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 %}

View File

@ -0,0 +1,305 @@
// 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}}; }
{% 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}} ? {{property_field}}.get() : defaultValue;
}
{% endif %}
const {{protocol.optional_type(property)}}& {{"get" | to_method_case}}{{property_name}}() const {
return {{property_field}};
}
{% 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 %}
{{protocol.optional_type(property)}} 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 -%}
{{protocol.optional_type(parameter)}} {{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 -%}
{{protocol.optional_type(parameter)}} 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 -%}
{{protocol.optional_type(parameter)}}* 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 -%}
{{protocol.optional_type(parameter)}} {{parameter.name}} = {}
{%- 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)