당신은 consume()
을 사용하여 코덱을 구축 시도하고 Outer
객체 구축없이 시작할 수 : 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
그 후, 당신 :
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]
상기 정의 된 바와을, 당신은 인코딩 할 때 다음을 얻을 xmap()
Codec[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
-하고있을 수 있습니다 : 즉 (이 변환 Outer
에 대한 방법과 OuterExpanded
추가) 위의 예에서 _.tail.head.length
을 호출하는 대신 벡터의 길이에 도달하는 더 좋은 방법입니다. 특히 인코딩 된 값의 개수 이후에 둘 이상의 필드가있는 경우 더욱 그렇습니다.
또한, Codec scaladoc 유용 사업자 나는 다음과 같은 코드를 내놓았다 이전의 답변에 따라
확인. "Atomic ..."솔루션과 비교했을 때 약간의 반복이 있었지만 "상태 비 저장"코덱을 사용하는 장점이 있습니다. 아직 더 나은 해결책이 없다면 그것이 받아 들여진 대답이라고 말할 수 있습니다. –