Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Derived codecs don't pick up custom codecs for basic types #42

Closed
plokhotnyuk opened this issue Jul 12, 2019 · 2 comments
Closed

Derived codecs don't pick up custom codecs for basic types #42

plokhotnyuk opened this issue Jul 12, 2019 · 2 comments

Comments

@plokhotnyuk
Copy link
Contributor

In previous version it worked fine:

scala> :paste
// Entering paste mode (ctrl-D to finish)

import io.bullet.borer._
import io.bullet.borer.derivation.MapBasedCodecs._

def stringCodec[T](f: String => T): Codec[T] = 
  Codec((w: Writer, value: T) => w.writeString(value.toString), (r: Reader) => f(r.readString()))

implicit val Codec(charEnc: Encoder[Char], charDec: Decoder[Char]) = stringCodec(_.charAt(0))

case class HasChar(ch: Char)

implicit val Codec(hasCharEnc: Encoder[HasChar], hasCharDec: Decoder[HasChar]) = deriveCodec[HasChar]

io.bullet.borer.Json.decode("""{"ch":"F"}""".getBytes).to[HasChar].value

// Exiting paste mode, now interpreting.
...
res0: HasChar = HasChar(F)

Now it tries to parse chars as ints without taking in account a custom codec provided by the implicit and throws the following error:

io.bullet.borer.Borer$Error$InvalidInputData: Expected Char but got Chars (input position 6)
  at io.bullet.borer.InputReader.unexpectedDataItem(Reader.scala:536)
  at io.bullet.borer.InputReader.unexpectedDataItem(Reader.scala:532)
  at io.bullet.borer.InputReader.readChar(Reader.scala:85)
  at HasCharDecoder$1.readObject$1(<console>:1)
  at HasCharDecoder$1.read(<console>:1)
  at $anon$2.read(<console>:1)
  at $anon$2.read(<console>:1)
  at io.bullet.borer.DecodingSetup$Impl.decodeFrom(DecodingSetup.scala:160)
  at io.bullet.borer.DecodingSetup$Impl.value(DecodingSetup.scala:99)
  ... 36 elided

But for some cases like bellow it picks the custom codec:

scala> io.bullet.borer.Json.decode("""["F"]""".getBytes).to[List[Char]].value
...
res1: List[Char] = List(F)
@plokhotnyuk plokhotnyuk changed the title Regression in 0.10.0: cannot inject a custom codec using implicit Regression in 0.10.0: cannot inject a custom codec using implicit during derivation of a map based codec Jul 12, 2019
@sirthias
Copy link
Owner

The reason for this is an optimization that came with 0.10.0.
For members with basic types derived codecs now don't rely on the implicit codecs, but read them directly from the reader, which circumvents boxing.

So, for all non-basic types custom codecs are still picked up as before.

@sirthias
Copy link
Owner

Theoretically this could be fixed by running implicit resolution at the macros call site for all encoders/decoders, including the ones for basic types, and comparing whether they match the default definitions. If they do we can take the shortcut, otherwise we need to go through the custom codecs.
However, at this point I'm not sure that there are sufficiently important real use cases for overriding the basic codecs to justify this investment...

@sirthias sirthias changed the title Regression in 0.10.0: cannot inject a custom codec using implicit during derivation of a map based codec Derived codecs don't pick up custom codecs for basic types Jul 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants