[英]Scodec combinators: Header contains magic number that is used to discriminate types
I am looking for a way to approach a protocol like the following example: 我正在寻找一种方法来处理类似以下示例的协议:
case class Request(bodyType: Int, foo: Int, bar: Int, body: RequestBody)
sealed trait RequestBody
case class Read(key: String) extends RequestBody
case class Write(key: String, value: Array[Byte]) extends RequestBody
Here, bodyType == 0
will stand for Read
, and bodyType != 0
will encode Write
. 这里,
bodyType == 0
代表Read
,而bodyType != 0
Write
。 Note that there are a few fields separating discriminator from discriminated value. 注意,有一些字段将区分符和区分值分开。
I've seen an example with byte-ordering . 我看过一个字节排序的例子 。 But as far as I understand this "squid" encoded discriminator would not round trip.
但是据我了解,这种“乌贼”编码的鉴别器不会往返。 What's the correct way to solve such a problem?
解决此类问题的正确方法是什么?
There are a few ways to do it, but this is one I've used: 有几种方法可以做到这一点,但这是我使用的一种方法:
import scodec._
import scodec.codecs._
import scodec.bits._
case class Request(bodyType: Int, foo: Int, bar: Int, body: RequestBody)
sealed trait RequestBody
case class Read(key: String) extends RequestBody
object Read {
implicit val codec: Codec[Read] = ("key" | utf8).as[Read]
implicit val discriminator: Discriminator[RequestBody, Read, Int] = Discriminator(0)
}
case class Write(key: String, value: ByteVector) extends RequestBody
object Write {
implicit val codec: Codec[Write] = {
("key" | utf8 ) ::
("value" | bytes )
}.as[Write]
implicit val discriminator: Discriminator[RequestBody, Write, Int] = Discriminator(1)
}
object Request {
implicit val codec: Codec[Request] = {
("bodyType" | uint16 ).flatPrepend { bodyType =>
("foo" | uint16 ) ::
("bar" | uint16 ) ::
("body" | Codec.coproduct[RequestBody].discriminatedBy(provide(bodyType)).auto)
}}.as[Request]
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.