1
+ import org.msgpack.core.MessagePack
2
+ import org.msgpack.core.buffer.ArrayBufferInput
3
+ import org.msgpack.core.buffer.ArrayBufferOutput
4
+
5
+ /* *
6
+ * NOT THREAD SAFE
7
+ */
8
+ class Packer (val transform : (buffer: ByteArray , len: Int ) -> String ) {
9
+ private var buffer: ByteArray = ByteArray (256 )
10
+ private val unpacker = MessagePack .newDefaultUnpacker(buffer)
11
+ private val packer = MessagePack .newDefaultBufferPacker()
12
+ private val output = ArrayBufferOutput (256 )
13
+
14
+ /* *
15
+ * Creates new msgpack array from `packed`
16
+ *
17
+ * Value to transform must be at index 1 (second item)
18
+ * Transformed value will be returned at index 2 (third item)
19
+ * `packed` must have nil at index 2
20
+ *
21
+ * The returned array will have the same number of items as `packed`
22
+ * items at index 0, 1, 3+ will be reproduced exactly as is
23
+ * index 2 will be the only difference between the two arrays
24
+ *
25
+ * @param packed an encoded msgpack array
26
+ * @return an encoded msgpack array
27
+ */
28
+ fun repack (packed : ByteArray ): ByteArray {
29
+ // reset everything
30
+ val unpacker = unpacker
31
+ val packer = packer
32
+ unpacker.reset(ArrayBufferInput (packed))
33
+ packer.reset(output) // TODO make sure we're not shrinking
34
+
35
+
36
+ // array length
37
+ packer.packArrayHeader(unpacker.unpackArrayHeader())
38
+
39
+ // index 0 MUST int (version)
40
+ packer.packInt(unpacker.unpackInt())
41
+
42
+ // index 1 MUST byte array
43
+ val len = unpacker.unpackBinaryHeader()
44
+ val buffer = getBuffer(len)
45
+ unpacker.readPayload(buffer, 0 , len)
46
+ packer.packBinaryHeader(len)
47
+ packer.writePayload(buffer, 0 , len)
48
+
49
+ // index 2 transform result
50
+ val result = transform(buffer, len)
51
+ packer.packString(result)
52
+ unpacker.unpackNil()
53
+
54
+ // (cheat and) copy the rest verbatim
55
+ val remaining = packed.size - unpacker.totalReadBytes
56
+ packer.writePayload(packed, unpacker.totalReadBytes as Int , remaining as Int )
57
+
58
+ return packer.toByteArray()
59
+ }
60
+
61
+ private fun getBuffer (len : Int ): ByteArray {
62
+ var buffer = buffer
63
+ if (buffer.size >= len)
64
+ return buffer
65
+
66
+ // use next power of 2
67
+ buffer = ByteArray (Integer .highestOneBit(len) * 2 )
68
+ this .buffer = buffer
69
+ return buffer
70
+ }
71
+ }
0 commit comments