{{/*
// Copyright 2020 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:EventSender:WireMessagingHeader" }}
{{ EnsureNamespace "" }}
{{- IfdefFuchsia -}}
template<>
class {{ .WireWeakEventSender }} : public ::fidl::internal::WeakEventSenderBase {
 public:
  using WeakEventSenderBase::WeakEventSenderBase;
{{ "" }}

  {{- range .Events }}
    {{- .Docs }}
    fidl::Status {{ .Name }}({{ RenderParams .ResponseArgs }});

{{ "" }}
  {{- end }}
};

template<>
class {{ .WireWeakBufferEventSender }} : public ::fidl::internal::WeakBufferEventSenderBase {
 public:
  using WeakBufferEventSenderBase::WeakBufferEventSenderBase;
{{ "" }}

  {{- range .Events }}
    {{- .Docs }}
    fidl::Status {{ .Name }}({{ RenderParams .ResponseArgs }});

{{ "" }}
  {{- end }}
};

template<>
class {{ .WireEventSender }}
    : public ::fidl::internal::SyncEndpointManagedVeneer<{{ .WireEventSender }}> {
 public:
  using SyncEndpointManagedVeneer::SyncEndpointManagedVeneer;
{{ "" }}

  {{- range .Events }}
    {{- .Docs }}
    fidl::Status {{ .Name }}({{ RenderParams .ResponseArgs }});

{{ "" }}
  {{- end }}
};

template<>
class {{ .InternalWireBufferEventSender }}
    : public ::fidl::internal::SyncEndpointBufferVeneer<{{ .InternalWireBufferEventSender }}> {
 public:
  using SyncEndpointBufferVeneer::SyncEndpointBufferVeneer;
{{ "" }}

  {{- range .Events }}
    {{- .Docs }}
    fidl::Status {{ .Name }}({{ RenderParams .ResponseArgs }});

{{ "" }}
  {{- end }}
};

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

{{- define "Protocol:EventSender:WireMessagingSource" }}
{{ EnsureNamespace "" }}
{{- IfdefFuchsia -}}
  {{- range .Events }}

    {{- /* Weak, managed */}}
fidl::Status {{ $.WireWeakEventSender.NoLeading }}::{{ .Name }}(
    {{- RenderParams .ResponseArgs }}) {
  {{ .WireTransactionalEvent }} _response{ {{- RenderForwardParams .ResponseArgs }} };
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::unstable::OwnedEncodedMessage<{{ .WireTransactionalEvent }}, {{ .Transport.Type }}> _response_message{
      ::fidl::internal::AllowUnownedInputRef{}, &_response
  };
  return _inner().SendEvent(_response_message.GetOutgoingMessage());
}

    {{- /* Weak, caller-allocated */}}
{{ "" }}
fidl::Status {{ $.WireWeakBufferEventSender.NoLeading }}::{{ .Name }}(
    {{- RenderParams .ResponseArgs }}) {
  constexpr uint32_t _buffer_size = ::fidl::EventReplyBufferSizeInChannel<{{ .Marker }}>();
  ::fitx::result<::fidl::Error, ::fidl::BufferSpan> _allocation =
      _allocator().TryAllocate(_buffer_size);
  if (!_allocation.is_ok()) {
    _inner().HandleSendError(_allocation.error_value());
    return _allocation.error_value();
  }

  {{ .WireTransactionalEvent }} _response{ {{- RenderForwardParams .ResponseArgs }} };
  ::fidl::unstable::UnownedEncodedMessage<{{ .WireTransactionalEvent }}, {{ .Transport.Type }}> _response_message(
      _allocation->data, _buffer_size, &_response);
  return _inner().SendEvent(_response_message.GetOutgoingMessage());
}
{{ "" }}

    {{- /* Managed */}}
