Cannot deserialize empty arrays of non-primitive types
sptz45 opened this issue · comments
The bug
Currently the following code fails with a ClassCastException
:
val bytes = Cbor.encode(Array.empty[String]).toByteArray
Cbor.decode(bytes).to[Array[String]].value // throws exceptions
The exception message is:
java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.String; ([Ljava.lang.Object; and [Ljava.lang.String; are in module java.base of loader 'bootstrap')
The code works as expected if we use a primitive type like Int
:
val bytes = Cbor.encode(Array.empty[Int]).toByteArray
Cbor.decode(bytes).to[Array[Int]].value // returns the empty array
The root cause
When decoding an array the io.bullet.borer.internal.Util.emptyArray
method is used to construct empty arrays. The method is defined as:
def emptyArray[T](implicit ct: ClassTag[T]): Array[T] =
(ct.runtimeClass match {
case java.lang.Byte.TYPE => Array.emptyByteArray
case java.lang.Short.TYPE => Array.emptyShortArray
case java.lang.Character.TYPE => Array.emptyCharArray
case java.lang.Integer.TYPE => Array.emptyIntArray
case java.lang.Long.TYPE => Array.emptyLongArray
case java.lang.Float.TYPE => Array.emptyFloatArray
case java.lang.Double.TYPE => Array.emptyDoubleArray
case java.lang.Boolean.TYPE => Array.emptyBooleanArray
case _ => Array.emptyObjectArray
}).asInstanceOf[Array[T]]
The exception is thrown because in Java we cannot cast S[]
to T[]
if T
is a subtype of S
(if I recall correctly this has to do with the fact the arrays in Java are covariant).
For example:
jshell> Object[] o = new Object[]{};
o ==> Object[0] { }
jshell> String[] s = (String[])o;
| Exception java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.String; ([Ljava.lang.Object; and [Ljava.lang.String; are in module java.base of loader 'bootstrap')
| at (#2:1)
Thank you, Spiros, for this awesome bug report!
Not simply with a very clear problem description, but also a complete root-cause analysis!
Kudos and huge hats-off to you!
I'll take the fix for this as a nice trigger for the next release, which I'll publish this afternoon.
Thank you @sirthias for the quick fix!