您可以尝试使用构建编解码器consume()
并在不构建Outer
对象的情况下开始:
case class OuterExpanded(
fieldBefore: Int, // Field before number of items in the binary encoding
fieldAdter: Int, // Field after number of items in the binary encoding
items: Vector[Item] // Encoded items
)
// Single Item codec
def itemC: Codec[Item] = (int32 :: int32).as[Item]
def outerExpandedC: Codec[OuterExpanded] = (
int32 :: // Field before count
int32.consume( c => // Item count
int32 :: // Field after count
vectorOfN(provide(c), itemC)) // 'consume' (use and forget) the count
(_.tail.head.length) // provide the length when encoding
).as[OuterExpanded]
如上定义,编码时会得到以下信息outerExpandedC.encode(OuterExpanded(-1, -1, Vector(Item(1,2), Item(3,4))))
:
Successful(BitVector(224 bits,
0xffffffff00000002fffffffe00000001000000020000000300000004))
^ ^ ^ ^-------^-> First Item
|-1 | |-2
|Vector length inserted between the two header fields
之后,您可以xmap()
将Codec[OuterExpanded]
其他标头字段一起打包到它们自己的对象中。即(添加两个转换方法到Outer
和OuterExpanded
):
def outerC: Codec[Outer] =
outerExpandedC.xmap(_.toOuter,_.expand)
case class OuterExpanded(fieldBefore: Int, fieldAfter: Int, items: Vector[Item]) {
def toOuter = Outer(Hdr(fieldBefore,fieldAfter), items)
}
case class Outer(header: Hdr, items: Vector[Item]) {
def expand = OuterExpanded(header.beforeField1, header.beforeField1, items)
}
这可能适用于更复杂的情况,尽管我并不完全熟悉无形的异构列表 - 或者HList
- 可能有更好的方法来获取向量的长度而不是_.tail.head.length
在上面的示例中调用,特别是如果你在编码值的数量之后有多个字段。
此外,Codec scaladoc是发现有用运算符的好地方