{{/*
// 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:CompleterBase:WireMessagingHeader" }}
{{ EnsureNamespace "" }}
template<>
class {{ .WireCompleterImpl }} : public ::fidl::internal::CompleterImplBase<{{ .Marker }}> {
 public:
  using CompleterImplBase::CompleterImplBase;

  void Reply({{ RenderParams .ResponseArgs }});

  {{- if .Result }}
  void ReplySuccess({{ RenderParams .Result.ValueParameters }});
  void ReplyError({{ .Result.ErrorDecl }} error);
  {{- end }}
};

template <>
class {{ .WireBufferCompleterImpl }} : public ::fidl::internal::BufferCompleterImplBase {
 public:
  using BufferCompleterImplBase::BufferCompleterImplBase;

  void Reply({{ RenderParams .ResponseArgs }});

  {{- if .Result }}
  void ReplySuccess({{ RenderParams .Result.ValueParameters }});
  void ReplyError({{ .Result.ErrorDecl }} error);
  {{- end }}
};

template<>
class {{ .WireCompleterBase }} : public ::fidl::CompleterBase, public {{ .WireCompleterImpl }} {
 public:
  {{ .WireCompleterBase.Self }}(::fidl::Transaction* transaction, bool owned, bool expects_reply)
      : CompleterBase(transaction, owned, expects_reply),
        {{ .WireCompleterImpl.Self }}(this) {}

  {{- /* Update `this` pointer after moving the completer. */}}
  {{ .WireCompleterBase.Self }}({{ .WireCompleterBase.Self }}&& other) noexcept
      : CompleterBase(std::move(other)), {{ .WireCompleterImpl.Self }}(this) {}
  {{ .WireCompleterBase.Self }}& operator=({{ .WireCompleterBase.Self }}&& other) noexcept {
    CompleterBase::operator=(std::move(other));
    {{ .WireCompleterImpl.Self }}::_set_core(this);
    return *this;
  }
};

{{- end }}



{{- define "Method:CompleterBase:WireMessagingSource" }}
{{ EnsureNamespace "" }}
{{- IfdefFuchsia -}}

void
{{ .WireCompleterImpl.NoLeading }}::Reply({{ RenderParams .ResponseArgs }}) {
  {{ .WireTransactionalResponse }} _response{ {{ RenderForwardParams .ResponseArgs }} };
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::unstable::OwnedEncodedMessage<
      {{ .WireTransactionalResponse }}, {{ .Transport.Type }}> _response_message{
      ::fidl::internal::AllowUnownedInputRef{}, &_response};
  return _core()->SendReply(&_response_message.GetOutgoingMessage(),
                            ::fidl::internal::OutgoingTransportContext());
}

{{- if .Result }}
  void
  {{ .WireCompleterImpl.NoLeading }}::ReplySuccess({{ RenderParams .Result.ValueParameters }}) {
    {{ .Result.BuildPayload "_response" -}}

    {{- if .Result.Value.InlineInEnvelope }}
    return Reply({{ .Result.ResultDecl }}::WithResponse(std::move(_response)));
    {{- else }}
    return Reply({{ .Result.ResultDecl }}::WithResponse(
        ::fidl::ObjectView<{{ .Result.ValueTypeDecl }}>::FromExternal(&_response)));
    {{- end }}
  }

  void
  {{ .WireCompleterImpl.NoLeading }}::ReplyError({{ .Result.ErrorDecl }} error) {
    {{- if .Result.Error.InlineInEnvelope }}
    return Reply({{ .Result.ResultDecl }}::WithErr(std::move(error)));
    {{- else }}
    return Reply({{ .Result.ResultDecl }}::WithErr(
        ::fidl::ObjectView<{{ .Result.ErrorDecl }}>::FromExternal(&error)));
    {{- end }}
  }
{{- end }}


void
{{ .WireBufferCompleterImpl.NoLeading }}::Reply({{ RenderParams .ResponseArgs }}) {
  {{ .WireTransactionalResponse }} _response{ {{ RenderForwardParams .ResponseArgs }} };
  constexpr uint32_t _buffer_size = ::fidl::ServerReplyBufferSizeInChannel<{{ .Marker }}>();
  ::fitx::result<::fidl::Error, ::fidl::BufferSpan> _allocation =
      _allocator().TryAllocate(_buffer_size);
  if (!_allocation.is_ok()) {
    ::fidl::OutgoingMessage _failure{_allocation.error_value()};
    return _core()->SendReply(&_failure, ::fidl::internal::OutgoingTransportContext());
  }
  ::fidl::unstable::UnownedEncodedMessage<
      {{ .WireTransactionalResponse }}, {{ .Transport.Type }}> _response_message(
      _allocation->data, _buffer_size, &_response);
  return _core()->SendReply(&_response_message.GetOutgoingMessage(),
                            ::fidl::internal::OutgoingTransportContext());
}

{{- if .Result }}
  void
  {{ .WireBufferCompleterImpl.NoLeading }}::ReplySuccess({{ RenderParams .Result.ValueParameters }}) {
    {{ .Result.BuildPayload "_response" -}}

    {{- if .Result.Value.InlineInEnvelope }}
    return Reply({{ .Result.ResultDecl }}::WithResponse(std::move(_response)));
    {{- else }}
    return Reply({{ .Result.ResultDecl }}::WithResponse(
        ::fidl::ObjectView<{{ .Result.ValueTypeDecl }}>::FromExternal(&_response)));
    {{- end }}
  }

  void
  {{ .WireBufferCompleterImpl.NoLeading }}::ReplyError({{ .Result.ErrorDecl }} error) {
    {{- if .Result.Error.InlineInEnvelope }}
    return Reply({{ .Result.ResultDecl }}::WithErr(std::move(error)));
    {{- else }}
    return Reply({{ .Result.ResultDecl }}::WithErr(
        ::fidl::ObjectView<{{ .Result.ErrorDecl }}>::FromExternal(&error)));
    {{- end }}
  }
{{- end }}


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



{{- define "Method:NaturalReplySignature:Helper" -}}
{{- /* TODO(fxbug.dev/60240): Use `const T&` for value types. */}}
{{- if .HasResponsePayload }}{{ .NaturalResponse }}&& response{{ end }}
{{- end }}



{{- define "Method:CompleterBase:NaturalMessagingHeader" }}
{{ EnsureNamespace "" }}
template<>
class {{ .NaturalCompleterBase }} : public ::fidl::CompleterBase {
 public:
  void Reply({{ template "Method:NaturalReplySignature:Helper" . }});

 protected:
  using ::fidl::CompleterBase::CompleterBase;
};

{{- end }}



{{- define "Method:CompleterBase:NaturalMessagingSource" }}
{{ EnsureNamespace "" }}
void {{ .NaturalCompleterBase.NoLeading }}::Reply(
    {{- template "Method:NaturalReplySignature:Helper" . }}) {
  ::fidl::internal::NaturalMessageEncoder _encoder{
      &::fidl::internal::ChannelTransport::VTable, {{ .OrdinalName }}, {{ .DynamicFlagsName }} };
  {{- if .HasResponsePayload }}
  _encoder.EncodeBody(
      {{ .NaturalResponseConverter }}::IntoDomainObject(std::move(response)));
  {{- end }}
  ::fidl::OutgoingMessage _encoded_message = _encoder.GetMessage();
  SendReply(&_encoded_message, ::fidl::internal::OutgoingTransportContext{});
}
{{- end }}
