使用它限制大小字节后如何忽略编解码器

时间:2018-10-08 08:48:42

标签: scala shapeless scodec

我将为适用于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])将编解码器转换为仅具有值case class的{​​{1}}。 A使用后如何忽略uint32?否则,我会对改进方法的评论感兴趣。


以下是limitedSizeBytes个示例:

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

1 个答案:

答案 0 :(得分: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 :: _)