{{/*
// 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 "Protocol:Caller:WireMessagingHeader" }}
{{- EnsureNamespace "" }}

// Methods to make a sync FIDL call directly on an unowned handle or a
// const reference to a |{{ .ClientEnd }}|,
// avoiding setting up a client.
template<>
class {{ .WireSyncClientImpl }} final :
    public ::fidl::internal::SyncEndpointManagedVeneer<{{ .WireSyncClientImpl }}> {
 public:
  {{ range .ClientMethods }}
    {{- .Docs }}
    {{- if .DocComments }}
    //
    {{- end }}
    // {{- template "Method:ClientAllocationComment:Helper" . }}
    {{ if .HasResponse }}{{ .WireResult }}{{ else }}::fidl::OneWayStatus{{ end }}
    {{ .Name }}({{- RenderParams .RequestArgs }}) {
      {{ .WireTransactionalRequest }} _request{ {{ RenderForwardParams .RequestArgs }} };
      return {{ .WireResult }}(_client_end(), &_request);
    }
{{ "" }}
  {{- end }}

 private:
  {{ .UnownedClientEnd }} _client_end() const {
    return {{ .UnownedClientEnd }}(
      _transport().get<{{ .Transport.Type }}>());
  }
};

template <>
class {{ .WireSyncBufferClientImpl }} final :
    public ::fidl::internal::SyncEndpointBufferVeneer<{{ .WireSyncBufferClientImpl }}> {
 public:
  {{ range .ClientMethods }}
    {{- .Docs }}
    // Caller provides the backing storage for FIDL message via an argument to `.buffer()`.
    {{ if .HasResponse }}{{ .WireUnownedResult }}{{ else }}::fidl::OneWayStatus{{ end }}
    {{ .Name }}({{ RenderParams .RequestArgs }}) {
      {{ .WireTransactionalRequest }} _request{ {{ RenderForwardParams .RequestArgs }} };
      return {{ .WireUnownedResult }}(_client_end(), _allocator(), &_request);
    }
{{ "" }}
  {{- end }}

 private:
  {{ .UnownedClientEnd }} _client_end() const {
    return {{ .UnownedClientEnd }}(
      _transport().get<{{ .Transport.Type }}>());
  }
};
{{- end }}



{{- define "Protocol:Caller:NaturalMessagingHeader" }}
{{- EnsureNamespace "" }}
{{- IfdefFuchsia }}

template <>
class {{ .NaturalSyncClientImpl }} final
    : public ::fidl::internal::SyncEndpointManagedVeneer<{{ .NaturalSyncClientImpl }}> {
 public:
  {{ range .TwoWayMethods }}
    {{ .Docs }}
    {{ .NaturalResult }} {{ .Name }}({{ .NaturalRequestArg "request" }});

  {{ end }}

  {{ range .OneWayMethods }}
    {{ .Docs }}
    ::fit::result<::fidl::OneWayError> {{ .Name }}({{ .NaturalRequestArg "request" }});

  {{ end }}

 private:
  {{ .UnownedClientEnd }} _client_end() const {
    return {{ .UnownedClientEnd }}(
      _transport().get<{{ .Transport.Type }}>());
  }
};

{{- EndifFuchsia }}
{{- end }}



{{- define "Protocol:Caller:NaturalMessagingSource" }}
{{- EnsureNamespace "" }}
{{- IfdefFuchsia }}

{{ range .TwoWayMethods }}
  {{ .NaturalResult }}
  {{ $.NaturalSyncClientImpl.NoLeading }}::{{ .Name }}({{ .NaturalRequestArg "request" }}) {
    ::fidl::internal::NaturalMessageEncoder encoder{
        &::fidl::internal::ChannelTransport::VTable, {{ .OrdinalName }}, {{ .DynamicFlagsName }} };
    {{- if .HasRequestPayload }}
    encoder.EncodeBody({{ .Request.Forward "request" }});
    {{- end }}
    ::fidl::OutgoingMessage msg = encoder.GetMessage();
    {{ .IncomingMessageStorageForResponse }} response_storage;
    return ::fidl::internal::DecodeResponseAndFoldError<{{ .Marker }}>(
        msg.Call(_client_end().handle(), response_storage.view()), nullptr);
  }

{{ end }}

{{ range .OneWayMethods }}
  ::fit::result<::fidl::OneWayError>
  {{ $.NaturalSyncClientImpl.NoLeading }}::{{ .Name }}({{ .NaturalRequestArg "request" }}) {
    ::fidl::internal::NaturalMessageEncoder encoder{
        &::fidl::internal::ChannelTransport::VTable, {{ .OrdinalName }}, {{ .DynamicFlagsName }} };
    {{- if .HasRequestPayload }}
    encoder.EncodeBody({{ .Request.Forward "request" }});
    {{- end }}
    ::fidl::OutgoingMessage msg = encoder.GetMessage();
    msg.Write(_client_end().handle());
    return ::fidl::internal::ToFitxResult(::fidl::OneWayStatus{msg});
  }

{{ end }}

{{- EndifFuchsia }}
{{- end }}
