Я использую Play Framework и пытаюсь написать действие, которое может анализировать Protobuf запроса следующим образом:Quasiquotes и Дженерик в Scala
def AsyncProtoAction(block: ProtoRequestA => Future[Result]): Action[AnyContent] = {
Action.async { request =>
request.contentType match {
case Some("application/protobuf") => request.body.asRaw match {
case Some(raw) => raw.asBytes(1024 * 1024) match {
case Some(rawBytes) =>
val proto = ProtoRequestA.parseFrom(rawBytes)
block(proto)
case _ => ...
}
}
}
}
}
Здесь ProtoRequestA
является сгенерированным объектом с помощью ScalaPB
. Он работает, однако, у меня много объектов запроса protobuf. Затем я пытаюсь переписать его с помощью макроса:
object Actions {
def AsyncProtoAction[T](block: T => Future[Result]):
Action[AnyContent] = macro asyncProtoAction_impl[T]
def asyncProtoAction_impl[T: c.WeakTypeTag](c: blackbox.Context)
(block: c.Tree) = { import c.universe._
val protoType = weakTypeOf[T]
q"""import play.api.mvc._
Action.async { request =>
request.contentType match {
case Some("application/protobuf") =>
request.body.asRaw match {
case Some(raw) =>
raw.asBytes(1024 * 1024) match {
case Some(rawBytes) =>
val proto = $protoType.parseFrom(rawBytes)
$block(proto)
case _ => ...
}
}
}
}"""
}
}
Это не работает. Ошибка компиляции - value parseFrom is not a member of packageName.ProtoRequestA
.
Я пробовал showRaw(tq"$protoType")
в REPL, выход которого String = TypeTree()
. Я думаю, правильный результат должен быть String = Select(Ident(TermName("packageName")), TypeName("ProtoRequestA"))
. И что же мне делать?
Попробуйте заменить '$ protoType'' $ {protoType.typeSymbol.companionSymbol} 'и посмотреть, как это происходит. –