amnaredo / test

0 stars 0 forks source link

MessagePack Float32 reading error #286

Open amnaredo opened 2 years ago

amnaredo commented 2 years ago

Reading Float values from MessagePack Float32 values should be supported according to the documentation and it should be consistent with the writing behavior.

Currently, writing Float values creates a MessagePack Float32 value but an equivalent reading operation causes the FloatReader to report an unexpected data type error.

Environment

Reproduce

import upickle.default._

object Main extends App:

  println(readBinary[Float](writeMsg(1.0f)))

Result

upickle.core.Abort: expected number got float32
    at upickle.core.SimpleVisitor.visitFloat32(SimpleVisitor.scala:29)
    at upickle.core.SimpleVisitor.visitFloat32$(SimpleVisitor.scala:7)
    at upickle.implicits.Readers$$anon$5.visitFloat32(Readers.scala:59)
    at upack.Msg$.transform(Msg.scala:182)
    at upack.Msg.transform(Msg.scala:23)
    at upack.Msg.transform$(Msg.scala:21)
    at upack.Float32.transform(Msg.scala:107)
    at upickle.Api.readBinary$$anonfun$1(Api.scala:30)
    at upickle.core.TraceVisitor$.withTrace(TraceVisitor.scala:18)
    at upickle.Api.readBinary(Api.scala:30)
    at upickle.Api.readBinary$(Api.scala:17)
    at upickle.default$.readBinary(Api.scala:133)
    at Main$.<clinit>(main.scala:6)

Expected

1.0

Fix

Add the following method override to the FloatReader:

override def visitFloat32(d: Float, index: Int) = d

Workaround

Add the following implicit reader override to your custom configuration:

  implicit override val FloatReader: Reader[Float] =
    new SimpleReader[Float] {

      override def expectedMsg = "expected number"
      override def visitString(s: CharSequence, index: Int) = s.toString.toFloat
      override def visitInt32(d: Int, index: Int) = d.toFloat
      override def visitInt64(d: Long, index: Int) = d.toFloat
      override def visitUInt64(d: Long, index: Int) = d.toFloat
      override def visitFloat32(d: Float, index: Int) = d
      override def visitFloat64(d: Double, index: Int) = d.toFloat
      override def visitFloat64StringParts(s: CharSequence, decIndex: Int, expIndex: Int, index: Int) =
        s.toString.toFloat
    }

ID: 354 Original Author: martin-ockajak