@@ -2,11 +2,15 @@ package nl.tudelft.ipv8.messaging
2
2
3
3
import java.nio.Buffer
4
4
import java.nio.ByteBuffer
5
+ import kotlin.reflect.full.isSubclassOf
6
+ import kotlin.reflect.full.memberProperties
7
+ import kotlin.reflect.full.primaryConstructor
5
8
6
9
const val SERIALIZED_USHORT_SIZE = 2
7
10
const val SERIALIZED_UINT_SIZE = 4
11
+ const val SERIALIZED_INT_SIZE = 4
8
12
const val SERIALIZED_ULONG_SIZE = 8
9
- const val SERIALIZED_LONG_SIZE = 4
13
+ const val SERIALIZED_LONG_SIZE = 8
10
14
const val SERIALIZED_UBYTE_SIZE = 1
11
15
12
16
const val SERIALIZED_PUBLIC_KEY_SIZE = 74
@@ -20,6 +24,81 @@ interface Serializable {
20
24
21
25
interface Deserializable <T > {
22
26
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))
23
102
}
24
103
25
104
fun serializeBool (data : Boolean ): ByteArray {
@@ -40,10 +119,21 @@ fun serializeUShort(value: Int): ByteArray {
40
119
return bytes
41
120
}
42
121
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
+
43
128
fun deserializeUShort (buffer : ByteArray , offset : Int = 0): Int {
44
129
return (((buffer[offset].toInt() and 0xFF ) shl 8 ) or (buffer[offset + 1 ].toInt() and 0xFF ))
45
130
}
46
131
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
+
47
137
fun serializeUInt (value : UInt ): ByteArray {
48
138
val bytes = UByteArray (SERIALIZED_UINT_SIZE )
49
139
for (i in 0 until SERIALIZED_UINT_SIZE ) {
@@ -80,7 +170,7 @@ fun deserializeULong(buffer: ByteArray, offset: Int = 0): ULong {
80
170
81
171
fun serializeLong (value : Long ): ByteArray {
82
172
val buffer = ByteBuffer .allocate(SERIALIZED_LONG_SIZE )
83
- buffer.putInt (value.toInt() )
173
+ buffer.putLong (value)
84
174
return buffer.array()
85
175
}
86
176
@@ -89,7 +179,20 @@ fun deserializeLong(bytes: ByteArray, offset: Int = 0): Long {
89
179
buffer.put(bytes.copyOfRange(offset, offset + SERIALIZED_LONG_SIZE ))
90
180
// In JDK 8 this returns a Buffer.
91
181
(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
93
196
}
94
197
95
198
fun serializeUChar (char : UByte ): ByteArray {
@@ -107,8 +210,10 @@ fun serializeVarLen(bytes: ByteArray): ByteArray {
107
210
108
211
fun deserializeVarLen (buffer : ByteArray , offset : Int = 0): Pair <ByteArray , Int > {
109
212
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
+ )
112
217
return Pair (payload, SERIALIZED_UINT_SIZE + len)
113
218
}
114
219
@@ -117,19 +222,31 @@ fun deserializeRecursively(buffer: ByteArray, offset: Int = 0): Array<ByteArray>
117
222
return arrayOf()
118
223
}
119
224
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
+ )
124
235
}
125
236
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> {
127
242
val returnValues = arrayListOf<ByteArray >()
128
243
var localOffset = offset
129
244
for (i in 0 until amount) {
130
245
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
+ )
133
250
localOffset + = SERIALIZED_UINT_SIZE + len
134
251
returnValues.add(payload)
135
252
}
0 commit comments