mirror of
https://github.com/corda/corda.git
synced 2024-12-21 22:07:55 +00:00
Merge pull request #1106 from corda/kat-primArrayDeserialise
Add support for serialising arrays of unboxed primitives
This commit is contained in:
commit
6dc48e7cea
@ -7,12 +7,21 @@ import java.lang.reflect.Type
|
|||||||
/**
|
/**
|
||||||
* Serialization / deserialization of arrays.
|
* Serialization / deserialization of arrays.
|
||||||
*/
|
*/
|
||||||
class ArraySerializer(override val type: Type, factory: SerializerFactory) : AMQPSerializer<Any> {
|
open class ArraySerializer(override val type: Type, factory: SerializerFactory) : AMQPSerializer<Any> {
|
||||||
override val typeDescriptor = "$DESCRIPTOR_DOMAIN:${fingerprintForType(type, factory)}"
|
companion object {
|
||||||
|
fun make(type: Type, factory: SerializerFactory) = when (type) {
|
||||||
|
Array<Character>::class.java -> CharArraySerializer(factory)
|
||||||
|
else -> ArraySerializer(type, factory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal val elementType: Type = type.componentType()
|
override val typeDescriptor by lazy { "$DESCRIPTOR_DOMAIN:${fingerprintForType(type, factory)}" }
|
||||||
|
internal val elementType: Type by lazy { type.componentType() }
|
||||||
|
internal open val typeName by lazy { type.typeName }
|
||||||
|
|
||||||
private val typeNotation: TypeNotation = RestrictedType(type.typeName, null, emptyList(), "list", Descriptor(typeDescriptor, null), emptyList())
|
internal val typeNotation: TypeNotation by lazy {
|
||||||
|
RestrictedType(typeName, null, emptyList(), "list", Descriptor(typeDescriptor, null), emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
override fun writeClassInfo(output: SerializationOutput) {
|
override fun writeClassInfo(output: SerializationOutput) {
|
||||||
if (output.writeTypeNotations(typeNotation)) {
|
if (output.writeTypeNotations(typeNotation)) {
|
||||||
@ -37,14 +46,105 @@ class ArraySerializer(override val type: Type, factory: SerializerFactory) : AMQ
|
|||||||
} else throw NotSerializableException("Expected a List but found $obj")
|
} else throw NotSerializableException("Expected a List but found $obj")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> List<T>.toArrayOfType(type: Type): Any {
|
open fun <T> List<T>.toArrayOfType(type: Type): Any {
|
||||||
|
val elementType = type.asClass() ?: throw NotSerializableException("Unexpected array element type $type")
|
||||||
|
val list = this
|
||||||
|
return java.lang.reflect.Array.newInstance(elementType, this.size).apply {
|
||||||
|
(0..lastIndex).forEach { java.lang.reflect.Array.set(this, it, list[it]) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boxed Character arrays required a specialisation to handle the type conversion properly when populating
|
||||||
|
// the array since Kotlin won't allow an implicit cast from Int (as they're stored as 16bit ints) to Char
|
||||||
|
class CharArraySerializer(factory: SerializerFactory) : ArraySerializer(Array<Character>::class.java, factory) {
|
||||||
|
override fun <T> List<T>.toArrayOfType(type: Type): Any {
|
||||||
|
val elementType = type.asClass() ?: throw NotSerializableException("Unexpected array element type $type")
|
||||||
|
val list = this
|
||||||
|
return java.lang.reflect.Array.newInstance(elementType, this.size).apply {
|
||||||
|
(0..lastIndex).forEach { java.lang.reflect.Array.set(this, it, (list[it] as Int).toChar()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specialisation of [ArraySerializer] that handles arrays of unboxed java primitive types
|
||||||
|
abstract class PrimArraySerializer(type: Type, factory: SerializerFactory) : ArraySerializer(type, factory) {
|
||||||
|
companion object {
|
||||||
|
// We don't need to handle the unboxed byte type as that is coercible to a byte array, but
|
||||||
|
// the other 7 primitive types we do
|
||||||
|
val primTypes: Map<Type, (SerializerFactory) -> PrimArraySerializer> = mapOf(
|
||||||
|
IntArray::class.java to { f -> PrimIntArraySerializer(f, "int[p]") },
|
||||||
|
CharArray::class.java to { f -> PrimCharArraySerializer(f, "char[p]") },
|
||||||
|
BooleanArray::class.java to { f -> PrimBooleanArraySerializer(f, "boolean[p]") },
|
||||||
|
FloatArray::class.java to { f -> PrimFloatArraySerializer(f, "float[p]") },
|
||||||
|
ShortArray::class.java to { f -> PrimShortArraySerializer(f, "short[p]") },
|
||||||
|
DoubleArray::class.java to { f -> PrimDoubleArraySerializer(f, "double[p]") },
|
||||||
|
LongArray::class.java to { f -> PrimLongArraySerializer(f, "long[p]") }
|
||||||
|
// ByteArray::class.java <-> NOT NEEDED HERE (see comment above)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun make(type: Type, factory: SerializerFactory) = primTypes[type]!!(factory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun localWriteObject(data: Data, func: () -> Unit) {
|
||||||
|
data.withDescribed(typeNotation.descriptor) { withList { func() } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrimIntArraySerializer(factory: SerializerFactory, override val typeName: String) :
|
||||||
|
PrimArraySerializer(IntArray::class.java, factory) {
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
|
||||||
|
localWriteObject(data) { (obj as IntArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrimCharArraySerializer(factory: SerializerFactory, override val typeName: String) :
|
||||||
|
PrimArraySerializer(CharArray::class.java, factory) {
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
|
||||||
|
localWriteObject(data) { (obj as CharArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T> List<T>.toArrayOfType(type: Type): Any {
|
||||||
val elementType = type.asClass() ?: throw NotSerializableException("Unexpected array element type $type")
|
val elementType = type.asClass() ?: throw NotSerializableException("Unexpected array element type $type")
|
||||||
val list = this
|
val list = this
|
||||||
return java.lang.reflect.Array.newInstance(elementType, this.size).apply {
|
return java.lang.reflect.Array.newInstance(elementType, this.size).apply {
|
||||||
val array = this
|
val array = this
|
||||||
for (i in 0..lastIndex) {
|
(0..lastIndex).forEach { java.lang.reflect.Array.set(array, it, (list[it] as Int).toChar()) }
|
||||||
java.lang.reflect.Array.set(array, i, list[i])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PrimBooleanArraySerializer(factory: SerializerFactory, override val typeName: String) :
|
||||||
|
PrimArraySerializer(BooleanArray::class.java, factory) {
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
|
||||||
|
localWriteObject(data) { (obj as BooleanArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrimDoubleArraySerializer(factory: SerializerFactory, override val typeName: String) :
|
||||||
|
PrimArraySerializer(DoubleArray::class.java, factory) {
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
|
||||||
|
localWriteObject(data) { (obj as DoubleArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrimFloatArraySerializer(factory: SerializerFactory, override val typeName: String) :
|
||||||
|
PrimArraySerializer(FloatArray::class.java, factory) {
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
|
||||||
|
localWriteObject(data) { (obj as FloatArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrimShortArraySerializer(factory: SerializerFactory, override val typeName: String) :
|
||||||
|
PrimArraySerializer(ShortArray::class.java, factory) {
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
|
||||||
|
localWriteObject(data) { (obj as ShortArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrimLongArraySerializer(factory: SerializerFactory, override val typeName: String) :
|
||||||
|
PrimArraySerializer(LongArray::class.java, factory) {
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
|
||||||
|
localWriteObject(data) { (obj as LongArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -133,7 +133,8 @@ class DeserializationInput(internal val serializerFactory: SerializerFactory = S
|
|||||||
// Look up serializer in factory by descriptor
|
// Look up serializer in factory by descriptor
|
||||||
val serializer = serializerFactory.get(obj.descriptor, schema)
|
val serializer = serializerFactory.get(obj.descriptor, schema)
|
||||||
if (serializer.type != type && !serializer.type.isSubClassOf(type))
|
if (serializer.type != type && !serializer.type.isSubClassOf(type))
|
||||||
throw NotSerializableException("Described type with descriptor ${obj.descriptor} was expected to be of type $type")
|
throw NotSerializableException("Described type with descriptor ${obj.descriptor} was " +
|
||||||
|
"expected to be of type $type but was ${serializer.type}")
|
||||||
return serializer.readObject(obj.described, schema, this)
|
return serializer.readObject(obj.described, schema, this)
|
||||||
} else if (obj is Binary) {
|
} else if (obj is Binary) {
|
||||||
return obj.array
|
return obj.array
|
||||||
|
@ -13,6 +13,6 @@ class DeserializedGenericArrayType(private val componentType: Type) : GenericArr
|
|||||||
override fun toString(): String = typeName
|
override fun toString(): String = typeName
|
||||||
override fun hashCode(): Int = Objects.hashCode(componentType)
|
override fun hashCode(): Int = Objects.hashCode(componentType)
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
return other is GenericArrayType && componentType.equals(other.genericComponentType)
|
return other is GenericArrayType && (componentType == other.genericComponentType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,8 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
|
|||||||
findCustomSerializer(clazz, declaredType) ?: run {
|
findCustomSerializer(clazz, declaredType) ?: run {
|
||||||
if (type.isArray()) {
|
if (type.isArray()) {
|
||||||
whitelisted(type.componentType())
|
whitelisted(type.componentType())
|
||||||
ArraySerializer(type, this)
|
if (clazz.componentType.isPrimitive) PrimArraySerializer.make(type, this)
|
||||||
|
else ArraySerializer.make (type, this)
|
||||||
} else if (clazz.kotlin.objectInstance != null) {
|
} else if (clazz.kotlin.objectInstance != null) {
|
||||||
whitelisted(clazz)
|
whitelisted(clazz)
|
||||||
SingletonSerializer(clazz, clazz.kotlin.objectInstance!!, this)
|
SingletonSerializer(clazz, clazz.kotlin.objectInstance!!, this)
|
||||||
@ -292,14 +293,15 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
|
|||||||
|
|
||||||
private val namesOfPrimitiveTypes: Map<String, Class<*>> = primitiveTypeNames.map { it.value to it.key }.toMap()
|
private val namesOfPrimitiveTypes: Map<String, Class<*>> = primitiveTypeNames.map { it.value to it.key }.toMap()
|
||||||
|
|
||||||
fun nameForType(type: Type): String {
|
fun nameForType(type: Type) : String = when (type) {
|
||||||
if (type is Class<*>) {
|
is Class<*> -> {
|
||||||
return primitiveTypeName(type) ?: if (type.isArray) "${nameForType(type.componentType)}[]" else type.name
|
primitiveTypeName(type) ?: if (type.isArray) {
|
||||||
} else if (type is ParameterizedType) {
|
"${nameForType(type.componentType)}${if(type.componentType.isPrimitive)"[p]" else "[]"}"
|
||||||
return "${nameForType(type.rawType)}<${type.actualTypeArguments.joinToString { nameForType(it) }}>"
|
} else type.name
|
||||||
} else if (type is GenericArrayType) {
|
}
|
||||||
return "${nameForType(type.genericComponentType)}[]"
|
is ParameterizedType -> "${nameForType(type.rawType)}<${type.actualTypeArguments.joinToString { nameForType(it) }}>"
|
||||||
} else throw NotSerializableException("Unable to render type $type to a string.")
|
is GenericArrayType -> "${nameForType(type.genericComponentType)}[]"
|
||||||
|
else -> throw NotSerializableException("Unable to render type $type to a string.")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun typeForName(name: String): Type {
|
private fun typeForName(name: String): Type {
|
||||||
@ -312,6 +314,20 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
|
|||||||
} else {
|
} else {
|
||||||
throw NotSerializableException("Not able to deserialize array type: $name")
|
throw NotSerializableException("Not able to deserialize array type: $name")
|
||||||
}
|
}
|
||||||
|
} else if (name.endsWith("[p]")) {
|
||||||
|
// There is no need to handle the ByteArray case as that type is coercible automatically
|
||||||
|
// to the binary type and is thus handled by the main steriliser and doesn't need a
|
||||||
|
// special case for a primitive array of bytes
|
||||||
|
when(name) {
|
||||||
|
"int[p]" -> IntArray::class.java
|
||||||
|
"char[p]" -> CharArray::class.java
|
||||||
|
"boolean[p]" -> BooleanArray::class.java
|
||||||
|
"float[p]" -> FloatArray::class.java
|
||||||
|
"double[p]" -> DoubleArray::class.java
|
||||||
|
"short[p]" -> ShortArray::class.java
|
||||||
|
"long[p]" -> LongArray::class.java
|
||||||
|
else -> throw NotSerializableException("Not able to deserialize array type: $name")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DeserializedParameterizedType.make(name)
|
DeserializedParameterizedType.make(name)
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,37 @@
|
|||||||
package net.corda.core.serialization.amqp
|
package net.corda.core.serialization.amqp
|
||||||
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
|
||||||
/**
|
// Prior to certain fixes being made within the [PropertySerializaer] classes these simple
|
||||||
* Prior to certain fixes being made within the [PropertySerializaer] classes these simple
|
// deserialization operations would've blown up with type mismatch errors where the deserlized
|
||||||
* deserialization operations would've blown up with type mismatch errors where the deserlized
|
// char property of the class would've been treated as an Integer and given to the constructor
|
||||||
* char property of the class would've been treated as an Integer and given to the constructor
|
// as such
|
||||||
* as such
|
|
||||||
*/
|
|
||||||
class DeserializeSimpleTypesTests {
|
class DeserializeSimpleTypesTests {
|
||||||
|
class TestSerializationOutput(
|
||||||
|
private val verbose: Boolean,
|
||||||
|
serializerFactory: SerializerFactory = SerializerFactory()) : SerializationOutput(serializerFactory) {
|
||||||
|
|
||||||
|
override fun writeSchema(schema: Schema, data: Data) {
|
||||||
|
if (verbose) println(schema)
|
||||||
|
super.writeSchema(schema, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* If you want to see the schema encoded into the envelope after serialisation change this to true
|
||||||
|
*/
|
||||||
|
private const val VERBOSE = false
|
||||||
|
}
|
||||||
|
|
||||||
|
val sf = SerializerFactory()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testChar() {
|
fun testChar() {
|
||||||
data class C(val c: Char)
|
data class C(val c: Char)
|
||||||
|
|
||||||
val c = C('c')
|
val c = C('c')
|
||||||
val serialisedC = SerializationOutput().serialize(c)
|
val serialisedC = SerializationOutput().serialize(c)
|
||||||
val deserializedC = DeserializationInput().deserialize(serialisedC)
|
val deserializedC = DeserializationInput().deserialize(serialisedC)
|
||||||
@ -24,11 +42,333 @@ class DeserializeSimpleTypesTests {
|
|||||||
@Test
|
@Test
|
||||||
fun testCharacter() {
|
fun testCharacter() {
|
||||||
data class C(val c: Character)
|
data class C(val c: Character)
|
||||||
val c = C(Character ('c'))
|
|
||||||
|
val c = C(Character('c'))
|
||||||
val serialisedC = SerializationOutput().serialize(c)
|
val serialisedC = SerializationOutput().serialize(c)
|
||||||
val deserializedC = DeserializationInput().deserialize(serialisedC)
|
val deserializedC = DeserializationInput().deserialize(serialisedC)
|
||||||
|
|
||||||
assertEquals(c.c, deserializedC.c)
|
assertEquals(c.c, deserializedC.c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfInt() {
|
||||||
|
class IA(val ia: Array<Int>)
|
||||||
|
|
||||||
|
val ia = IA(arrayOf(1, 2, 3))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Integer;", ia.ia::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(ia.ia::class.java), "int[]")
|
||||||
|
|
||||||
|
val serialisedIA = TestSerializationOutput(VERBOSE, sf).serialize(ia)
|
||||||
|
val deserializedIA = DeserializationInput(sf).deserialize(serialisedIA)
|
||||||
|
|
||||||
|
assertEquals(ia.ia.size, deserializedIA.ia.size)
|
||||||
|
assertEquals(ia.ia[0], deserializedIA.ia[0])
|
||||||
|
assertEquals(ia.ia[1], deserializedIA.ia[1])
|
||||||
|
assertEquals(ia.ia[2], deserializedIA.ia[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfInteger() {
|
||||||
|
class IA(val ia: Array<Integer>)
|
||||||
|
|
||||||
|
val ia = IA(arrayOf(Integer(1), Integer(2), Integer(3)))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Integer;", ia.ia::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(ia.ia::class.java), "int[]")
|
||||||
|
|
||||||
|
val serialisedIA = TestSerializationOutput(VERBOSE, sf).serialize(ia)
|
||||||
|
val deserializedIA = DeserializationInput(sf).deserialize(serialisedIA)
|
||||||
|
|
||||||
|
assertEquals(ia.ia.size, deserializedIA.ia.size)
|
||||||
|
assertEquals(ia.ia[0], deserializedIA.ia[0])
|
||||||
|
assertEquals(ia.ia[1], deserializedIA.ia[1])
|
||||||
|
assertEquals(ia.ia[2], deserializedIA.ia[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test unboxed primitives
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
fun testIntArray() {
|
||||||
|
class IA(val ia: IntArray)
|
||||||
|
|
||||||
|
val v = IntArray(3)
|
||||||
|
v[0] = 1; v[1] = 2; v[2] = 3
|
||||||
|
val ia = IA(v)
|
||||||
|
|
||||||
|
assertEquals("class [I", ia.ia::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(ia.ia::class.java), "int[p]")
|
||||||
|
|
||||||
|
val serialisedIA = TestSerializationOutput(VERBOSE, sf).serialize(ia)
|
||||||
|
val deserializedIA = DeserializationInput(sf).deserialize(serialisedIA)
|
||||||
|
|
||||||
|
assertEquals(ia.ia.size, deserializedIA.ia.size)
|
||||||
|
assertEquals(ia.ia[0], deserializedIA.ia[0])
|
||||||
|
assertEquals(ia.ia[1], deserializedIA.ia[1])
|
||||||
|
assertEquals(ia.ia[2], deserializedIA.ia[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfChars() {
|
||||||
|
class C(val c: Array<Char>)
|
||||||
|
|
||||||
|
val c = C(arrayOf('a', 'b', 'c'))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Character;", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "char[]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCharArray() {
|
||||||
|
class C(val c: CharArray)
|
||||||
|
|
||||||
|
val v = CharArray(3)
|
||||||
|
v[0] = 'a'; v[1] = 'b'; v[2] = 'c'
|
||||||
|
val c = C(v)
|
||||||
|
|
||||||
|
assertEquals("class [C", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "char[p]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfBoolean() {
|
||||||
|
class C(val c: Array<Boolean>)
|
||||||
|
|
||||||
|
val c = C(arrayOf(true, false, false, true))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Boolean;", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "boolean[]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
assertEquals(c.c[3], deserializedC.c[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBooleanArray() {
|
||||||
|
class C(val c: BooleanArray)
|
||||||
|
|
||||||
|
val c = C(BooleanArray(4))
|
||||||
|
c.c[0] = true; c.c[1] = false; c.c[2] = false; c.c[3] = true
|
||||||
|
|
||||||
|
assertEquals("class [Z", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "boolean[p]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
assertEquals(c.c[3], deserializedC.c[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfByte() {
|
||||||
|
class C(val c: Array<Byte>)
|
||||||
|
|
||||||
|
val c = C(arrayOf(0b0001, 0b0101, 0b1111))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Byte;", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "byte[]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testByteArray() {
|
||||||
|
class C(val c: ByteArray)
|
||||||
|
|
||||||
|
val c = C(ByteArray(3))
|
||||||
|
c.c[0] = 0b0001; c.c[1] = 0b0101; c.c[2] = 0b1111
|
||||||
|
|
||||||
|
assertEquals("class [B", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "binary")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfShort() {
|
||||||
|
class C(val c: Array<Short>)
|
||||||
|
|
||||||
|
val c = C(arrayOf(1, 2, 3))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Short;", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "short[]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testShortArray() {
|
||||||
|
class C(val c: ShortArray)
|
||||||
|
|
||||||
|
val c = C(ShortArray(3))
|
||||||
|
c.c[0] = 1; c.c[1] = 2; c.c[2] = 5
|
||||||
|
|
||||||
|
assertEquals("class [S", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "short[p]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfLong() {
|
||||||
|
class C(val c: Array<Long>)
|
||||||
|
|
||||||
|
val c = C(arrayOf(2147483650, -2147483800, 10))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Long;", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "long[]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testLongArray() {
|
||||||
|
class C(val c: LongArray)
|
||||||
|
|
||||||
|
val c = C(LongArray(3))
|
||||||
|
c.c[0] = 2147483650; c.c[1] = -2147483800; c.c[2] = 10
|
||||||
|
|
||||||
|
assertEquals("class [J", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "long[p]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfFloat() {
|
||||||
|
class C(val c: Array<Float>)
|
||||||
|
|
||||||
|
val c = C(arrayOf(10F, 100.023232F, -1455.433400F))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Float;", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "float[]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFloatArray() {
|
||||||
|
class C(val c: FloatArray)
|
||||||
|
|
||||||
|
val c = C(FloatArray(3))
|
||||||
|
c.c[0] = 10F; c.c[1] = 100.023232F; c.c[2] = -1455.433400F
|
||||||
|
|
||||||
|
assertEquals("class [F", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "float[p]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArrayOfDouble() {
|
||||||
|
class C(val c: Array<Double>)
|
||||||
|
|
||||||
|
val c = C(arrayOf(10.0, 100.2, -1455.2))
|
||||||
|
|
||||||
|
assertEquals("class [Ljava.lang.Double;", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "double[]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDoubleArray() {
|
||||||
|
class C(val c: DoubleArray)
|
||||||
|
|
||||||
|
val c = C(DoubleArray(3))
|
||||||
|
c.c[0] = 10.0; c.c[1] = 100.2; c.c[2] = -1455.2
|
||||||
|
|
||||||
|
assertEquals("class [D", c.c::class.java.toString())
|
||||||
|
assertEquals(SerializerFactory.nameForType(c.c::class.java), "double[p]")
|
||||||
|
|
||||||
|
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
|
||||||
|
|
||||||
|
assertEquals(c.c.size, deserializedC.c.size)
|
||||||
|
assertEquals(c.c[0], deserializedC.c[0])
|
||||||
|
assertEquals(c.c[1], deserializedC.c[1])
|
||||||
|
assertEquals(c.c[2], deserializedC.c[2])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user