blob: 36e2452f308f6ac5b24b87d09e0bc352e764c116 [file] [log] [blame]
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.experimental.io.jvm.nio
import kotlinx.coroutines.experimental.io.*
import java.nio.channels.*
/**
* Copies up to [limit] bytes from blocking NIO channel to CIO [ch]. It does suspend if no space available for writing
* in the destination channel but may block if source NIO channel blocks.
*
* @return number of bytes were copied
*/
suspend fun ReadableByteChannel.copyTo(ch: ByteWriteChannel, limit: Long = Long.MAX_VALUE): Long {
require(limit >= 0L) { "Limit shouldn't be negative: $limit" }
if (this is SelectableChannel && !isBlocking) {
throw IllegalArgumentException("Non-blocking channels are not supported")
}
var copied = 0L
var eof = false
val copy: (ByteBuffer) -> Unit = { bb ->
val rem = limit - copied
if (rem < bb.remaining()) {
val l = bb.limit()
bb.limit(bb.position() + rem.toInt())
val rc = read(bb)
if (rc == -1) eof = true
else copied += rc
bb.limit(l)
} else {
val rc = read(bb)
if (rc == -1) eof = true
else copied += rc
}
}
val needFlush = !ch.autoFlush
while (copied < limit && !eof) {
ch.write(1, copy)
if (needFlush) ch.flush()
}
return copied
}
/**
* Copies up to [limit] bytes from a blocking NIO pipe to CIO [ch]. A shortcut to copyTo with
* NIO readable channel receiver
*
* @return number of bytes copied
*/
suspend fun Pipe.copyTo(ch: ByteWriteChannel, limit: Long = Long.MAX_VALUE): Long = source().copyTo(ch, limit)