为递归数据结构定义 `Codec`
define `Codec` for recursive data structure
我有一个 class 看起来像这样,
case class Foo ( bar: Int, foos: Vector[Foo] )
定义一个Codec[Foo]
,我试过了,
def fc = shapeless.Lazy((int32 ~~ vector(fc)).widenOpt( (Foo.apply _).tupled, Foo.unapply _ ))
但这没有用,因为 scodec 抛出 WhosebugError
。这样做的正确方法是什么?
您需要 scodec.codecs.lazily
组合器来构建递归编解码器(而不是 shapeless.lazily
)。例如:
scala> def fc: Codec[Foo] = lazily((int32 :: vector(fc)).as[Foo])
fc: scodec.Codec[Foo]
scala> val res = fc.encode(Foo(1, Vector(Foo(2, Vector.empty)))).require
res: scodec.bits.BitVector = BitVector(64 bits, 0x0000000100000002)
scala> fc.decode(res)
res2: scodec.Attempt[scodec.DecodeResult[Foo]] = Successful(DecodeResult(Foo(1,Vector(Foo(2,Vector()))),BitVector(empty)))
在 scodec 1.8.2 及之前的版本中,派生此编解码器而不是显式定义它会导致编译时出错,因为派生会一直递归进行。自 1.8.3 起,此编解码器可以自动导出而不会出现问题。
有关递归树的示例,请参阅 this example from scodec source。
我有一个 class 看起来像这样,
case class Foo ( bar: Int, foos: Vector[Foo] )
定义一个Codec[Foo]
,我试过了,
def fc = shapeless.Lazy((int32 ~~ vector(fc)).widenOpt( (Foo.apply _).tupled, Foo.unapply _ ))
但这没有用,因为 scodec 抛出 WhosebugError
。这样做的正确方法是什么?
您需要 scodec.codecs.lazily
组合器来构建递归编解码器(而不是 shapeless.lazily
)。例如:
scala> def fc: Codec[Foo] = lazily((int32 :: vector(fc)).as[Foo])
fc: scodec.Codec[Foo]
scala> val res = fc.encode(Foo(1, Vector(Foo(2, Vector.empty)))).require
res: scodec.bits.BitVector = BitVector(64 bits, 0x0000000100000002)
scala> fc.decode(res)
res2: scodec.Attempt[scodec.DecodeResult[Foo]] = Successful(DecodeResult(Foo(1,Vector(Foo(2,Vector()))),BitVector(empty)))
在 scodec 1.8.2 及之前的版本中,派生此编解码器而不是显式定义它会导致编译时出错,因为派生会一直递归进行。自 1.8.3 起,此编解码器可以自动导出而不会出现问题。
有关递归树的示例,请参阅 this example from scodec source。