blob: 7a45d667a604789aa52b9bec5cf56fda1fb506e6 [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 fragmentProtocolTmpl = `
{{- define "ProtocolForwardDeclaration" }}
{{ EnsureNamespace . }}
class {{ .Name }};
{{- end }}
{{- define "ForwardMessageParamsUnwrapTypedChannels" -}}
{{- range $index, $param := . -}}
{{- if $index }}, {{ end -}} std::move(
{{- if or (eq .Type.Kind TypeKinds.Protocol) (eq .Type.Kind TypeKinds.Request) -}}
{{ $param.Name }}.channel()
{{- else -}}
{{ $param.Name }}
{{- end -}}
)
{{- end -}}
{{- end }}
{{- define "ClientAllocationComment" -}}
{{- $context := .LLProps.ClientContext }}
{{- if StackUse $context }} Allocates {{ StackUse $context }} bytes of {{ "" }}
{{- if not $context.StackAllocRequest -}} response {{- else -}}
{{- if not $context.StackAllocResponse -}} request {{- else -}} message {{- end -}}
{{- end }} buffer on the stack. {{- end }}
{{- if and $context.StackAllocRequest $context.StackAllocResponse }} No heap allocation necessary.
{{- else }}
{{- if not $context.StackAllocRequest }} Request is heap-allocated. {{- end }}
{{- if not $context.StackAllocResponse }} Response is heap-allocated. {{- end }}
{{- end }}
{{- end }}
{{- define "RequestSentSize" }}
{{- if gt .RequestSentMaxSize 65536 -}}
ZX_CHANNEL_MAX_MSG_BYTES
{{- else -}}
PrimarySize + MaxOutOfLine
{{- end -}}
{{- end }}
{{- define "ResponseSentSize" }}
{{- if gt .ResponseSentMaxSize 65536 -}}
ZX_CHANNEL_MAX_MSG_BYTES
{{- else -}}
PrimarySize + MaxOutOfLine
{{- end -}}
{{- end }}
{{- define "ResponseReceivedSize" }}
{{- if gt .ResponseReceivedMaxSize 65536 -}}
ZX_CHANNEL_MAX_MSG_BYTES
{{- else -}}
{{ .Name }}Response::PrimarySize + {{ .Name }}Response::MaxOutOfLine
{{- end -}}
{{- end }}
{{- define "ResponseReceivedByteAccess" }}
{{- if gt .ResponseReceivedMaxSize 512 -}}
bytes_->data()
{{- else -}}
bytes_
{{- end -}}
{{- end }}
{{- define "ProtocolDeclaration" }}
{{- $protocol := . }}
{{ "" }}
{{- range .Methods }}
{{ EnsureNamespace .RequestCodingTable }}
extern "C" const fidl_type_t {{ .RequestCodingTable.Name }};
{{ EnsureNamespace .ResponseCodingTable }}
extern "C" const fidl_type_t {{ .ResponseCodingTable.Name }};
{{- end }}
{{ "" }}
{{ EnsureNamespace . }}
{{- range .DocComments }}
//{{ . }}
{{- end }}
class {{ .Name }} final {
{{ .Name }}() = delete;
public:
{{- if .ServiceName }}
static constexpr char Name[] = {{ .ServiceName }};
{{- end }}
{{ "" }}
{{- range .Methods }}
{{- if .HasResponse }}
struct {{ .Name }}Response final {
FIDL_ALIGNDECL
{{- /* Add underscore to prevent name collision */}}
fidl_message_header_t _hdr;
{{- range $index, $param := .Response }}
{{ $param.Type }} {{ $param.Name }};
{{- end }}
{{- if .Response }}
explicit {{ .Name }}Response({{ .Response | MessagePrototype }})
{{ .Response | InitMessage }} {
_InitHeader();
}
{{- end }}
{{ .Name }}Response() {
_InitHeader();
}
static constexpr const fidl_type_t* Type =
{{- if .Response }}
&{{ .ResponseCodingTable }};
{{- else }}
&::fidl::_llcpp_coding_AnyZeroArgMessageTable;
{{- end }}
static constexpr uint32_t MaxNumHandles = {{ .ResponseMaxHandles }};
static constexpr uint32_t PrimarySize = {{ .ResponseSize }};
static constexpr uint32_t MaxOutOfLine = {{ .ResponseMaxOutOfLine }};
static constexpr bool HasFlexibleEnvelope = {{ .ResponseFlexible }};
static constexpr bool HasPointer = {{ .ResponseHasPointer }};
static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
::fidl::internal::TransactionalMessageKind::kResponse;
{{- if .ResponseIsResource }}
void _CloseHandles();
{{- end }}
private:
class UnownedEncodedByteMessage final {
public:
UnownedEncodedByteMessage(uint8_t* _bytes, uint32_t _byte_size
{{- .Response | CommaMessagePrototype }})
: message_(_bytes, _byte_size, sizeof({{ .Name }}Response),
{{- if gt .ResponseMaxHandles 0 }}
handles_, std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0
{{- else }}
nullptr, 0, 0
{{- end }}
) {
FIDL_ALIGNDECL {{ .Name }}Response _response{
{{- .Response | ParamNames -}}
};
message_.Encode<{{ .Name }}Response>(&_response);
}
UnownedEncodedByteMessage(uint8_t* bytes, uint32_t byte_size, {{ .Name }}Response* response)
: message_(bytes, byte_size, sizeof({{ .Name }}Response),
{{- if gt .ResponseMaxHandles 0 }}
handles_, std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0
{{- else }}
nullptr, 0, 0
{{- end }}
) {
message_.Encode<{{ .Name }}Response>(response);
}
UnownedEncodedByteMessage(const UnownedEncodedByteMessage&) = delete;
UnownedEncodedByteMessage(UnownedEncodedByteMessage&&) = delete;
UnownedEncodedByteMessage* operator=(const UnownedEncodedByteMessage&) = delete;
UnownedEncodedByteMessage* operator=(UnownedEncodedByteMessage&&) = delete;
zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
const char* status_string() const { return message_.status_string(); }
#endif
bool ok() const { return message_.status() == ZX_OK; }
const char* error() const { return message_.error(); }
::fidl::OutgoingByteMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
template <typename ChannelLike>
void Write(ChannelLike&& client) { message_.Write(std::forward<ChannelLike>(client)); }
#endif
private:
{{- if gt .ResponseMaxHandles 0 }}
zx_handle_disposition_t handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
{{- end }}
::fidl::OutgoingByteMessage message_;
};
class UnownedEncodedIovecMessage final {
public:
UnownedEncodedIovecMessage(zx_channel_iovec_t* iovecs, uint32_t iovec_size,
fidl_iovec_substitution_t* substitutions, uint32_t substitutions_size
{{- .Response | CommaMessagePrototype }})
: message_(::fidl::OutgoingIovecMessage::constructor_args{
.iovecs = iovecs,
.iovecs_actual = 0,
.iovecs_capacity = iovec_size,
.substitutions = substitutions,
.substitutions_actual = 0,
.substitutions_capacity = substitutions_size,
{{- if gt .ResponseMaxHandles 0 }}
.handles = handles_,
.handle_actual = 0,
.handle_capacity = std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles),
{{- else }}
.handles = nullptr,
.handle_actual = 0,
.handle_capacity = 0,
{{- end }}
}) {
FIDL_ALIGNDECL {{ .Name }}Response _response{
{{- .Response | ParamNames -}}
};
message_.Encode<{{ .Name }}Response>(&_response);
}
UnownedEncodedIovecMessage(zx_channel_iovec_t* iovecs, uint32_t iovec_size,
fidl_iovec_substitution_t* substitutions, uint32_t substitutions_size,
{{ .Name }}Response* response)
: message_(::fidl::OutgoingIovecMessage::constructor_args{
.iovecs = iovecs,
.iovecs_actual = 0,
.iovecs_capacity = iovec_size,
.substitutions = substitutions,
.substitutions_actual = 0,
.substitutions_capacity = substitutions_size,
{{- if gt .ResponseMaxHandles 0 }}
.handles = handles_,
.handle_actual = 0,
.handle_capacity = std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles),
{{- else }}
.handles = nullptr,
.handle_actual = 0,
.handle_capacity = 0,
{{- end }}
}) {
message_.Encode<{{ .Name }}Response>(response);
}
UnownedEncodedIovecMessage(const UnownedEncodedIovecMessage&) = delete;
UnownedEncodedIovecMessage(UnownedEncodedIovecMessage&&) = delete;
UnownedEncodedIovecMessage* operator=(const UnownedEncodedIovecMessage&) = delete;
UnownedEncodedIovecMessage* operator=(UnownedEncodedIovecMessage&&) = delete;
zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
const char* status_string() const { return message_.status_string(); }
#endif
bool ok() const { return message_.status() == ZX_OK; }
const char* error() const { return message_.error(); }
::fidl::OutgoingIovecMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
template <typename ChannelLike>
void Write(ChannelLike&& client) { message_.Write(std::forward<ChannelLike>(client)); }
#endif
private:
{{- if gt .ResponseMaxHandles 0 }}
zx_handle_disposition_t handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
{{- end }}
::fidl::OutgoingIovecMessage message_;
};
class OwnedEncodedByteMessage final {
public:
explicit OwnedEncodedByteMessage({{ .Response | MessagePrototype }})
{{- if gt .ResponseSentMaxSize 512 -}}
: bytes_(std::make_unique<::fidl::internal::AlignedBuffer<{{- template "ResponseSentSize" . }}>>()),
message_(bytes_->data(), {{- template "ResponseSentSize" . }}
{{- else }}
: message_(bytes_, sizeof(bytes_)
{{- end }}
{{- .Response | CommaParamNames }}) {}
explicit OwnedEncodedByteMessage({{ .Name }}Response* response)
{{- if gt .ResponseSentMaxSize 512 -}}
: bytes_(std::make_unique<::fidl::internal::AlignedBuffer<{{- template "ResponseSentSize" . }}>>()),
message_(bytes_->data(), {{- template "ResponseSentSize" . }}
{{- else }}
: message_(bytes_, sizeof(bytes_)
{{- end }}
, response) {}
OwnedEncodedByteMessage(const OwnedEncodedByteMessage&) = delete;
OwnedEncodedByteMessage(OwnedEncodedByteMessage&&) = delete;
OwnedEncodedByteMessage* operator=(const OwnedEncodedByteMessage&) = delete;
OwnedEncodedByteMessage* operator=(OwnedEncodedByteMessage&&) = delete;
zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
const char* status_string() const { return message_.status_string(); }
#endif
bool ok() const { return message_.ok(); }
const char* error() const { return message_.error(); }
::fidl::OutgoingByteMessage& GetOutgoingMessage() { return message_.GetOutgoingMessage(); }
#ifdef __Fuchsia__
template <typename ChannelLike>
void Write(ChannelLike&& client) { message_.Write(std::forward<ChannelLike>(client)); }
#endif
private:
{{- if gt .ResponseSentMaxSize 512 }}
std::unique_ptr<::fidl::internal::AlignedBuffer<{{- template "ResponseSentSize" . }}>> bytes_;
{{- else }}
FIDL_ALIGNDECL
uint8_t bytes_[PrimarySize + MaxOutOfLine];
{{- end }}
UnownedEncodedByteMessage message_;
};
class OwnedEncodedIovecMessage final {
public:
explicit OwnedEncodedIovecMessage({{ .Response | MessagePrototype }})
: message_(iovecs_, ::fidl::internal::kIovecBufferSize,
substitutions_, ::fidl::internal::kIovecBufferSize
{{- .Response | CommaParamNames }}) {}
explicit OwnedEncodedIovecMessage({{ .Name }}Response* response)
: message_(iovecs_, ::fidl::internal::kIovecBufferSize,
substitutions_, ::fidl::internal::kIovecBufferSize,
response) {}
OwnedEncodedIovecMessage(const OwnedEncodedIovecMessage&) = delete;
OwnedEncodedIovecMessage(OwnedEncodedIovecMessage&&) = delete;
OwnedEncodedIovecMessage* operator=(const OwnedEncodedIovecMessage&) = delete;
OwnedEncodedIovecMessage* operator=(OwnedEncodedIovecMessage&&) = delete;
zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
const char* status_string() const { return message_.status_string(); }
#endif
bool ok() const { return message_.ok(); }
const char* error() const { return message_.error(); }
::fidl::OutgoingIovecMessage& GetOutgoingMessage() { return message_.GetOutgoingMessage(); }
#ifdef __Fuchsia__
template <typename ChannelLike>
void Write(ChannelLike&& client) { message_.Write(std::forward<ChannelLike>(client)); }
#endif
private:
zx_channel_iovec_t iovecs_[::fidl::internal::kIovecBufferSize];
fidl_iovec_substitution_t substitutions_[::fidl::internal::kIovecBufferSize];
UnownedEncodedIovecMessage message_;
};
public:
friend ::fidl::internal::EncodedMessageTypes<{{ .Name }}Response>;
using OwnedEncodedMessage = OwnedEncodedByteMessage;
using UnownedEncodedMessage = UnownedEncodedByteMessage;
class DecodedMessage final : public ::fidl::internal::IncomingMessage {
public:
DecodedMessage(uint8_t* bytes, uint32_t byte_actual, zx_handle_info_t* handles = nullptr,
uint32_t handle_actual = 0)
: ::fidl::internal::IncomingMessage(bytes, byte_actual, handles, handle_actual) {
Decode<{{ .Name }}Response>();
}
DecodedMessage(fidl_incoming_msg_t* msg) : ::fidl::internal::IncomingMessage(msg) {
Decode<{{ .Name }}Response>();
}
DecodedMessage(const DecodedMessage&) = delete;
DecodedMessage(DecodedMessage&&) = delete;
DecodedMessage* operator=(const DecodedMessage&) = delete;
DecodedMessage* operator=(DecodedMessage&&) = delete;
{{- if .ResponseIsResource }}
~DecodedMessage() {
if (ok() && (PrimaryObject() != nullptr)) {
PrimaryObject()->_CloseHandles();
}
}
{{- end }}
{{ .Name }}Response* PrimaryObject() {
ZX_DEBUG_ASSERT(ok());
return reinterpret_cast<{{ .Name }}Response*>(bytes());
}
// Release the ownership of the decoded message. That means that the handles won't be closed
// When the object is destroyed.
// After calling this method, the DecodedMessage object should not be used anymore.
void ReleasePrimaryObject() { ResetBytes(); }
};
private:
void _InitHeader();
};
{{- end }}
{{- if .HasRequest }}
struct {{ .Name }}Request final {
FIDL_ALIGNDECL
{{- /* Add underscore to prevent name collision */}}
fidl_message_header_t _hdr;
{{- range $index, $param := .Request }}
{{ $param.Type }} {{ $param.Name }};
{{- end }}
{{- if .Request }}
explicit {{ .Name }}Request(zx_txid_t _txid {{- .Request | CommaMessagePrototype }})
{{ .Request | InitMessage }} {
_InitHeader(_txid);
}
{{- end }}
explicit {{ .Name }}Request(zx_txid_t _txid) {
_InitHeader(_txid);
}
static constexpr const fidl_type_t* Type =
{{- if .Request }}
&{{ .RequestCodingTable }};
{{- else }}
&::fidl::_llcpp_coding_AnyZeroArgMessageTable;
{{- end }}
static constexpr uint32_t MaxNumHandles = {{ .RequestMaxHandles }};
static constexpr uint32_t PrimarySize = {{ .RequestSize }};
static constexpr uint32_t MaxOutOfLine = {{ .RequestMaxOutOfLine }};
static constexpr uint32_t AltPrimarySize = {{ .RequestSize }};
static constexpr uint32_t AltMaxOutOfLine = {{ .RequestMaxOutOfLine }};
static constexpr bool HasFlexibleEnvelope = {{ .RequestFlexible }};
static constexpr bool HasPointer = {{ .RequestHasPointer }};
static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
::fidl::internal::TransactionalMessageKind::kRequest;
{{- if and .HasResponse .Response }}
using ResponseType = {{ .Name }}Response;
{{- end }}
{{- if .RequestIsResource }}
void _CloseHandles();
{{- end }}
private:
class UnownedEncodedByteMessage final {
public:
UnownedEncodedByteMessage(uint8_t* _bytes, uint32_t _byte_size, zx_txid_t _txid
{{- .Request | CommaMessagePrototype }})
: message_(_bytes, _byte_size, sizeof({{ .Name }}Request),
{{- if gt .RequestMaxHandles 0 }}
handles_, std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0
{{- else }}
nullptr, 0, 0
{{- end }}
) {
FIDL_ALIGNDECL {{ .Name }}Request _request(_txid
{{- .Request | CommaParamNames -}}
);
message_.Encode<{{ .Name }}Request>(&_request);
}
UnownedEncodedByteMessage(uint8_t* bytes, uint32_t byte_size, {{ .Name }}Request* request)
: message_(bytes, byte_size, sizeof({{ .Name }}Request),
{{- if gt .RequestMaxHandles 0 }}
handles_, std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0
{{- else }}
nullptr, 0, 0
{{- end }}
) {
message_.Encode<{{ .Name }}Request>(request);
}
UnownedEncodedByteMessage(const UnownedEncodedByteMessage&) = delete;
UnownedEncodedByteMessage(UnownedEncodedByteMessage&&) = delete;
UnownedEncodedByteMessage* operator=(const UnownedEncodedByteMessage&) = delete;
UnownedEncodedByteMessage* operator=(UnownedEncodedByteMessage&&) = delete;
zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
const char* status_string() const { return message_.status_string(); }
#endif
bool ok() const { return message_.status() == ZX_OK; }
const char* error() const { return message_.error(); }
::fidl::OutgoingByteMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
template <typename ChannelLike>
void Write(ChannelLike&& client) { message_.Write(std::forward<ChannelLike>(client)); }
#endif
private:
{{- if gt .RequestMaxHandles 0 }}
zx_handle_disposition_t handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
{{- end }}
::fidl::OutgoingByteMessage message_;
};
class UnownedEncodedIovecMessage final {
public:
UnownedEncodedIovecMessage(zx_channel_iovec_t* iovecs, uint32_t iovec_size,
fidl_iovec_substitution_t* substitutions, uint32_t substitutions_size,
zx_txid_t _txid
{{- .Request | CommaMessagePrototype }})
: message_(::fidl::OutgoingIovecMessage::constructor_args{
.iovecs = iovecs,
.iovecs_actual = 0,
.iovecs_capacity = iovec_size,
.substitutions = substitutions,
.substitutions_actual = 0,
.substitutions_capacity = substitutions_size,
{{- if gt .RequestMaxHandles 0 }}
.handles = handles_,
.handle_actual = 0,
.handle_capacity = std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles),
{{- else }}
.handles = nullptr,
.handle_actual = 0,
.handle_capacity = 0,
{{- end }}
}) {
FIDL_ALIGNDECL {{ .Name }}Request _request(_txid
{{- .Request | CommaParamNames -}}
);
message_.Encode<{{ .Name }}Request>(&_request);
}
UnownedEncodedIovecMessage(zx_channel_iovec_t* iovecs, uint32_t iovec_size,
fidl_iovec_substitution_t* substitutions, uint32_t substitutions_size,
{{ .Name }}Request* request)
: message_(::fidl::OutgoingIovecMessage::constructor_args{
.iovecs = iovecs,
.iovecs_actual = 0,
.iovecs_capacity = iovec_size,
.substitutions = substitutions,
.substitutions_actual = 0,
.substitutions_capacity = substitutions_size,
{{- if gt .RequestMaxHandles 0 }}
.handles = handles_,
.handle_actual = 0,
.handle_capacity = std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles),
{{- else }}
.handles = nullptr,
.handle_actual = 0,
.handle_capacity = 0,
{{- end }}
}) {
message_.Encode<{{ .Name }}Request>(request);
}
UnownedEncodedIovecMessage(const UnownedEncodedIovecMessage&) = delete;
UnownedEncodedIovecMessage(UnownedEncodedIovecMessage&&) = delete;
UnownedEncodedIovecMessage* operator=(const UnownedEncodedIovecMessage&) = delete;
UnownedEncodedIovecMessage* operator=(UnownedEncodedIovecMessage&&) = delete;
zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
const char* status_string() const { return message_.status_string(); }
#endif
bool ok() const { return message_.status() == ZX_OK; }
const char* error() const { return message_.error(); }
::fidl::OutgoingIovecMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
template <typename ChannelLike>
void Write(ChannelLike&& client) { message_.Write(std::forward<ChannelLike>(client)); }
#endif
private:
{{- if gt .RequestMaxHandles 0 }}
zx_handle_disposition_t handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
{{- end }}
::fidl::OutgoingIovecMessage message_;
};
class OwnedEncodedByteMessage final {
public:
explicit OwnedEncodedByteMessage(zx_txid_t _txid
{{- .Request | CommaMessagePrototype }})
{{- if gt .RequestSentMaxSize 512 -}}
: bytes_(std::make_unique<::fidl::internal::AlignedBuffer<{{- template "RequestSentSize" . }}>>()),
message_(bytes_->data(), {{- template "RequestSentSize" . }}, _txid
{{- else }}
: message_(bytes_, sizeof(bytes_), _txid
{{- end }}
{{- .Request | CommaParamNames }}) {}
explicit OwnedEncodedByteMessage({{ .Name }}Request* request)
{{- if gt .RequestSentMaxSize 512 -}}
: bytes_(std::make_unique<::fidl::internal::AlignedBuffer<{{- template "RequestSentSize" . }}>>()),
message_(bytes_->data(), {{- template "RequestSentSize" . }}
{{- else }}
: message_(bytes_, sizeof(bytes_)
{{- end }}
, request) {}
OwnedEncodedByteMessage(const OwnedEncodedByteMessage&) = delete;
OwnedEncodedByteMessage(OwnedEncodedByteMessage&&) = delete;
OwnedEncodedByteMessage* operator=(const OwnedEncodedByteMessage&) = delete;
OwnedEncodedByteMessage* operator=(OwnedEncodedByteMessage&&) = delete;
zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
const char* status_string() const { return message_.status_string(); }
#endif
bool ok() const { return message_.ok(); }
const char* error() const { return message_.error(); }
::fidl::OutgoingByteMessage& GetOutgoingMessage() { return message_.GetOutgoingMessage(); }
#ifdef __Fuchsia__
template <typename ChannelLike>
void Write(ChannelLike&& client) { message_.Write(std::forward<ChannelLike>(client)); }
#endif
private:
{{- if gt .RequestSentMaxSize 512 }}
std::unique_ptr<::fidl::internal::AlignedBuffer<{{- template "RequestSentSize" . }}>> bytes_;
{{- else }}
FIDL_ALIGNDECL
uint8_t bytes_[PrimarySize + MaxOutOfLine];
{{- end }}
UnownedEncodedByteMessage message_;
};
class OwnedEncodedIovecMessage final {
public:
explicit OwnedEncodedIovecMessage(zx_txid_t _txid
{{- .Request | CommaMessagePrototype }})
: message_(iovecs_, ::fidl::internal::kIovecBufferSize,
substitutions_, ::fidl::internal::kIovecBufferSize, _txid
{{- .Request | CommaParamNames }}) {}
explicit OwnedEncodedIovecMessage({{ .Name }}Request* request)
: message_(iovecs_, ::fidl::internal::kIovecBufferSize,
substitutions_, ::fidl::internal::kIovecBufferSize,
request) {}
OwnedEncodedIovecMessage(const OwnedEncodedIovecMessage&) = delete;
OwnedEncodedIovecMessage(OwnedEncodedIovecMessage&&) = delete;
OwnedEncodedIovecMessage* operator=(const OwnedEncodedIovecMessage&) = delete;
OwnedEncodedIovecMessage* operator=(OwnedEncodedIovecMessage&&) = delete;
zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
const char* status_string() const { return message_.status_string(); }
#endif
bool ok() const { return message_.ok(); }
const char* error() const { return message_.error(); }
::fidl::OutgoingIovecMessage& GetOutgoingMessage() { return message_.GetOutgoingMessage(); }
#ifdef __Fuchsia__
template <typename ChannelLike>
void Write(ChannelLike&& client) { message_.Write(std::forward<ChannelLike>(client)); }
#endif
private:
zx_channel_iovec_t iovecs_[::fidl::internal::kIovecBufferSize];
fidl_iovec_substitution_t substitutions_[::fidl::internal::kIovecBufferSize];
UnownedEncodedIovecMessage message_;
};
public:
friend ::fidl::internal::EncodedMessageTypes<{{ .Name }}Request>;
using OwnedEncodedMessage = OwnedEncodedByteMessage;
using UnownedEncodedMessage = UnownedEncodedByteMessage;
class DecodedMessage final : public ::fidl::internal::IncomingMessage {
public:
DecodedMessage(uint8_t* bytes, uint32_t byte_actual, zx_handle_info_t* handles = nullptr,
uint32_t handle_actual = 0)
: ::fidl::internal::IncomingMessage(bytes, byte_actual, handles, handle_actual) {
Decode<{{ .Name }}Request>();
}
DecodedMessage(fidl_incoming_msg_t* msg) : ::fidl::internal::IncomingMessage(msg) {
Decode<{{ .Name }}Request>();
}
DecodedMessage(const DecodedMessage&) = delete;
DecodedMessage(DecodedMessage&&) = delete;
DecodedMessage* operator=(const DecodedMessage&) = delete;
DecodedMessage* operator=(DecodedMessage&&) = delete;
{{- if .RequestIsResource }}
~DecodedMessage() {
if (ok() && (PrimaryObject() != nullptr)) {
PrimaryObject()->_CloseHandles();
}
}
{{- end }}
{{ .Name }}Request* PrimaryObject() {
ZX_DEBUG_ASSERT(ok());
return reinterpret_cast<{{ .Name }}Request*>(bytes());
}
// Release the ownership of the decoded message. That means that the handles won't be closed
// When the object is destroyed.
// After calling this method, the DecodedMessage object should not be used anymore.
void ReleasePrimaryObject() { ResetBytes(); }
};
private:
void _InitHeader(zx_txid_t _txid);
};
{{ "" }}
{{- end }}
{{- end }}
class EventHandlerInterface {
public:
EventHandlerInterface() = default;
virtual ~EventHandlerInterface() = default;
{{- range .Events -}}
{{- range .DocComments }}
//{{ . }}
{{- end }}
virtual void {{ .Name }}({{ .Name }}Response* event) {}
{{- end }}
};
{{- if .Events }}
{{ "" }}
class SyncEventHandler : public EventHandlerInterface {
public:
SyncEventHandler() = default;
// Method called when an unknown event is found. This methods gives the status which, in this
// case, is returned by HandleOneEvent.
virtual zx_status_t Unknown() = 0;
// Handle all possible events defined in this protocol.
// Blocks to consume exactly one message from the channel, then call the corresponding virtual
// method.
::fidl::Result HandleOneEvent(
::fidl::UnownedClientEnd<{{ . }}> client_end);
};
{{- end }}
#ifdef __Fuchsia__
// Collection of return types of FIDL calls in this protocol.
class ResultOf final {
ResultOf() = delete;
public:
{{- range .ClientMethods -}}
{{- if .HasResponse -}}
{{ "" }}
{{- end }}
class {{ .Name }} final : public ::fidl::Result {
public:
explicit {{ .Name }}(
::fidl::UnownedClientEnd<{{ $protocol }}> _client
{{- .Request | CommaMessagePrototype }});
{{- if .HasResponse }}
{{ .Name }}(
::fidl::UnownedClientEnd<{{ $protocol }}> _client
{{- .Request | CommaMessagePrototype }},
zx_time_t _deadline);
{{- end }}
explicit {{ .Name }}(const ::fidl::Result& result) : ::fidl::Result(result) {}
{{ .Name }}({{ .Name }}&&) = delete;
{{ .Name }}(const {{ .Name }}&) = delete;
{{ .Name }}* operator=({{ .Name }}&&) = delete;
{{ .Name }}* operator=(const {{ .Name }}&) = delete;
{{- if and .HasResponse .ResponseIsResource }}
~{{ .Name }}() {
if (ok()) {
Unwrap()->_CloseHandles();
}
}
{{- else }}
~{{ .Name }}() = default;
{{- end }}
{{- if .HasResponse }}
{{ .Name }}Response* Unwrap() {
ZX_DEBUG_ASSERT(ok());
return reinterpret_cast<{{ .Name }}Response*>({{- template "ResponseReceivedByteAccess" . }});
}
const {{ .Name }}Response* Unwrap() const {
ZX_DEBUG_ASSERT(ok());
return reinterpret_cast<const {{ .Name }}Response*>({{- template "ResponseReceivedByteAccess" . }});
}
{{ .Name }}Response& value() { return *Unwrap(); }
const {{ .Name }}Response& value() const { return *Unwrap(); }
{{ .Name }}Response* operator->() { return &value(); }
const {{ .Name }}Response* operator->() const { return &value(); }
{{ .Name }}Response& operator*() { return value(); }
const {{ .Name }}Response& operator*() const { return value(); }
{{- end }}
private:
{{- if .HasResponse }}
{{- if gt .ResponseReceivedMaxSize 512 }}
std::unique_ptr<::fidl::internal::AlignedBuffer<{{ template "ResponseReceivedSize" . }}>> bytes_;
{{- else }}
FIDL_ALIGNDECL
uint8_t bytes_[{{ .Name }}Response::PrimarySize + {{ .Name }}Response::MaxOutOfLine];
{{- end }}
{{- end }}
};
{{- end }}
};
// Collection of return types of FIDL calls in this protocol,
// when the caller-allocate flavor or in-place call is used.
class UnownedResultOf final {
UnownedResultOf() = delete;
public:
{{- range .ClientMethods -}}
class {{ .Name }} final : public ::fidl::Result {
public:
explicit {{ .Name }}(
::fidl::UnownedClientEnd<{{ $protocol }}> _client
{{- if .Request -}}
, uint8_t* _request_bytes, uint32_t _request_byte_capacity
{{- end -}}
{{- .Request | CommaMessagePrototype }}
{{- if .HasResponse -}}
, uint8_t* _response_bytes, uint32_t _response_byte_capacity
{{- end -}});
explicit {{ .Name }}(const ::fidl::Result& result) : ::fidl::Result(result) {}
{{ .Name }}({{ .Name }}&&) = delete;
{{ .Name }}(const {{ .Name }}&) = delete;
{{ .Name }}* operator=({{ .Name }}&&) = delete;
{{ .Name }}* operator=(const {{ .Name }}&) = delete;
{{- if and .HasResponse .ResponseIsResource }}
~{{ .Name }}() {
if (ok()) {
Unwrap()->_CloseHandles();
}
}
{{- else }}
~{{ .Name }}() = default;
{{- end }}
{{- if .HasResponse }}
{{ .Name }}Response* Unwrap() {
ZX_DEBUG_ASSERT(ok());
return reinterpret_cast<{{ .Name }}Response*>(bytes_);
}
const {{ .Name }}Response* Unwrap() const {
ZX_DEBUG_ASSERT(ok());
return reinterpret_cast<const {{ .Name }}Response*>(bytes_);
}
{{ .Name }}Response& value() { return *Unwrap(); }
const {{ .Name }}Response& value() const { return *Unwrap(); }
{{ .Name }}Response* operator->() { return &value(); }
const {{ .Name }}Response* operator->() const { return &value(); }
{{ .Name }}Response& operator*() { return value(); }
const {{ .Name }}Response& operator*() const { return value(); }
private:
uint8_t* bytes_;
{{- end }}
};
{{- end }}
};
// Methods to make a sync FIDL call directly on an unowned channel or a
// const reference to a |fidl::ClientEnd<{{ .WireType }}>|,
// avoiding setting up a client.
class Call final {
Call() = delete;
public:
{{ "" }}
{{- /* Client-calling functions do not apply to events. */}}
{{- range .ClientMethods -}}
{{- range .DocComments }}
//{{ . }}
{{- end }}
//{{ template "ClientAllocationComment" . }}
static ResultOf::{{ .Name }} {{ .Name }}(
::fidl::UnownedClientEnd<{{ .LLProps.ProtocolName }}> _client_end
{{- .Request | CommaParams }}) {
return ResultOf::{{ .Name }}(_client_end
{{- .Request | CommaParamNames -}}
);
}
{{ "" }}
{{- if or .Request .Response }}
{{- range .DocComments }}
//{{ . }}
{{- end }}
// Caller provides the backing storage for FIDL message via request and response buffers.
static UnownedResultOf::{{ .Name }} {{ .Name }}({{ template "StaticCallSyncRequestCallerAllocateMethodArguments" . }}) {
return UnownedResultOf::{{ .Name }}(_client_end
{{- if .Request -}}
, _request_buffer.data, _request_buffer.capacity
{{- end -}}
{{- .Request | CommaParamNames -}}
{{- if .HasResponse -}}
, _response_buffer.data, _response_buffer.capacity
{{- end -}});
}
{{- end }}
{{ "" }}
{{- end }}
};
class SyncClient final {
public:
SyncClient() = default;
explicit SyncClient(::fidl::ClientEnd<{{ .Name }}> client_end)
: client_end_(std::move(client_end)) {}
~SyncClient() = default;
SyncClient(SyncClient&&) = default;
SyncClient& operator=(SyncClient&&) = default;
const ::fidl::ClientEnd<{{ .Name }}>& client_end() const { return client_end_; }
::fidl::ClientEnd<{{ .Name }}>& client_end() { return client_end_; }
const ::zx::channel& channel() const { return client_end_.channel(); }
::zx::channel* mutable_channel() { return &client_end_.channel(); }
{{ "" }}
{{- /* Client-calling functions do not apply to events. */}}
{{- range .ClientMethods -}}
{{- range .DocComments }}
//{{ . }}
{{- end }}
//{{ template "ClientAllocationComment" . }}
ResultOf::{{ .Name }} {{ .Name }}({{ .Request | Params }}) {
return ResultOf::{{ .Name }}(this->client_end()
{{- .Request | CommaParamNames -}});
}
{{ "" }}
{{- if or .Request .Response }}
{{- range .DocComments }}
//{{ . }}
{{- end }}
// Caller provides the backing storage for FIDL message via request and response buffers.
UnownedResultOf::{{ .Name }} {{ .Name }}({{ template "SyncRequestCallerAllocateMethodArguments" . }}) {
return UnownedResultOf::{{ .Name }}(this->client_end()
{{- if .Request -}}
, _request_buffer.data, _request_buffer.capacity
{{- end -}}
{{- .Request | CommaParamNames -}}
{{- if .HasResponse -}}
, _response_buffer.data, _response_buffer.capacity
{{- end -}});
}
{{- end }}
{{ "" }}
{{- end }}
{{- if .Events }}
// Handle all possible events defined in this protocol.
// Blocks to consume exactly one message from the channel, then call the corresponding virtual
// method defined in |SyncEventHandler|. The return status of the handler function is folded with
// any transport-level errors and returned.
::fidl::Result HandleOneEvent(SyncEventHandler& event_handler) {
return event_handler.HandleOneEvent(client_end_);
}
{{- end }}
private:
::fidl::ClientEnd<{{ .Name }}> client_end_;
};
{{ template "ClientForwardDeclaration" . }}
{{ "" }}
// Pure-virtual interface to be implemented by a server.
// This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
// and |fidl::ServerEnd<SomeProtocol>|).
class Interface : public ::fidl::internal::IncomingMessageDispatcher {
public:
Interface() = default;
virtual ~Interface() = default;
// The marker protocol type within which this |Interface| class is defined.
using _EnclosingProtocol = {{ $protocol.Name }};
{{ "" }}
{{- range .Methods }}
{{- if .HasRequest }}
{{- if .HasResponse }}
class {{ .Name }}CompleterBase : public ::fidl::CompleterBase {
public:
// In the following methods, the return value indicates internal errors during
// the reply, such as encoding or writing to the transport.
// Note that any error will automatically lead to the destruction of the binding,
// after which the |on_unbound| callback will be triggered with a detailed reason.
//
// See //zircon/system/ulib/fidl/include/lib/fidl/llcpp/server.h.
//
// Because the reply status is identical to the unbinding status, it can be safely ignored.
::fidl::Result {{ template "ReplyManagedMethodSignature" . }};
{{- if .Result }}
::fidl::Result {{ template "ReplyManagedResultSuccessMethodSignature" . }};
::fidl::Result {{ template "ReplyManagedResultErrorMethodSignature" . }};
{{- end }}
{{- if .Response }}
::fidl::Result {{ template "ReplyCallerAllocateMethodSignature" . }};
{{- if .Result }}
::fidl::Result {{ template "ReplyCallerAllocateResultSuccessMethodSignature" . }};
{{- end }}
{{- end }}
protected:
using ::fidl::CompleterBase::CompleterBase;
};
using {{ .Name }}Completer = ::fidl::Completer<{{ .Name }}CompleterBase>;
{{- else }}
using {{ .Name }}Completer = ::fidl::Completer<>;
{{- end }}
{{ "" }}
{{- range .DocComments }}
//{{ . }}
{{- end }}
virtual void {{ .Name }}(
{{- .Request | Params }}{{ if .Request }}, {{ end -}}
{{- if .Transitional -}}
{{ .Name }}Completer::Sync& _completer) { _completer.Close(ZX_ERR_NOT_SUPPORTED); }
{{- else -}}
{{ .Name }}Completer::Sync& _completer) = 0;
{{- end }}
{{ "" }}
{{- end }}
{{- end }}
private:
{{- /* Note that this implementation is snake_case to avoid name conflicts. */}}
::fidl::DispatchResult dispatch_message(fidl_incoming_msg_t* msg,
::fidl::Transaction* txn) final;
};
{{ "" }}
{{- if .ShouldEmitTypedChannelCascadingInheritance }}
// Pure-virtual interface to be implemented by a server.
// Implementing this interface is discouraged since it uses raw |zx::channel|s
// instead of |fidl::ClientEnd| and |fidl::ServerEnd|. Consider implementing
// |{{ .Name }}::Interface| instead.
// TODO(fxbug.dev/65212): Remove this interface after all users have
// migrated to the typed channels API.
class FIDL_DEPRECATED_USE_TYPED_CHANNELS RawChannelInterface : public Interface {
public:
RawChannelInterface() = default;
virtual ~RawChannelInterface() = default;
// The marker protocol type within which this |RawChannelInterface| class is defined.
using Interface::_EnclosingProtocol;
{{- range .ClientMethods }}
using Interface::{{ .Name }}Completer;
{{ "" }}
{{- if .ShouldEmitTypedChannelCascadingInheritance }}
virtual void {{ .Name }}(
{{- .Request | Params }}{{ if .Request }}, {{ end -}}
{{ .Name }}Completer::Sync& _completer) final {
{{ .Name }}({{ template "ForwardMessageParamsUnwrapTypedChannels" .Request }}
{{- if .Request }}, {{ end -}} _completer);
}
// TODO(fxbug.dev/65212): Overriding this method is discouraged since it
// uses raw channels instead of |fidl::ClientEnd| and |fidl::ServerEnd|.
// Please move to overriding the typed channel overload above instead.
virtual void {{ .Name }}(
{{- .Request | ParamsNoTypedChannels }}{{ if .Request }}, {{ end -}}
{{- if .Transitional -}}
{{ .Name }}Completer::Sync& _completer) { _completer.Close(ZX_ERR_NOT_SUPPORTED); }
{{- else -}}
{{ .Name }}Completer::Sync& _completer) = 0;
{{- end }}
{{ "" }}
{{- end }}
{{- end }}
};
{{- end }}
// Attempts to dispatch the incoming message to a handler function in the server implementation.
// If there is no matching handler, it returns false, leaving the message and transaction intact.
// In all other cases, it consumes the message and returns true.
// It is possible to chain multiple TryDispatch functions in this manner.
static ::fidl::DispatchResult TryDispatch{{ template "SyncServerDispatchMethodSignature" }};
// Dispatches the incoming message to one of the handlers functions in the protocol.
// If there is no matching handler, it closes all the handles in |msg| and closes the channel with
// a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
static ::fidl::DispatchResult Dispatch{{ template "SyncServerDispatchMethodSignature" }};
// Same as |Dispatch|, but takes a |void*| instead of |Interface*|.
// Only used with |fidl::BindServer| to reduce template expansion.
// Do not call this method manually. Use |Dispatch| instead.
static ::fidl::DispatchResult TypeErasedDispatch(
void* impl, fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
return Dispatch(static_cast<Interface*>(impl), msg, txn);
}
#endif
class EventSender;
class WeakEventSender;
};
{{- end }}
{{- define "ProtocolTraits" -}}
{{ $protocol := . -}}
{{ range .Methods -}}
{{ $method := . -}}
{{- if .HasRequest }}
template <>
struct IsFidlType<{{ $protocol }}::{{ .Name }}Request> : public std::true_type {};
template <>
struct IsFidlMessage<{{ $protocol }}::{{ .Name }}Request> : public std::true_type {};
static_assert(sizeof({{ $protocol }}::{{ .Name }}Request)
== {{ $protocol }}::{{ .Name }}Request::PrimarySize);
{{- range $index, $param := .Request }}
static_assert(offsetof({{ $protocol }}::{{ $method.Name }}Request, {{ $param.Name }}) == {{ $param.Offset }});
{{- end }}
{{- end }}
{{- if .HasResponse }}
template <>
struct IsFidlType<{{ $protocol }}::{{ .Name }}Response> : public std::true_type {};
template <>
struct IsFidlMessage<{{ $protocol }}::{{ .Name }}Response> : public std::true_type {};
static_assert(sizeof({{ $protocol }}::{{ .Name }}Response)
== {{ $protocol }}::{{ .Name }}Response::PrimarySize);
{{- range $index, $param := .Response }}
static_assert(offsetof({{ $protocol }}::{{ $method.Name }}Response, {{ $param.Name }}) == {{ $param.Offset }});
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- define "ProtocolDefinition" }}
{{ EnsureNamespace . }}
namespace {
{{ $protocol := . -}}
{{- range .Methods }}
[[maybe_unused]]
constexpr uint64_t {{ .OrdinalName }} = {{ .Ordinal }}lu; {{/* TODO: Make a DeclName for OrdinalName */}}
{{ EnsureNamespace .RequestCodingTable }}
extern "C" const fidl_type_t {{ .RequestCodingTable.Name }};
{{ EnsureNamespace .ResponseCodingTable }}
extern "C" const fidl_type_t {{ .ResponseCodingTable.Name }};
{{- end }}
} // namespace
{{- /* Client-calling functions do not apply to events. */}}
{{- range .ClientMethods -}}
{{ "" }}
{{- template "SyncRequestManagedMethodDefinition" . }}
{{- if or .Request .Response }}
{{ "" }}
{{- template "SyncRequestCallerAllocateMethodDefinition" . }}
{{- end }}
{{ "" }}
{{- end }}
{{- range .ClientMethods }}
{{ "" }}
{{- template "ClientSyncRequestManagedMethodDefinition" . }}
{{- if or .Request .Response }}
{{ "" }}
{{- template "ClientSyncRequestCallerAllocateMethodDefinition" . }}
{{- end }}
{{- if .HasResponse }}
{{ "" }}
{{- template "ClientAsyncRequestManagedMethodDefinition" . }}
{{- end }}
{{- end }}
{{ template "ClientDispatchDefinition" . }}
{{ "" }}
{{- if .Events }}
{{- template "EventHandlerHandleOneEventMethodDefinition" . }}
{{- end }}
{{- /* Server implementation */}}
{{ template "SyncServerTryDispatchMethodDefinition" . }}
{{ template "SyncServerDispatchMethodDefinition" . }}
{{- if .Methods }}
{{ "" }}
{{- range .TwoWayMethods -}}
{{ "" }}
{{- template "ReplyManagedMethodDefinition" . }}
{{- if .Result }}
{{- template "ReplyManagedResultSuccessMethodDefinition" . }}
{{- template "ReplyManagedResultErrorMethodDefinition" . }}
{{- end }}
{{- if .Response }}
{{ "" }}
{{- template "ReplyCallerAllocateMethodDefinition" . }}
{{- if .Result }}
{{- template "ReplyCallerAllocateResultSuccessMethodDefinition" . }}
{{- end }}
{{- end }}
{{ "" }}
{{- end }}
{{ "" }}
{{- range .Methods }}
{{ "" }}
{{- if .HasRequest }}
{{ "" }}
void {{ .LLProps.ProtocolName }}::{{ .Name }}Request::_InitHeader(zx_txid_t _txid) {
fidl_init_txn_header(&_hdr, _txid, {{ .OrdinalName }});
}
{{- if .RequestIsResource }}
void {{ .LLProps.ProtocolName }}::{{ .Name }}Request::_CloseHandles() {
{{- range .Request }}
{{- CloseHandles . false false }}
{{- end }}
}
{{- end }}
{{- end }}
{{- if .HasResponse }}
{{ "" }}
void {{ .LLProps.ProtocolName }}::{{ .Name }}Response::_InitHeader() {
fidl_init_txn_header(&_hdr, 0, {{ .OrdinalName }});
}
{{- if .ResponseIsResource }}
void {{ .LLProps.ProtocolName }}::{{ .Name }}Response::_CloseHandles() {
{{- range .Response }}
{{- CloseHandles . false false }}
{{- end }}
}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
`