我有以下我喜欢编码的结构。 我知道如果大小字段直接位于矢量数据前面,我可以使用 vector() 对矢量进行编码。但这里编码向量大小的字段不相邻。
case class Item(
address: Int,
size: Int,
)
case class Header {
// lots of other fields before
numOfItems: Int,
// lots of other fields after
}
case class Outer(
hdr: Header,
items: Vector[]
)
外部解码正常:
从位向量中读取 Header.numOfItems 并使用 vectorOfN(provide(hdr.numOfItems, Item.codec)) 创建项目
外部编码是问题:
编码时,我希望从 items.length 中获取 numOfItem。 我知道我可以在更新 items Vector 时使用附加代码或使用“编码回调之前”之类的内容设置 numOfItems。
问题是是否有更优雅的解决方案。对我来说 Header.numOfItems
与 Outer.items.length
是多余的,所以理想情况下只有
编码器应该了解 numOfItems。
最佳答案
您可以尝试使用 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]
将其他 header 字段打包到它们自己的对象中。即(向 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是发现有用运算符的好地方
关于scodec - 编码向量长度字段不与向量相邻,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40151072/