blob: 9c042a06412ac71788955f6864d89a165af7a0e3 [file] [log] [blame]
{{/*
// Copyright 2022 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.
*/}}
{{- define "driver/Method:UnownedResult:MessagingHeader" }}
{{- EnsureNamespace "" }}
template<>
class [[nodiscard]] {{ .WireUnownedResult }} final : public ::fidl::Status {
public:
{{- if .Transport.HasSyncClient }}
{{- $args := (printf "::%s::UnownedClientEnd<%s> client_end" .Transport.Namespace .Protocol) }}
{{- $args = (List $args "const ::fdf::Arena& arena") }}
{{- $args = (List $args (printf "%s* request" .WireTransactionalRequest)) }}
explicit {{ .WireUnownedResult.Self }}({{ RenderParams $args }});
{{- end }}
{{- if .HasResponse }}
explicit {{ .WireUnownedResult.Self }}({{ .WireTransactionalResponse }}* response)
: bytes_(reinterpret_cast<uint8_t*>(response)) {
{{- if .Result }}
auto* raw_response = reinterpret_cast<{{ .WireResponse }} *>(
bytes_ + sizeof(fidl_message_header_t));
if (raw_response->result.is_err()) {
result_ = fitx::error(raw_response->result.err());
} else {
result_ = fitx::ok({{ if .Result.ValueParameters }}&(raw_response->result.response()){{ end }});
}
{{- end }}
}
{{- end }}
explicit {{ .WireUnownedResult.Self }}(const ::fidl::Status& result) : ::fidl::Status(result) {}
{{- if .HasResponse }}
explicit {{ .WireUnownedResult.Self }}(
::fidl::unstable::DecodedMessage<{{ .WireTransactionalResponse }}>&& decoded,
::fidl::internal::IncomingTransportContext context)
: ::fidl::Status(decoded), arena_(context.release<::fidl::internal::DriverTransport>())
{
if (decoded.ok()) {
bytes_ = reinterpret_cast<uint8_t*>(decoded.PrimaryObject());
{{- if .Result }}
auto* raw_response = reinterpret_cast<{{ .WireResponse }} *>(
bytes_ + sizeof(fidl_message_header_t));
if (raw_response->result.is_err()) {
result_ = fitx::error(raw_response->result.err());
} else if (raw_response->result.is_response()) {
result_ = fitx::ok(
{{- if .Result.ValueParameters -}}
&(raw_response->result.response())
{{- end -}}
);
}
{{- end }}
} else {
bytes_ = nullptr;
}
decoded.ReleasePrimaryObject();
}
{{- end }}
{{ .WireUnownedResult.Self }}({{ .WireUnownedResult.Self }}&&) = delete;
{{ .WireUnownedResult.Self }}(const {{ .WireUnownedResult.Self }}&) = delete;
{{ .WireUnownedResult.Self }}* operator=({{ .WireUnownedResult.Self }}&&) = delete;
{{ .WireUnownedResult.Self }}* operator=(const {{ .WireUnownedResult.Self }}&) = delete;
{{- if and .HasResponse .Response.IsResource }}
~{{ .WireUnownedResult.Self }}() {
if (ok()) {
Unwrap()->_CloseHandles();
}
}
{{- else }}
~{{ .WireUnownedResult.Self }}() = default;
{{- end }}
{{- if .HasResponse }}
{{- if .ResponseArgs }}
{{ .WireResponse }}* Unwrap() {
ZX_DEBUG_ASSERT(ok());
return &(reinterpret_cast<{{ .WireTransactionalResponse }}*>(bytes_)->body);
}
const {{ .WireResponse }}* Unwrap() const {
ZX_DEBUG_ASSERT(ok());
return &(reinterpret_cast<const {{ .WireTransactionalResponse }}*>(bytes_)->body);
}
{{ .WireResultBase }}* Unwrap_NEW() {
{{- if .Result }}
return &result_.value();
{{- else }}
ZX_DEBUG_ASSERT(ok());
return &(reinterpret_cast<{{ .WireTransactionalResponse }}*>(bytes_)->body);
{{- end }}
}
const {{ .WireResultBase }}* Unwrap_NEW() const {
{{- if .Result }}
return &result_.value();
{{- else }}
ZX_DEBUG_ASSERT(ok());
return &(reinterpret_cast<const {{ .WireTransactionalResponse }}*>(bytes_)->body);
{{- end }}
}
{{ .WireResponse }}& value() { return *Unwrap(); }
const {{ .WireResponse }}& value() const { return *Unwrap(); }
{{ .WireResultBase }}& value_NEW() { return *Unwrap_NEW(); }
const {{ .WireResultBase }}& value_NEW() const { return *Unwrap_NEW(); }
{{ .WireResponse }}* operator->() { return &value(); }
const {{ .WireResponse }}* operator->() const { return &value(); }
{{ .WireResponse }}& operator*() { return value(); }
const {{ .WireResponse }}& operator*() const { return value(); }
{{- end }}
fdf::Arena& arena() {
ZX_DEBUG_ASSERT(ok());
return arena_;
}
private:
uint8_t* bytes_;
fdf::Arena arena_;
{{- if .Result }}
std::optional<{{ .WireResultBase }}> result_ = std::nullopt;
{{- end }}
{{- end }}
};
{{- end }}
{{- define "driver/Method:UnownedResult:MessagingSource" }}
{{- if .Transport.HasSyncClient }}
{{- IfdefFuchsia -}}
{{- EnsureNamespace "" }}
{{- $args := (printf "::%s::UnownedClientEnd<%s> client_end" .Transport.Namespace .Protocol) }}
{{- $args = (List $args "const ::fdf::Arena& arena") }}
{{- $args = (List $args (printf "%s* request" .WireTransactionalRequest)) }}
{{ .WireUnownedResult }}::{{ .WireUnownedResult.Self }}({{ RenderParams $args }}) {
{{/* TODO(fxbug.dev/86367): Factor out common buffer allocation logic once we have other instances
of this pattern. */ -}}
constexpr uint32_t buffer_size =
::fidl::MaxSizeInChannel<{{ .WireTransactionalRequest }}, ::fidl::MessageDirection::kSending>();
uint8_t* buffer = static_cast<uint8_t*>(arena.Allocate(buffer_size));
::fidl::unstable::UnownedEncodedMessage<{{ .WireTransactionalRequest }}, fidl::internal::DriverTransport> request_message(
buffer, buffer_size, request);
auto& outgoing = request_message.GetOutgoingMessage();
{{- if .HasResponse }}
::fidl::internal::IncomingTransportContext incoming_context;
::fidl::CallOptions call_options = {
.outgoing_transport_context =
::fidl::internal::OutgoingTransportContext::Create<fidl::internal::DriverTransport>(
arena.get()),
.out_incoming_transport_context = &incoming_context,
};
uint32_t call_result_num_bytes;
outgoing.Call<{{ .WireTransactionalResponse }}>(
client_end.handle(), &bytes_, &call_result_num_bytes, std::move(call_options));
arena_ = fdf::Arena(incoming_context.release<fidl::internal::DriverTransport>());
{{- if .Result }}
if (outgoing.ok()) {
auto* raw_response = reinterpret_cast<{{ .WireResponse }} *>(
bytes_ + sizeof(fidl_message_header_t));
if (raw_response->result.is_err()) {
result_ = fitx::error(raw_response->result.err());
} else if (raw_response->result.is_response()) {
result_ = fitx::ok(
{{- if .Result.ValueParameters -}}
&(raw_response->result.response())
{{- end -}}
);
}
}
{{- end }}
{{- else }}
::fidl::WriteOptions write_options = {
.outgoing_transport_context =
::fidl::internal::OutgoingTransportContext::Create<fidl::internal::DriverTransport>(
arena.get()),
};
outgoing.Write(client_end.handle(), std::move(write_options));
{{- end }}
::fidl::Status::operator=(outgoing);
}
{{- EndifFuchsia -}}
{{- end }}
{{- end }}