Reputation: 1707
I have a class looking like this,
case class Foo ( bar: Int, foos: Vector[Foo] )
to define a Codec[Foo]
, I tried this,
def fc = shapeless.Lazy((int32 ~~ vector(fc)).widenOpt( (Foo.apply _).tupled, Foo.unapply _ ))
But this did not work, since scodec throws StackOverflowError
. What is the right way of doing this ?
Upvotes: 2
Views: 419
Reputation: 3855
You'll need the scodec.codecs.lazily
combinator to build recursive codecs (not shapeless.lazily
). For example:
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)))
In scodec 1.8.2 and prior, deriving this codec, instead of defining it explicitly, results in an error at compile time, due to the derivation continuing recursively forever. As of 1.8.3, this codec can be automatically derived without issue.
For an example of a recursive tree, see this example from scodec source.
Upvotes: 3