@*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * license agreements; and to You under the Apache License, version 2.0:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * This file is part of the Apache Pekko project, which was derived from Akka.
 *@

@*
 * Copyright (C) 2018-2021 Lightbend Inc. <https://www.lightbend.com>
 *@

@(service: org.apache.pekko.grpc.gen.scaladsl.Service)

@org.apache.pekko.grpc.gen.Constants.DoNotEditComment
package @service.packageName

import scala.concurrent.ExecutionContext

import org.apache.pekko
import pekko.actor.ClassicActorSystemProvider
import pekko.stream.Materializer
import pekko.grpc.GrpcProtocol.GrpcProtocolWriter
import pekko.grpc.ProtobufSerializer
import pekko.grpc.scaladsl.GrpcMarshalling
import pekko.grpc.scaladsl.ScalapbProtobufSerializer
import pekko.http.scaladsl.marshalling.Marshaller
import pekko.http.scaladsl.marshalling.ToResponseMarshaller
import pekko.http.scaladsl.model.HttpRequest
import pekko.http.scaladsl.unmarshalling.FromRequestUnmarshaller
import pekko.http.scaladsl.unmarshalling.Unmarshaller

import pekko.grpc.PekkoGrpcGenerated

@@PekkoGrpcGenerated
object @{service.name}Marshallers {
  @for(serializer <- service.serializers) {
  implicit val @serializer.name: ScalapbProtobufSerializer[@{serializer.scalaType}] = @{service.packageName}.@{service.name}.Serializers.@{serializer.name}
  }

  implicit def unmarshaller[T](implicit serializer: ProtobufSerializer[T], mat: Materializer): FromRequestUnmarshaller[T] =
    Unmarshaller((_: ExecutionContext) => (req: HttpRequest) => GrpcMarshalling.unmarshal(req)(serializer, mat))

  implicit def toSourceUnmarshaller[T](implicit serializer: ProtobufSerializer[T], mat: Materializer): FromRequestUnmarshaller[pekko.stream.scaladsl.Source[T, pekko.NotUsed]] =
    Unmarshaller((_: ExecutionContext) => (req: HttpRequest) => GrpcMarshalling.unmarshalStream(req)(serializer, mat))

  implicit def marshaller[T](implicit serializer: ProtobufSerializer[T], writer: GrpcProtocolWriter, system: ClassicActorSystemProvider): ToResponseMarshaller[T] =
    Marshaller.opaque((response: T) => GrpcMarshalling.marshal(response)(serializer, writer, system))

  implicit def fromSourceMarshaller[T](implicit serializer: ProtobufSerializer[T], writer: GrpcProtocolWriter, system: ClassicActorSystemProvider): ToResponseMarshaller[pekko.stream.scaladsl.Source[T, pekko.NotUsed]] =
    Marshaller.opaque((response: pekko.stream.scaladsl.Source[T, pekko.NotUsed]) => GrpcMarshalling.marshalStream(response)(serializer, writer, system))
}
