@@ -2,11 +2,15 @@ package nl.tudelft.ipv8.messaging
22
33import java.nio.Buffer
44import java.nio.ByteBuffer
5+ import kotlin.reflect.full.isSubclassOf
6+ import kotlin.reflect.full.memberProperties
7+ import kotlin.reflect.full.primaryConstructor
58
69const val SERIALIZED_USHORT_SIZE = 2
710const val SERIALIZED_UINT_SIZE = 4
11+ const val SERIALIZED_INT_SIZE = 4
812const val SERIALIZED_ULONG_SIZE = 8
9- const val SERIALIZED_LONG_SIZE = 4
13+ const val SERIALIZED_LONG_SIZE = 8
1014const val SERIALIZED_UBYTE_SIZE = 1
1115
1216const val SERIALIZED_PUBLIC_KEY_SIZE = 74
@@ -20,6 +24,81 @@ interface Serializable {
2024
2125interface Deserializable <T > {
2226 fun deserialize (buffer : ByteArray , offset : Int = 0): Pair <T , Int >
27+
28+ }
29+
30+ /* *
31+ * Serializes the object and returns the buffer.
32+ * Alternative to manually defining the serialize function.
33+ */
34+ interface AutoSerializable : Serializable {
35+ override fun serialize (): ByteArray {
36+ return this ::class .primaryConstructor!! .parameters.map { param ->
37+ val value =
38+ this .javaClass.kotlin.memberProperties.find { it.name == param.name }!! .get(this )
39+ simpleSerialize(value)
40+ }.reduce { acc, bytes -> acc + bytes }
41+ }
42+ }
43+
44+ // /**
45+ // * Deserializes the object from the buffer and returns the object and the new offset.
46+ // * Alternative to manually defining the deserialize function.
47+ // */
48+ // inline fun <reified T> Deserializable<T>.autoDeserialize(buffer: ByteArray, offset: Int = 0): Pair<T, Int> {
49+ // TODO()
50+ // }
51+
52+ fun <U > simpleSerialize (data : U ): ByteArray {
53+ return when (data) {
54+ is Int -> serializeInt(data)
55+ is Long -> serializeLong(data)
56+ is UByte -> serializeUChar(data)
57+ is UInt -> serializeUInt(data)
58+ is UShort -> serializeUShort(data.toInt())
59+ is ULong -> serializeULong(data)
60+ is String -> serializeVarLen(data.toByteArray())
61+ is ByteArray -> serializeVarLen(data)
62+ is Boolean -> serializeBool(data)
63+ is Enum <* > -> serializeUInt(data.ordinal.toUInt())
64+ is Serializable -> data.serialize()
65+ else -> throw IllegalArgumentException (" Unsupported serialization type" )
66+ }
67+ }
68+
69+ inline fun <reified U > simpleDeserialize (buffer : ByteArray , offset : Int = 0): Pair <U , Int > {
70+ val (value, off) = when (U ::class ) {
71+ Int ::class -> Pair (deserializeInt(buffer, offset) as U , SERIALIZED_INT_SIZE )
72+ Long ::class -> Pair (deserializeLong(buffer, offset) as U , SERIALIZED_LONG_SIZE )
73+ UByte ::class -> Pair (deserializeUChar(buffer, offset) as U , SERIALIZED_UBYTE_SIZE )
74+ UShort ::class -> Pair (
75+ deserializeUShort(buffer, offset).toUShort() as U ,
76+ SERIALIZED_USHORT_SIZE
77+ )
78+
79+ UInt ::class -> Pair (deserializeUInt(buffer, offset) as U , SERIALIZED_UINT_SIZE )
80+ ULong ::class -> Pair (deserializeULong(buffer, offset) as U , SERIALIZED_ULONG_SIZE )
81+ String ::class -> {
82+ val (data, len) = deserializeVarLen(buffer, offset)
83+ Pair (data.decodeToString() as U , len)
84+ }
85+
86+ ByteArray ::class -> {
87+ val (data, len) = deserializeVarLen(buffer, offset)
88+ Pair (data as U , len)
89+ }
90+
91+ Boolean ::class -> Pair (deserializeBool(buffer, offset) as U , 1 )
92+ else -> {
93+ println (" Enum: ${U ::class .qualifiedName} " )
94+ if (U ::class .isSubclassOf(Enum ::class )) {
95+ val ordinal = deserializeUInt(buffer, offset).toInt()
96+ val values = U ::class .java.enumConstants
97+ Pair (values[ordinal] as U , SERIALIZED_UINT_SIZE )
98+ } else throw IllegalArgumentException (" Unsupported deserialization type" )
99+ }
100+ }
101+ return (value to (offset + off))
23102}
24103
25104fun serializeBool (data : Boolean ): ByteArray {
@@ -40,10 +119,21 @@ fun serializeUShort(value: Int): ByteArray {
40119 return bytes
41120}
42121
122+ fun serializeUShort (value : UShort ): ByteArray {
123+ val bytes = ByteBuffer .allocate(SERIALIZED_USHORT_SIZE )
124+ bytes.putShort(value.toShort())
125+ return bytes.array()
126+ }
127+
43128fun deserializeUShort (buffer : ByteArray , offset : Int = 0): Int {
44129 return (((buffer[offset].toInt() and 0xFF ) shl 8 ) or (buffer[offset + 1 ].toInt() and 0xFF ))
45130}
46131
132+ fun deserializeRealUShort (buffer : ByteArray , offset : Int = 0): UShort {
133+ val buf = ByteBuffer .wrap(buffer, offset, SERIALIZED_USHORT_SIZE )
134+ return buf.short.toUShort()
135+ }
136+
47137fun serializeUInt (value : UInt ): ByteArray {
48138 val bytes = UByteArray (SERIALIZED_UINT_SIZE )
49139 for (i in 0 until SERIALIZED_UINT_SIZE ) {
@@ -80,7 +170,7 @@ fun deserializeULong(buffer: ByteArray, offset: Int = 0): ULong {
80170
81171fun serializeLong (value : Long ): ByteArray {
82172 val buffer = ByteBuffer .allocate(SERIALIZED_LONG_SIZE )
83- buffer.putInt (value.toInt() )
173+ buffer.putLong (value)
84174 return buffer.array()
85175}
86176
@@ -89,7 +179,20 @@ fun deserializeLong(bytes: ByteArray, offset: Int = 0): Long {
89179 buffer.put(bytes.copyOfRange(offset, offset + SERIALIZED_LONG_SIZE ))
90180 // In JDK 8 this returns a Buffer.
91181 (buffer as Buffer ).flip()
92- return buffer.int.toLong()
182+ return buffer.long
183+ }
184+
185+ fun serializeInt (value : Int ): ByteArray {
186+ val buffer = ByteBuffer .allocate(SERIALIZED_INT_SIZE )
187+ buffer.putInt(value)
188+ return buffer.array()
189+ }
190+
191+ fun deserializeInt (bytes : ByteArray , offset : Int = 0): Int {
192+ val buffer = ByteBuffer .allocate(SERIALIZED_INT_SIZE )
193+ buffer.put(bytes.copyOfRange(offset, offset + SERIALIZED_INT_SIZE ))
194+ buffer.flip()
195+ return buffer.int
93196}
94197
95198fun serializeUChar (char : UByte ): ByteArray {
@@ -107,8 +210,10 @@ fun serializeVarLen(bytes: ByteArray): ByteArray {
107210
108211fun deserializeVarLen (buffer : ByteArray , offset : Int = 0): Pair <ByteArray , Int > {
109212 val len = deserializeUInt(buffer, offset).toInt()
110- val payload = buffer.copyOfRange(offset + SERIALIZED_UINT_SIZE ,
111- offset + SERIALIZED_UINT_SIZE + len)
213+ val payload = buffer.copyOfRange(
214+ offset + SERIALIZED_UINT_SIZE ,
215+ offset + SERIALIZED_UINT_SIZE + len
216+ )
112217 return Pair (payload, SERIALIZED_UINT_SIZE + len)
113218}
114219
@@ -117,19 +222,31 @@ fun deserializeRecursively(buffer: ByteArray, offset: Int = 0): Array<ByteArray>
117222 return arrayOf()
118223 }
119224 val len = deserializeUInt(buffer, offset).toInt()
120- val payload = buffer.copyOfRange(offset + SERIALIZED_UINT_SIZE ,
121- offset + SERIALIZED_UINT_SIZE + len)
122- return arrayOf(payload) + deserializeRecursively(buffer.copyOfRange(offset + SERIALIZED_UINT_SIZE + len,
123- buffer.size), offset)
225+ val payload = buffer.copyOfRange(
226+ offset + SERIALIZED_UINT_SIZE ,
227+ offset + SERIALIZED_UINT_SIZE + len
228+ )
229+ return arrayOf(payload) + deserializeRecursively(
230+ buffer.copyOfRange(
231+ offset + SERIALIZED_UINT_SIZE + len,
232+ buffer.size
233+ ), offset
234+ )
124235}
125236
126- fun deserializeAmount (buffer : ByteArray , amount : Int , offset : Int = 0): Pair <Array <ByteArray >, ByteArray> {
237+ fun deserializeAmount (
238+ buffer : ByteArray ,
239+ amount : Int ,
240+ offset : Int = 0
241+ ): Pair <Array <ByteArray >, ByteArray> {
127242 val returnValues = arrayListOf<ByteArray >()
128243 var localOffset = offset
129244 for (i in 0 until amount) {
130245 val len = deserializeUInt(buffer, localOffset).toInt()
131- val payload = buffer.copyOfRange(localOffset + SERIALIZED_UINT_SIZE ,
132- localOffset + SERIALIZED_UINT_SIZE + len)
246+ val payload = buffer.copyOfRange(
247+ localOffset + SERIALIZED_UINT_SIZE ,
248+ localOffset + SERIALIZED_UINT_SIZE + len
249+ )
133250 localOffset + = SERIALIZED_UINT_SIZE + len
134251 returnValues.add(payload)
135252 }
0 commit comments