本文介绍了Scodec 组合器:标头包含用于区分类型的幻数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方法来处理类似以下示例的协议:

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 

这里,bodyType == 0 将代表 Read,而 bodyType != 0 将编码 Write.请注意,有几个字段将鉴别器与鉴别值分开.

Here, bodyType == 0 will stand for Read, and bodyType != 0 will encode 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]
} 

这篇关于Scodec 组合器:标头包含用于区分类型的幻数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 04:20