Skip to content

Commit f64ef93

Browse files
author
Sergey Mashkov
committed
IO: implement byte packet copy
1 parent ea3a418 commit f64ef93

File tree

5 files changed

+55
-0
lines changed

5 files changed

+55
-0
lines changed

core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/packet/ByteReadPacket.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ interface ByteReadPacket {
3333
}
3434

3535
fun release()
36+
fun copy(): ByteReadPacket
3637

3738
fun readUTF8LineTo(out: Appendable, limit: Int = Int.MAX_VALUE): Boolean
3839

core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/packet/ByteReadPacketEmpty.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ object ByteReadPacketEmpty : ByteReadPacket {
4848
override fun release() {
4949
}
5050

51+
override fun copy() = this
52+
5153
override fun readUTF8LineTo(out: Appendable, limit: Int) = false
5254

5355
override fun inputStream(): InputStream = EmptyInputStream

core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/packet/ByteReadPacketImpl.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ internal class ByteReadPacketImpl(private val packets: ArrayDeque<ByteBuffer>, i
5050

5151
override fun readFully(dst: ByteArray, offset: Int, length: Int) {
5252
val rc = readAvailable(dst, offset, length)
53+
if (rc == -1 && length == 0) return
5354
if (rc < length) throw EOFException("Not enough bytes in the packet")
5455
}
5556

@@ -232,6 +233,17 @@ internal class ByteReadPacketImpl(private val packets: ArrayDeque<ByteBuffer>, i
232233
}
233234
}
234235

236+
override fun copy(): ByteReadPacket {
237+
if (packets.isEmpty()) return ByteReadPacketEmpty
238+
val copyDeque = ArrayDeque<ByteBuffer>(packets.size)
239+
240+
for (p in packets) {
241+
copyDeque.add(pool.borrow().also { it.put(p.duplicate()); it.flip() })
242+
}
243+
244+
return ByteReadPacketImpl(copyDeque, pool)
245+
}
246+
235247
private inline fun reading(size: Int, block: (ByteBuffer) -> Boolean): Boolean {
236248
if (packets.isEmpty()) return false
237249

core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/packet/ByteReadPacketSingle.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package kotlinx.coroutines.experimental.io.packet
22

3+
import kotlinx.coroutines.experimental.io.*
34
import kotlinx.coroutines.experimental.io.internal.ObjectPool
45
import kotlinx.coroutines.experimental.io.internal.decodeUTF8
56
import java.io.*
@@ -225,6 +226,14 @@ internal class ByteReadPacketSingle(private var buffer: ByteBuffer?, internal va
225226
buffer = null
226227
}
227228

229+
override fun copy(): ByteReadPacket {
230+
val bb = buffer?.takeIf { it.hasRemaining() } ?: return ByteReadPacketEmpty
231+
val copyBuffer = pool.borrow()
232+
copyBuffer.put(bb.duplicate())
233+
copyBuffer.flip()
234+
return ByteReadPacketSingle(copyBuffer, pool)
235+
}
236+
228237
private inline fun reading(block: (ByteBuffer) -> Unit): Boolean {
229238
val buffer = buffer ?: return false
230239

core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/BytePacketReaderWriterTest.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,4 +274,35 @@ class BytePacketReaderWriterTest {
274274

275275
assertTrue { bb.contentEquals(p.readBytes()) }
276276
}
277+
278+
@Test
279+
fun testCopySingleBufferPacket() {
280+
val bb = ByteArray(100)
281+
Random().nextBytes(bb)
282+
283+
val p = buildPacket {
284+
writeFully(bb)
285+
}
286+
287+
val copy = p.copy()
288+
assertEquals(p.remaining, p.remaining)
289+
assertTrue { p.readBytes().contentEquals(copy.readBytes()) }
290+
}
291+
292+
@Test
293+
fun testCopyMultipleBufferPacket() {
294+
val bb = ByteArray(1000000)
295+
Random().nextBytes(bb)
296+
297+
val p = buildPacket {
298+
writeFully(bb)
299+
}
300+
301+
val copy = p.copy()
302+
assertEquals(p.remaining, p.remaining)
303+
val bytes = p.readBytes()
304+
val copied = copy.readBytes()
305+
306+
assertTrue { bytes.contentEquals(copied) }
307+
}
277308
}

0 commit comments

Comments
 (0)