For "big" codecs, the Scala phase typer takes forever (we're talking minutes) when creating a codec directly from HList
s and applying .dropUnits
( ignore(6) ::
uint(2) ::
uint(30) ::
int(4) ::
int(8) ::
uint(10) ::
bool(1) ::
int(28) ::
int(27) ::
uint(12) ::
uint(9) ::
uint(6) ::
int(2) ::
ignore(3) ::
bool(1) ::
uint(19)
).dropUnits.as[SomeBigCaseClass]
And it seems to be way faster to create a codec with ~
, and then applying .hlist
like such:
( ignore(6) ~
uint(2) ~
...
).hlist.dropUnits.as[SomeBigCaseClass]
But this doesn't seem work.
Could not prove that this.Out can be converted to/from reports.SomeBigCaseClass.
).hlist.dropUnits.as[SomeBigCaseClass]
^
The simplest solution I've found, which is good enough for me is omitting Unit
values inline.
( (ignore(6) dropLeft
uint(2)) ::
...
).as[SomeBigCaseClass]
For codecs with many ignores, this feature would be highly welcome. What am I doing wrong? Am I totally missing the point of .hlist
?
The hlist
combinator converts a Codec[A]
in to a Codec[A :: HNil]
. This is typically used with other combinators, like flatZip
, which require an HList
based codec.
Repeated use of the ~
operator creates a left-associated Tuple2
based structure. For example, int8 ~ bool ~ int8
has type Codec[((Int, Boolean), Int)]
. The latest scodec snapshot, 1.7.0-SNAPSHOT (though not 1.7.0-RC1), has the flattenLeftPairs
method, which converts a left associated tuple codec to an equivalent HList
codec.
A future version of scodec will have a combinator like ~
but rather than nesting Tuple2
instances, it will create TupleN
instances. For example: int8 ~~ bool ~~ int8
would have type Codec[(Int, Boolean, Int)]
. This has not been integrated yet though. This has both a performance advantage, by reducing the number of tuples allocated, as well as a convenience advantage, because it allows binding to case classes via widenOpt(SomeBigCaseClass.apply, SomeBigCaseClass.unapply)
.
Finally, the observed compiler performance problem with dropUnits
is indeed a problem with the way that combinator is defined. This has been fixed in scodec-core 1.7.0-SNAPSHOT (not 1.7.0-RC1 though). See https://github.com/scodec/scodec/issues/41.