Repository: ktorio/ktor
File: ktor-io/common/src/io/ktor/utils/io/ByteReadChannelOperations.kt (Kotlin)

Code before:

    return true
}

@OptIn(InternalAPI::class, UnsafeIoApi::class, InternalIoApi::class)
public suspend inline fun ByteReadChannel.read(crossinline block: suspend (ByteArray, Int, Int) -> Int): Int {
    if (isClosedForRead) return -1
    if (readBuffer.exhausted()) awaitContent()
    if (isClosedForRead) return -1

    var result: Int
    UnsafeBufferOperations.readFromHead(readBuffer.buffer) { array, start, endExclusive ->
        result = block(array, start, endExclusive)
        result
    }

    return result
}

@OptIn(InternalAPI::class, InternalIoApi::class)
public val ByteReadChannel.availableForRead: Int
    get() = readBuffer.buffer.size.toInt()


/**
 * Reads bytes available bytes into the provided [out] buffer, or fails
 * if the channel has been closed.
 *
 * Suspension occurs when there are not enough bytes available in the channel.
 */
public suspend fun ByteReadChannel.readFully(out: ByteArray) {
    readFully(out, 0, out.size)
}

/**
 * Reads bytes from [start] to [end] into the provided [out] buffer, or fails
 * if the channel has been closed.
 *
 * Suspension occurs when there are not enough bytes available in the channel.
 */
@OptIn(InternalAPI::class)
public suspend fun ByteReadChannel.readFully(out: ByteArray, start: Int, end: Int) {
    if (isClosedForRead) throw EOFException("Channel is already closed")

    var offset = start
    while (offset < end) {
        if (readBuffer.exhausted()) awaitContent()
        if (isClosedForRead) throw EOFException("Channel is already closed")

        val count = min(end - offset, readBuffer.remaining.toInt())
        readBuffer.readTo(out, offset, offset + count)

Review comment (bug):
Nit: typo
```suggestion
 * Reads all available bytes into the provided [out] buffer, or fails
```

Code after:
    return true
}

@OptIn(InternalAPI::class, UnsafeIoApi::class, InternalIoApi::class)
public suspend inline fun ByteReadChannel.read(crossinline block: suspend (ByteArray, Int, Int) -> Int): Int {
    if (isClosedForRead) return -1
    if (readBuffer.exhausted()) awaitContent()
    if (isClosedForRead) return -1

    var result: Int
    UnsafeBufferOperations.readFromHead(readBuffer.buffer) { array, start, endExclusive ->
        result = block(array, start, endExclusive)
        result
    }

    return result
}

@OptIn(InternalAPI::class, InternalIoApi::class)
public val ByteReadChannel.availableForRead: Int
    get() = readBuffer.buffer.size.toInt()

/**
 * Reads bytes from [start] to [end] into the provided [out] buffer, or fails
 * if the channel has been closed.
 *
 * Suspension occurs when there are not enough bytes available in the channel.
 *
 * @param out the buffer to write to
 * @param start the index to start writing at
 * @param end the index to write until
 */
@OptIn(InternalAPI::class)
public suspend fun ByteReadChannel.readFully(out: ByteArray, start: Int = 0, end: Int = out.size) {
    if (isClosedForRead) throw EOFException("Channel is already closed")

    var offset = start
    while (offset < end) {
        if (readBuffer.exhausted()) awaitContent()
        if (isClosedForRead) throw EOFException("Channel is already closed")

        val count = min(end - offset, readBuffer.remaining.toInt())
        readBuffer.readTo(out, offset, offset + count)
        offset += count
    }
}

@InternalAPI
public fun ByteReadChannel.rethrowCloseCauseIfNeeded() {
    closedCause?.let { throw it }
}