| {{/* |
| // Copyright 2021 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 "Method:UnownedResult:WireMessagingHeader" }} |
| {{- 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 "::fidl::internal::AnyBufferAllocator& allocator") }} |
| {{- $args = (List $args (printf "%s* request" .WireTransactionalRequest)) }} |
| explicit {{ .WireUnownedResult.Self }}({{ RenderParams $args }}); |
| {{- end }} |
| |
| {{- if .HasResponse }} |
| explicit {{ .WireUnownedResult.Self }}({{ .WireTransactionalResponse }}* response) |
| : fidl::Status(fidl::Status::Ok()), decoded_(response) { |
| {{- if .HasApplicationError }} |
| auto* raw_response = &decoded_.Value()->body; |
| 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 }} |
| } |
| |
| explicit {{ .WireUnownedResult.Self }}( |
| ::fidl::unstable::DecodedMessage<{{ .WireTransactionalResponse }}>&& decoded, |
| ::fidl::internal::MessageStorageViewBase* storage_view |
| ) : fidl::Status(decoded) { |
| if (decoded.ok()) { |
| decoded_ = decoded.Take(); |
| {{- if .HasApplicationError }} |
| auto* raw_response = &decoded_.Value()->body; |
| 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 }} |
| } |
| } |
| {{- end }} |
| |
| explicit {{ .WireUnownedResult.Self }}(const ::fidl::Status& result) : ::fidl::Status(result) {} |
| {{ .WireUnownedResult.Self }}({{ .WireUnownedResult.Self }}&&) = delete; |
| {{ .WireUnownedResult.Self }}(const {{ .WireUnownedResult.Self }}&) = delete; |
| {{ .WireUnownedResult.Self }}& operator=({{ .WireUnownedResult.Self }}&&) = delete; |
| {{ .WireUnownedResult.Self }}& operator=(const {{ .WireUnownedResult.Self }}&) = delete; |
| ~{{ .WireUnownedResult.Self }}() = default; |
| |
| {{- if .HasWireResultBase }} |
| {{ .WireResultBase }}* Unwrap() { |
| {{- if .Result }} |
| return &result_.value(); |
| {{- else }} |
| ZX_ASSERT(ok()); |
| return &decoded_.Value()->body; |
| {{- end }} |
| } |
| const {{ .WireResultBase }}* Unwrap() const { |
| {{- if .Result }} |
| return &result_.value(); |
| {{- else }} |
| ZX_ASSERT(ok()); |
| return &decoded_.Value()->body; |
| {{- end }} |
| } |
| |
| {{ .WireResultBase }}& value() { return *Unwrap(); } |
| const {{ .WireResultBase }}& value() const { return *Unwrap(); } |
| |
| {{ .WireResultBase }}* operator->() { return &value(); } |
| const {{ .WireResultBase }}* operator->() const { return &value(); } |
| |
| {{ .WireResultBase }}& operator*() { return value(); } |
| const {{ .WireResultBase }}& operator*() const { return value(); } |
| {{- end }} |
| |
| {{- if .HasResponse }} |
| private: |
| ::fidl::internal::DecodedValue<{{ .WireTransactionalResponse }}> decoded_; |
| {{- if and .Result .HasWireResultBase }} |
| std::optional<{{ .WireResultBase }}> result_ = std::nullopt; |
| {{- end }} |
| {{- end }} |
| }; |
| |
| {{- end }} |
| |
| |
| |
| {{- define "Method:UnownedResult:WireMessagingSource" }} |
| {{- if .Transport.HasSyncClient }} |
| {{- IfdefFuchsia -}} |
| {{- EnsureNamespace "" }} |
| {{- $args := (printf "::%s::UnownedClientEnd<%s> client_end" .Transport.Namespace .Protocol) }} |
| {{- $args = (List $args "::fidl::internal::AnyBufferAllocator& allocator") }} |
| {{- $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. */ -}} |
| |
| {{/* Allocate one buffer for both request/response (if applicable). */ -}} |
| constexpr uint32_t buffer_size = ::fidl::SyncClientMethodBufferSizeInChannel<{{ .Marker }}>(); |
| ::fitx::result<::fidl::Error, ::fidl::BufferSpan> allocation = allocator.TryAllocate(buffer_size); |
| if (!allocation.is_ok()) { |
| SetStatus(allocation.error_value()); |
| return; |
| } |
| uint8_t* buffer = allocation->data; |
| |
| {{- if .HasResponse -}} |
| {{/* TODO(fxbug.dev/85843): We should be able optimize this to just the max of |
| the send/receive size, once Zircon channel calls guarantee that the |
| send/receive buffers can overlap. |
| |
| For now, the invariant of SyncClientMethodBufferSizeInChannel is that it returns |
| the sum of the request/response size, so we can index into it and get the |
| address of the response buffer. */ -}} |
| constexpr uint32_t request_byte_capacity = ::fidl::MaxSizeInChannel< |
| {{ .WireTransactionalRequest }}, ::fidl::MessageDirection::kSending>(); |
| uint8_t* request_bytes = buffer; |
| static_assert(buffer_size > request_byte_capacity); |
| uint32_t response_byte_capacity = buffer_size - request_byte_capacity; |
| uint8_t* response_bytes = &buffer[request_byte_capacity]; |
| {{- else }} |
| uint32_t request_byte_capacity = buffer_size; |
| uint8_t* request_bytes = buffer; |
| {{- end }} |
| |
| ::fidl::unstable::UnownedEncodedMessage<{{ .WireTransactionalRequest }}> request_message( |
| request_bytes, request_byte_capacity, request); |
| auto& outgoing = request_message.GetOutgoingMessage(); |
| |
| {{- if .HasResponse }} |
| {{ .IncomingMessageHandleStorageForResponse }} handle_storage; |
| ::fidl::unstable::DecodedMessage<{{ .WireTransactionalResponse }}> decoded{ |
| outgoing.Call( |
| client_end.handle(), |
| handle_storage.view(fidl::BufferSpan(response_bytes, response_byte_capacity)) |
| ) |
| }; |
| SetStatus(decoded); |
| if (ok()) { |
| decoded_ = decoded.Take(); |
| } |
| |
| {{- if .HasApplicationError }} |
| if (ok()) { |
| auto* raw_response = &decoded_.Value()->body; |
| 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 }} |
| outgoing.Write(client_end.handle()); |
| SetStatus(outgoing); |
| {{- end }} |
| } |
| |
| {{- EndifFuchsia -}} |
| {{- end }} |
| {{- end }} |