fidl::Status {{ $.WireEventSender.NoLeading }}::{{ .Name }}(
    {{- RenderParams .ResponseArgs }}) {
  {{ .WireTransactionalEvent }} _response{ {{- RenderForwardParams .ResponseArgs }} };
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::unstable::OwnedEncodedMessage<{{ .WireTransactionalEvent }}, {{ .Transport.Type }}> _response_message{
      ::fidl::internal::AllowUnownedInputRef{}, &_response
  };
  auto& _message = _response_message.GetOutgoingMessage();
  _message.Write(_transport());
  return ::fidl::Status{_message};
}

    {{- /* Caller-allocated */}}
{{ "" }}
fidl::Status {{ $.InternalWireBufferEventSender.NoLeading }}::{{ .Name }}(
    {{- RenderParams .ResponseArgs }}) {
  constexpr uint32_t _buffer_size = ::fidl::EventReplyBufferSizeInChannel<{{ .Marker }}>();
  ::fitx::result<::fidl::Error, ::fidl::BufferSpan> _allocation =
      _allocator().TryAllocate(_buffer_size);
  if (!_allocation.is_ok()) {
    return _allocation.error_value();
  }

  {{ .WireTransactionalEvent }} _response{ {{- RenderForwardParams .ResponseArgs }} };
  ::fidl::unstable::UnownedEncodedMessage<{{ .WireTransactionalEvent }}, {{ .Transport.Type }}> _response_message(
        _allocation->data, _buffer_size, &_response);
  auto& _message = _response_message.GetOutgoingMessage();
  _message.Write(_transport());
  return ::fidl::Status{_message};
}
{{ "" }}

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



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

template<>
class {{ .NaturalWeakEventSender }} : public ::fidl::internal::WeakEventSenderBase {
 public:
  using WeakEventSenderBase::WeakEventSenderBase;
{{ "" }}

  {{- range .Events }}
    {{- .Docs }}
    ::fitx::result<::fidl::Error> {{ .Name }}(
        {{- if .HasResponsePayload }}{{ .ResponsePayload }} payload{{ end }});

  {{ end }}
};

template<>
class {{ .NaturalEventSender }}
    : public ::fidl::internal::SyncEndpointManagedVeneer<{{ .NaturalEventSender }}> {
 public:
  using SyncEndpointManagedVeneer::SyncEndpointManagedVeneer;
{{ "" }}

  {{- range .Events }}
    {{- .Docs }}
    ::fitx::result<::fidl::Error> {{ .Name }}(
        {{- if .HasResponsePayload }}{{ .ResponsePayload }} payload{{ end }});

  {{ end }}
};

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



{{- define "Protocol:EventSender:NaturalMessagingSource" }}
{{ EnsureNamespace "" }}
{{- IfdefFuchsia -}}
  {{- range .Events }}

::fitx::result<::fidl::Error> {{ $.NaturalWeakEventSender.NoLeading }}::{{ .Name }}(
    {{- if .HasResponsePayload }}{{ .ResponsePayload }} payload{{ end }}) {
  ::fidl::internal::NaturalMessageEncoder _encoder{
      &::fidl::internal::ChannelTransport::VTable, {{ .OrdinalName }}, {{ .DynamicFlagsName }} };
  {{- if .HasResponsePayload }}
  _encoder.EncodeBody(std::move(payload));
  {{- end }}
  ::fidl::OutgoingMessage _encoded_message = _encoder.GetMessage();
  ::fidl::Status result = _inner().SendEvent(_encoded_message);
  return ::fidl::internal::ToFitxResult(result);
}

::fitx::result<::fidl::Error> {{ $.NaturalEventSender.NoLeading }}::{{ .Name }}(
    {{- if .HasResponsePayload }}{{ .ResponsePayload }} payload{{ end }}) {
  ::fidl::internal::NaturalMessageEncoder _encoder{
      &::fidl::internal::ChannelTransport::VTable, {{ .OrdinalName }}, {{ .DynamicFlagsName }} };
  {{- if .HasResponsePayload }}
  _encoder.EncodeBody(std::move(payload));
  {{- end }}
  ::fidl::OutgoingMessage _encoded_message = _encoder.GetMessage();
  _encoded_message.Write(_transport());
  return ::fidl::internal::ToFitxResult(::fidl::Status{_encoded_message});
}

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