【问题标题】:How to ignore Codec after using it to limit size bytes使用编解码器限制大小字节后如何忽略编解码器
【发布时间】:2018-10-08 08:48:41
【问题描述】:

我将为使用 TTLV 编码 (Tag, Type, Length, Value) 的 KMIP 协议创建一个模型

ttlv 函数是“高级”函数,接受值的标签、类型和编解码器。

 def ttlv[A<:HList](tag:ByteVector, itype:ByteVector, value: Codec[A]) =
   constant(tag) :: constant(itype) :: 
   (uint32 >>:~ {
     case length => limitedSizeBytes(length, value)
   })

结果是Codec[Unit :: Unit :: Long :: A]。但是,我将有一个Codec[Unit :: Unit :: Unit :: A](或Codec[A])将编解码器转换为只有A 值的case classlimitedSizeBytes 使用后如何忽略 uint32 ?否则,我对 cme​​ts 感兴趣以获得更好的方法。


这里有case class 的例子:

case class RequestHeader(protocol:Int)
case class RequestPayload(payload:CompromiseDate, name:CertificateName)
case class RequestMessage(header:RequestHeader, payload: RequestPayload)
case class CompromiseDate(value:Int)
case class CertificateName(value:String)

更多高级函数,如ttlvStructure

def ttlvStructure[A<:HList](tag:ByteVector, struct:Codec[A]) =
  ttlv(tag, hex"01", struct)
def ttlvTextString(tag:ByteVector) =
  ttlv(tag, hex"07", utf8.hlist)
def ttlvInt(tag:ByteVector) =
  ttlv(tag, hex"02", int32.hlist)

以及最终的编解码器:

implicit val certificateNameCodec =
  ttlvTextString(hex"420020").as[CertificateName]

implicit val compromiseDateCodec =
  ttlvInt(hex"420021").as[CompromiseDate]

implicit val requestPayloadCodec =
  ttlvStructure(hex"420003", Codec[CompromiseDate] :: Codec[CertificateName]).as[RequestPayload]

implicit val requestHeaderCodec =
  ttlvInt(hex"420002").as[RequestHeader]

implicit val requestMessageCodec =
  ttlvStructure(hex"420001", Codec[RequestHeader] :: Codec[RequestPayload]).as[RequestMessage]

要编码的对象示例:

val m = RequestMessage(
      RequestHeader(14),
      RequestPayload(
        CompromiseDate(8),
        CertificateName("certificate name")
      )
    )

解决方案

variableSizeBytesLong 在这里做我想做的事:

def ttlv[A<:HList](tag:ByteVector, itype:ByteVector, value: Codec[A]): Codec[A] =
    (constant(tag) :~>: constant(itype) :~>: variableSizeBytesLong(uint32, value))

【问题讨论】:

    标签: scala shapeless scodec


    【解决方案1】:

    试试

    val defaultLength: Long = ???
    
    def ttlv[A<:HList](tag:ByteVector, itype:ByteVector, value: Codec[A]): Codec[A] =
      constant(tag) :~>: constant(itype) :~>:
        (uint32 >>:~ (length => limitedSizeBytes(length, value))).xmap[A](_.tail, defaultLength :: _)
    

    【讨论】:

    • 但默认长度是可变长度。我通读了编解码器代码,发现了完美的variableSizeBytesLong 结果到编解码器(constant(tag) :~&gt;: constant(itype) :~&gt;: variableSizeBytesLong(uint32, value))。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    相关资源
    最近更新 更多