3

我有一个用例,其中标头可以包含 7 个字节加上可选的 0-15 字节信息,其中大小信息位于第 5 个字节的低 4 位,因此格式为:

4 bytes | 4 bits | 4 bits <- length of extra bytes | 2 bytes | 0-15 extra Bytes

我在下面的案例类中对此进行了建模

case class FHDR(DevAddr:Long, ADR:Boolean, ADRACKReq:Boolean, ACK:Boolean, FPending:Boolean, FCnt:Int, FOpts:ByteVector)

implicit val FHDRCodec = {
  ("dev_addr" | uint32L) ::
  ("adr" | bool) ::
  ("adr_ack_req" | bool) ::
  ("ack" | bool) ::
  ("f_pending" | bool) ::
  variableSizePrefixedBytes(uint4, 
    "f_cnt" | uint16L, 
    "f_opts" | bytes)
}.as[FHDR]

在这种情况下,根据 scala 文档,我可以使用该variableSizePrefixedBytes方法对大小和额外字节之间的 2 个额外字节进行建模。

但是我做错了,因为编译器无法证明这个编解码器可以转换为/从FHDR类转换,我已经盯着这个看了一段时间了,但我一无所知

4

1 回答 1

4

这种情况下的错误是:

error: Could not prove that shapeless.::[Long,shapeless.::[Boolean,shapeless.::[Boolean,shapeless.::[Boolean,shapeless.::[Boolean,shapeless.::[(Int, scodec.bits.ByteVector),shapeless.HNil]]]]]] can be converted to/from FHDR.
   }.as[FHDR]
       ^

重新格式化错误以::在中缀位置使用给出:

error: Could not prove that Long :: Boolean :: Boolean :: Boolean :: Boolean :: (Int, ByteVector) :: HNil can be converted to/from FHDR.
   }.as[FHDR]
       ^

的一般表示FHDRLong :: Boolean :: Boolean :: Boolean :: Boolean :: Int :: ByteVector :: HNil。这里的问题是 中的最后一个类型HList(Int, ByteVector)由 引起的variableSizePrefixedBytes,它具有以下签名:

  def variableSizePrefixedBytes[A, B](size: Codec[Int], prefix: Codec[A], value: Codec[B], sizePadding: Int = 0): Codec[(A, B)] = ...

我们需要将该元组展平到外部HList结构中,这将导致编解码器的形状与 的通用表示的形状相匹配FHDR

import scodec.bits._
import scodec.codecs._
import shapeless.syntax.std.product._

case class FHDR(DevAddr:Long, ADR:Boolean, ADRACKReq:Boolean, ACK:Boolean, FPending:Boolean, FCnt:Int, FOpts:ByteVector)

implicit val FHDRCodec = {
  ("dev_addr" | uint32L) ::
  ("adr" | bool) ::
  ("adr_ack_req" | bool) ::
  ("ack" | bool) ::
  ("f_pending" | bool) ::
  variableSizePrefixedBytes(uint4, 
    "f_cnt" | uint16L, 
    "f_opts" | bytes
  ).xmapc(_.toHList)(_.tupled)
}.as[FHDR]

在这里,我们使用来自导入.toHList的 on 。我们还使用来扭转这种转变。Tuple2shapeless.syntax.std.product._.tupled

于 2016-01-05T17:35:22.207 回答