blob: 4e447337c279a2673758e3036cea15936ac080f3 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package codegen
const protocolTemplateProxiesAndStubs = `
{{- define "ProtocolForwardDeclaration/ProxiesAndStubs" }}
{{ EnsureNamespace . }}
{{- IfdefFuchsia -}}
{{- .Docs }}
using {{ .Name }}Ptr = ::fidl::InterfacePtr<{{ .Name }}>;
class {{ .Proxy.Name }};
class {{ .Stub.Name }};
class {{ .EventSender.Name }};
class {{ .SyncInterface.Name }};
using {{ .Name }}SyncPtr = ::fidl::SynchronousInterfacePtr<{{ .Name }}>;
class {{ .SyncProxy.Name }};
{{ range .Methods }}
{{- EnsureNamespace .OrdinalName }}
constexpr uint64_t {{ .OrdinalName.Name }} = {{ .Ordinal | printf "%#x" }}lu;
{{- end }}
{{- EndifFuchsia -}}
{{- end }}
{{- define "Params" -}}
{{- range $index, $param := . -}}
{{- if $index }}, {{ end -}}{{ $param.Type }} {{ $param.Name }}
{{- end -}}
{{ end }}
{{- define "OutParams" -}}
{{- range $index, $param := . -}}
{{- if $index }}, {{ end -}}{{ $param.Type }}* out_{{ $param.Name }}
{{- end -}}
{{ end }}
{{- define "ParamTypes" -}}
{{- range $index, $param := . -}}
{{- if $index }}, {{ end -}}{{ $param.Type }}
{{- end -}}
{{ end }}
{{- define "RequestMethodSignature" -}}
{{- if .HasResponse -}}
{{ .Name }}({{ template "Params" .RequestArgs }}{{ if .RequestArgs }}, {{ end }}{{ .CallbackType }} callback)
{{- else -}}
{{ .Name }}({{ template "Params" .RequestArgs }})
{{- end -}}
{{ end -}}
{{- define "EventMethodSignature" -}}
{{ .Name }}({{ template "Params" .ResponseArgs }})
{{- end -}}
{{- define "SyncRequestMethodSignature" -}}
{{- if .ResponseArgs -}}
{{ .Name }}({{ template "Params" .RequestArgs }}{{ if .RequestArgs }}, {{ end }}{{ template "OutParams" .ResponseArgs }})
{{- else -}}
{{ .Name }}({{ template "Params" .RequestArgs }})
{{- end -}}
{{ end -}}
{{- define "ProtocolDeclaration/ProxiesAndStubs" }}
{{- IfdefFuchsia -}}
{{- .Docs }}
class {{ .Name }} {
public:
using Proxy_ = {{ .Proxy }};
using Stub_ = {{ .Stub }};
using EventSender_ = {{ .EventSender }};
using Sync_ = {{ .SyncInterface }};
{{- if .DiscoverableName }}
static const char Name_[];
{{- end }}
virtual ~{{ .Name }}();
{{- range .Methods }}
{{- if .HasResponse }}
using {{ .CallbackType }} =
{{ .CallbackWrapper }}<void({{ template "ParamTypes" .ResponseArgs }})>;
{{- end }}
{{- if .HasRequest }}
{{ .Docs }}
{{- if .Transitional }}
virtual void {{ template "RequestMethodSignature" . }} { }
{{- else }}
virtual void {{ template "RequestMethodSignature" . }} = 0;
{{- end }}
{{- end }}
{{- end }}
};
class {{ .RequestDecoder.Name }} {
public:
{{ .RequestDecoder.Name }}() = default;
virtual ~{{ .RequestDecoder.Name }}() = default;
static const fidl_type_t* GetType(uint64_t ordinal, bool* out_needs_response);
{{- range .Methods }}
{{- if .HasRequest }}
virtual void {{ .Name }}({{ template "Params" .RequestArgs }}) = 0;
{{- end }}
{{- end }}
};
class {{ .ResponseDecoder.Name }} {
public:
{{ .ResponseDecoder.Name }}() = default;
virtual ~{{ .ResponseDecoder.Name }}() = default;
static const fidl_type_t* GetType(uint64_t ordinal);
{{- range .Methods }}
{{- if .HasResponse }}
virtual void {{ .Name }}({{ template "Params" .ResponseArgs }}) = 0;
{{- end }}
{{- end }}
};
class {{ .EventSender.Name }} {
public:
virtual ~{{ .EventSender.Name }}();
{{- range .Methods }}
{{- if not .HasRequest }}
{{- if .HasResponse }}
virtual void {{ template "EventMethodSignature" . }} = 0;
{{- end }}
{{- end }}
{{- end }}
};
class {{ .SyncInterface.Name }} {
public:
using Proxy_ = {{ .SyncProxy }};
virtual ~{{ .SyncInterface.Name }}();
{{- range .Methods }}
{{- if .HasRequest }}
virtual zx_status_t {{ template "SyncRequestMethodSignature" . }} = 0;
{{- end }}
{{- end }}
};
class {{ .Proxy.Name }} final : public ::fidl::internal::Proxy, public {{ .Name }} {
public:
explicit {{ .Proxy.Name }}(::fidl::internal::ProxyController* controller);
~{{ .Proxy.Name }}() override;
zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message) override;
{{- range .Methods }}
{{- if .HasRequest }}
void {{ template "RequestMethodSignature" . }} override;
{{- else if .HasResponse }}
{{ .CallbackType }} {{ .Name }};
{{- end }}
{{- end }}
private:
{{ .Proxy.Name }}(const {{ .Proxy }}&) = delete;
{{ .Proxy.Name }}& operator=(const {{ .Proxy }}&) = delete;
::fidl::internal::ProxyController* controller_;
};
class {{ .Stub.Name }} final : public ::fidl::internal::Stub, public {{ .EventSender }} {
public:
typedef class {{ . }} {{ .InterfaceAliasForStub.Self }};
explicit {{ .Stub.Name }}({{ .InterfaceAliasForStub }}* impl);
~{{ .Stub.Name }}() override;
zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message,
::fidl::internal::PendingResponse response) override;
{{- range .Methods }}
{{- if not .HasRequest }}
{{- if .HasResponse }}
void {{ template "EventMethodSignature" . }} override;
{{- end }}
{{- end }}
{{- end }}
private:
{{ .InterfaceAliasForStub }}* impl_;
};
class {{ .SyncProxy.Name }} : public {{ .SyncInterface }} {
public:
explicit {{ .SyncProxy.Name }}(::zx::channel channel);
~{{ .SyncProxy.Name }}() override;
{{- range .Methods }}
{{- if .HasRequest }}
zx_status_t {{ template "SyncRequestMethodSignature" . }} override;
{{- end }}
{{- end }}
private:
::fidl::internal::SynchronousProxy proxy_;
friend class ::fidl::SynchronousInterfacePtr<{{ .Name }}>;
};
{{- EndifFuchsia -}}
{{- end }}
{{- define "ProtocolDefinition" }}
{{- IfdefFuchsia -}}
{{- range .Methods }}
{{ if .HasRequest }}
{{ EnsureNamespace .Request.HlCodingTable }}
extern "C" const fidl_type_t {{ .Request.HlCodingTable.Name }};
{{- end }}
{{- if .HasResponse }}
{{ EnsureNamespace .Response.HlCodingTable }}
extern "C" const fidl_type_t {{ .Response.HlCodingTable.Name }};
{{- end }}
{{- end }}
{{ EnsureNamespace . }}
{{ .Name }}::~{{ .Name }}() = default;
{{- if .DiscoverableName }}
const char {{ .Name }}::Name_[] = {{ .DiscoverableName }};
{{- end }}
const fidl_type_t* {{ .RequestDecoder }}::GetType(uint64_t ordinal, bool* out_needs_response) {
switch (ordinal) {
{{- range .Methods }}
{{- if .HasRequest }}
case {{ .OrdinalName }}:
{{- if .HasResponse }}
*out_needs_response = true;
{{- else }}
*out_needs_response = false;
{{- end }}
return &{{ .Request.HlCodingTable }};
{{- end }}
{{- end }}
default:
*out_needs_response = false;
return nullptr;
}
}
const fidl_type_t* {{ .ResponseDecoder.Name }}::GetType(uint64_t ordinal) {
switch (ordinal) {
{{- range .Methods }}
{{- if .HasResponse }}
case {{ .OrdinalName }}:
return &{{ .Response.HlCodingTable }};
{{- end }}
{{- end }}
default:
return nullptr;
}
}
{{ .EventSender.Name }}::~{{ .EventSender.Name }}() = default;
{{ .SyncInterface.Name }}::~{{ .SyncInterface.Name }}() = default;
{{ .Proxy.Name }}::{{ .Proxy.Name }}(::fidl::internal::ProxyController* controller)
: controller_(controller) {
(void)controller_;
}
{{ .Proxy.Name }}::~{{ .Proxy.Name }}() = default;
zx_status_t {{ .Proxy.Name }}::Dispatch_(::fidl::HLCPPIncomingMessage message) {
zx_status_t status = ZX_OK;
switch (message.ordinal()) {
{{- range .Methods }}
{{- if not .HasRequest }}
{{- if .HasResponse }}
case {{ .OrdinalName }}:
{
if (!{{ .Name }}) {
status = ZX_OK;
break;
}
const char* error_msg = nullptr;
status = message.Decode(&{{ .Response.HlCodingTable }}, &error_msg);
if (status != ZX_OK) {
FIDL_REPORT_DECODING_ERROR(message, &{{ .Response.HlCodingTable }}, error_msg);
break;
}
{{- if .ResponseArgs }}
::fidl::Decoder decoder(std::move(message));
{{- end }}
{{ .Name }}(
{{- range $index, $param := .ResponseArgs -}}
{{- if $index }}, {{ end }}::fidl::DecodeAs<{{ .Type }}>(&decoder, {{ .Offset }})
{{- end -}}
);
break;
}
{{- end }}
{{- end }}
{{- end }}
default: {
status = ZX_ERR_NOT_SUPPORTED;
break;
}
}
return status;
}
{{ range .Methods }}
{{- if .HasRequest }}
{{- if .HasResponse }}
namespace {
::std::unique_ptr<::fidl::internal::SingleUseMessageHandler>
{{- /* Note: fidl::internal::SingleUseMessageHandler assumes that the lambda captures a single */}}
{{- /* fit::function. When changing CallbackType, make sure to update SingleUseMessageHandler. */}}
{{ .ResponseHandlerType }}({{ $.Name }}::{{ .CallbackType }}&& callback) {
ZX_DEBUG_ASSERT_MSG(callback,
"Callback must not be empty for {{ $.Name }}::{{ .Name }}\n");
return ::std::make_unique<::fidl::internal::SingleUseMessageHandler>(
[callback_ = std::move(callback)](::fidl::HLCPPIncomingMessage&& message) {
{{- if .ResponseArgs }}
::fidl::Decoder decoder(std::move(message));
{{- end }}
callback_(
{{- range $index, $param := .ResponseArgs -}}
{{- if $index }}, {{ end }}::fidl::DecodeAs<{{ .Type }}>(&decoder, {{ .Offset }})
{{- end -}}
);
return ZX_OK;
}, &{{ .Response.HlCodingTable }});
}
} // namespace
{{- end }}
void {{ $.Proxy.Name }}::{{ template "RequestMethodSignature" . }} {
::fidl::Encoder _encoder({{ .OrdinalName }});
controller_->Send(&{{ .Request.HlCodingTable }}, {{ $.RequestEncoder }}::{{ .Name }}(&_encoder
{{- range $index, $param := .RequestArgs -}}
, &{{ $param.Name }}
{{- end -}}
)
{{- if .HasResponse -}}
, {{ .ResponseHandlerType }}(std::move(callback))
{{- else -}}
, nullptr
{{- end -}}
);
}
{{- end }}
{{- end }}
{{ .Stub.Name }}::{{ .Stub.Name }}({{ .InterfaceAliasForStub }}* impl) : impl_(impl) {
(void)impl_;
}
{{ .Stub.Name }}::~{{ .Stub.Name }}() = default;
namespace {
{{- range .Methods }}
{{- if .HasRequest }}
{{- if .HasResponse }}
class {{ .ResponderType }} final {
public:
{{ .ResponderType }}(::fidl::internal::PendingResponse response)
: response_(std::move(response)) {}
void operator()({{ template "Params" .ResponseArgs }}) {
::fidl::Encoder _encoder({{ .OrdinalName }});
response_.Send(&{{ .Response.HlCodingTable }}, {{ $.ResponseEncoder }}::{{ .Name }}(&_encoder
{{- range $index, $param := .ResponseArgs -}}
, &{{ $param.Name }}
{{- end -}}
));
}
private:
::fidl::internal::PendingResponse response_;
};
{{- end }}
{{- end }}
{{- end }}
} // namespace
zx_status_t {{ .Stub.Name }}::Dispatch_(
::fidl::HLCPPIncomingMessage message,
::fidl::internal::PendingResponse response) {
bool needs_response;
const fidl_type_t* request_type = {{ .RequestDecoder }}::GetType(message.ordinal(), &needs_response);
if (request_type == nullptr) {
return ZX_ERR_NOT_SUPPORTED;
}
if (response.needs_response() != needs_response) {
if (needs_response) {
FIDL_REPORT_DECODING_ERROR(message, request_type, "Message needing a response with no txid");
} else {
FIDL_REPORT_DECODING_ERROR(message, request_type, "Message not needing a response with a txid");
}
return ZX_ERR_INVALID_ARGS;
}
const char* error_msg = nullptr;
zx_status_t status = message.Decode(request_type, &error_msg);
if (status != ZX_OK) {
FIDL_REPORT_DECODING_ERROR(message, request_type, error_msg);
return status;
}
uint64_t ordinal = message.ordinal();
switch (ordinal) {
{{- range .Methods }}
{{- if .HasRequest }}
case {{ .OrdinalName }}:
{
{{- if .RequestArgs }}
::fidl::Decoder decoder(std::move(message));
{{- end }}
impl_->{{ .Name }}(
{{- range $index, $param := .RequestArgs -}}
{{- if $index }}, {{ end }}::fidl::DecodeAs<{{ .Type }}>(&decoder, {{ .Offset }})
{{- end -}}
{{- if .HasResponse -}}
{{- if .RequestArgs }}, {{ end -}}{{ .ResponderType }}(std::move(response))
{{- end -}}
);
break;
}
{{- end }}
{{- end }}
default: {
status = ZX_ERR_NOT_SUPPORTED;
break;
}
}
return status;
}
{{- range .Methods }}
{{- if not .HasRequest }}
{{- if .HasResponse }}
void {{ $.Stub.Name }}::{{ template "EventMethodSignature" . }} {
::fidl::Encoder _encoder({{ .OrdinalName }});
sender_()->Send(&{{ .Response.HlCodingTable }}, {{ $.ResponseEncoder }}::{{ .Name }}(&_encoder
{{- range $index, $param := .ResponseArgs -}}
, &{{ $param.Name }}
{{- end -}}
));
}
{{- end }}
{{- end }}
{{- end }}
{{ .SyncProxy.Name }}::{{ .SyncProxy.Name }}(::zx::channel channel)
: proxy_(::std::move(channel)) {}
{{ .SyncProxy.Name }}::~{{ .SyncProxy.Name }}() = default;
{{- range .Methods }}
{{- if .HasRequest }}
zx_status_t {{ $.SyncProxy.Name }}::{{ template "SyncRequestMethodSignature" . }} {
::fidl::Encoder _encoder({{ .OrdinalName }});
{{- if .HasResponse }}
::fidl::IncomingMessageBuffer buffer_;
::fidl::HLCPPIncomingMessage response_ = buffer_.CreateEmptyIncomingMessage();
zx_status_t status_ = proxy_.Call(&{{ .Request.HlCodingTable }}, &{{ .Response.HlCodingTable }}, {{ $.RequestEncoder }}::{{ .Name }}(&_encoder
{{- range $index, $param := .RequestArgs -}}
, &{{ $param.Name }}
{{- end -}}
), &response_);
if (status_ != ZX_OK)
return status_;
{{- if .ResponseArgs }}
::fidl::Decoder decoder_(std::move(response_));
{{- range $index, $param := .ResponseArgs }}
*out_{{ .Name }} = ::fidl::DecodeAs<{{ .Type }}>(&decoder_, {{ .Offset }});
{{- end }}
{{- end }}
return ZX_OK;
{{- else }}
return proxy_.Send(&{{ .Request.HlCodingTable }}, {{ $.RequestEncoder }}::{{ .Name }}(&_encoder
{{- range $index, $param := .RequestArgs -}}
, &{{ $param.Name }}
{{- end -}}
));
{{- end }}
}
{{- end }}
{{- end }}
{{- EndifFuchsia -}}
{{ end }}
`