ScalaBuff
ScalaBuff copied to clipboard
Support for Spray
I am trying to use ScalaBuff in a Spray application. The marshalling of messages to Protobuf works like a charm using ScalaBuff:
object ProtobufProtocols {
val ProtobufMediaType = MediaTypes.register(MediaType.custom("application", "protobuf", compressible = false, binary = true))
val Protobuf = ContentType(ProtobufMediaType)
implicit def marshaller[T <: com.google.protobuf.MessageLite]() =
Marshaller.of[T](Protobuf) { (value, contentType, ctx) ⇒
ctx.marshalTo(HttpEntity(contentType, value.toByteArray))
}
}
This is generic and works for all messages generated by ScalaBuff.
I am, however, not sure how to get unmarshalling:
implicit def unmarshaller[T <: net.sandrogrzicic.scalabuff.Message]() =
Unmarshaller[T](ProtobufMediaType) {
case HttpBody(contentType, buffer) =>
// TODO
}
In this method, I somehow need to call T
's parseFrom
method.
Does ScalaBuff provide a way to achieve this?
Note: I also posted this question in the Spray User Group.
After some random searching, perhaps you can try something like this:
implicit def unmarshaller[T <: net.sandrogrzicic.scalabuff.Message]()(implicit tag: scala.reflect.ClassTag[T]) =
Unmarshaller[T](ProtobufMediaType) {
case HttpBody(contentType, buffer) =>
tag.erasure.newInstance.asInstanceOf[T].parseFrom(buffer)
}
Haven't tried it and it's by very definition unsafe, however every ScalaBuff case class comes with a no-arg constructor (every parameter is optional) so in theory this should never throw an Exception. If you pass in a Message that doesn't have a no-arg constructor, it will throw an InstantiationException.
Also, there's probably a cleaner way to do this - but I hope it's a good start. :)
https://github.com/akka/akka/blob/master/akka-remote/src/main/scala/akka/remote/serialization/ProtobufSerializer.scala
That works if you have a Class[T], but I don't think you do with Spray's Unmarshaller.
However I'm guessing it's better to do it this way, with a direct parseFrom method call on the object of type T instead of instantiating the whole class. I'm not sure about the exact semantics though since the companion object is a, well, object.