Asynchronous I/O library for Kotlin multiplatform providing channels, streams, and byte manipulation utilities optimized for watchOS ARM64
—
Core asynchronous I/O functionality providing single-reader/single-writer channels for non-blocking byte operations with coroutine integration.
Single-reader asynchronous byte channel for reading sequences of bytes with coroutine support.
/**
* Channel for asynchronous reading of sequences of bytes.
* This is a single-reader channel where operations cannot be invoked concurrently.
*/
interface ByteReadChannel {
/** Number of bytes available for reading without suspension */
val availableForRead: Int
/** True if channel is closed and no remaining bytes are available */
val isClosedForRead: Boolean
/** True if channel is closed for writing */
val isClosedForWrite: Boolean
/** Closure exception or null if closed successfully or not yet closed */
val closedCause: Throwable?
/** Total number of bytes read from the channel */
val totalBytesRead: Long
/**
* Reads available bytes to dst buffer, returns immediately or suspends if no bytes available
* @param dst destination byte array
* @param offset starting position in dst array
* @param length maximum number of bytes to read
* @return number of bytes read or -1 if channel is closed
*/
suspend fun readAvailable(dst: ByteArray, offset: Int, length: Int): Int
/**
* Reads exactly length bytes to dst buffer or fails if channel is closed
* @param dst destination byte array
* @param offset starting position in dst array
* @param length exact number of bytes to read
*/
suspend fun readFully(dst: ByteArray, offset: Int, length: Int)
/** Read a single byte, suspending if necessary */
suspend fun readByte(): Byte
/** Read a 16-bit short value in big-endian byte order */
suspend fun readShort(): Short
/** Read a 32-bit int value in big-endian byte order */
suspend fun readInt(): Int
/** Read a 64-bit long value in big-endian byte order */
suspend fun readLong(): Long
/** Read a 32-bit float value in big-endian byte order */
suspend fun readFloat(): Float
/** Read a 64-bit double value in big-endian byte order */
suspend fun readDouble(): Double
/** Read a boolean value (0 = false, non-zero = true) */
suspend fun readBoolean(): Boolean
/**
* Read a UTF-8 encoded line of text
* @param limit maximum line length in characters
* @return line string or null if end of input
*/
suspend fun readUTF8Line(limit: Int = Int.MAX_VALUE): String?
/**
* Read specified number of bytes into a new packet
* @param size number of bytes to read
* @return new ByteReadPacket containing the data
*/
suspend fun readPacket(size: Int): ByteReadPacket
/**
* Read all remaining bytes into a packet
* @param limit maximum number of bytes to read
* @return packet with remaining data
*/
suspend fun readRemaining(limit: Long = Long.MAX_VALUE): ByteReadPacket
/**
* Discard up to max bytes from the channel
* @param max maximum number of bytes to discard
* @return actual number of bytes discarded
*/
suspend fun discard(max: Long = Long.MAX_VALUE): Long
/** Wait for at least one byte to become available */
suspend fun awaitContent()
/**
* Cancel the channel with optional cause
* @param cause optional cancellation cause
* @return true if channel was cancelled, false if already closed
*/
fun cancel(cause: Throwable? = null): Boolean
companion object {
/** Empty channel that immediately returns EOF */
val Empty: ByteReadChannel
}
}Usage Examples:
import io.ktor.utils.io.*
import kotlinx.coroutines.*
// Reading from a channel
runBlocking {
val channel: ByteReadChannel = ByteReadChannel("Hello World".toByteArray())
// Read individual bytes
val firstByte = channel.readByte()
// Read into buffer
val buffer = ByteArray(5)
val bytesRead = channel.readAvailable(buffer, 0, buffer.size)
// Read remaining as packet
val packet = channel.readRemaining()
// Read UTF-8 text line
val textChannel = ByteReadChannel("Line 1\nLine 2\n")
val line1 = textChannel.readUTF8Line()
val line2 = textChannel.readUTF8Line()
}Single-writer asynchronous byte channel for writing sequences of bytes with coroutine support.
/**
* Channel for asynchronous writing of sequences of bytes.
* This is a single-writer channel where operations cannot be invoked concurrently,
* except for close() and flush() which can be called at any time.
*/
interface ByteWriteChannel {
/** Number of bytes that can be written without suspension */
val availableForWrite: Int
/** True if channel is closed for writing */
val isClosedForWrite: Boolean
/** True if channel flushes automatically after every write */
val autoFlush: Boolean
/** Total number of bytes written to the channel */
val totalBytesWritten: Long
/** Closure exception or null if closed successfully or not yet closed */
val closedCause: Throwable?
/**
* Write as many bytes as possible from src, suspending only if buffer is full
* @param src source byte array
* @param offset starting position in src array
* @param length maximum number of bytes to write
* @return number of bytes actually written
*/
suspend fun writeAvailable(src: ByteArray, offset: Int, length: Int): Int
/**
* Write all bytes from src, suspending as necessary
* @param src source byte array
* @param offset starting position in src array
* @param length exact number of bytes to write
*/
suspend fun writeFully(src: ByteArray, offset: Int, length: Int)
/** Write a single byte */
suspend fun writeByte(b: Byte)
/** Write a 16-bit short value in big-endian byte order */
suspend fun writeShort(s: Short)
/** Write a 32-bit int value in big-endian byte order */
suspend fun writeInt(i: Int)
/** Write a 64-bit long value in big-endian byte order */
suspend fun writeLong(l: Long)
/** Write a 32-bit float value in big-endian byte order */
suspend fun writeFloat(f: Float)
/** Write a 64-bit double value in big-endian byte order */
suspend fun writeDouble(d: Double)
/**
* Write all bytes from a packet to the channel
* @param packet source packet to write
*/
suspend fun writePacket(packet: ByteReadPacket)
/**
* Close the channel, optionally with a cause
* @param cause optional close cause
* @return true if channel was closed, false if already closed
*/
fun close(cause: Throwable? = null): Boolean
/** Flush any pending data immediately */
fun flush()
/** Wait for space to become available for writing */
suspend fun awaitFreeSpace()
}Usage Examples:
import io.ktor.utils.io.*
import kotlinx.coroutines.*
// Writing to a channel
runBlocking {
val channel = ByteChannel()
// Write individual bytes and primitives
channel.writeByte(0x42)
channel.writeInt(12345)
channel.writeFloat(3.14f)
// Write byte arrays
val data = "Hello World".toByteArray()
channel.writeFully(data, 0, data.size)
// Write packets
val packet = buildPacket {
writeText("Packet content")
writeInt(999)
}
channel.writePacket(packet)
// Ensure data is flushed
channel.flush()
channel.close()
}Combined read/write channel interface that extends both ByteReadChannel and ByteWriteChannel.
/**
* Channel for asynchronous reading and writing of sequences of bytes.
* This is a buffered single-reader single-writer channel.
* @deprecated Use separate ByteReadChannel and ByteWriteChannel instead
*/
@Deprecated("Use ByteReadChannel and ByteWriteChannel instead")
interface ByteChannel : ByteReadChannel, ByteWriteChannel {
/**
* Attach a Job to this channel for lifecycle management
* @param job coroutine job to attach
*/
fun attachJob(job: Job)
}Factory functions for creating various types of byte channels.
/**
* Create a buffered channel for asynchronous reading and writing
* @param autoFlush whether to flush automatically after each write
* @return new ByteChannel instance
*/
@Deprecated("Use ByteReadChannel and ByteWriteChannel instead")
fun ByteChannel(autoFlush: Boolean = false): ByteChannel
/**
* Create a read-only channel from a byte array
* @param content source byte array (may be used directly or copied)
* @return ByteReadChannel for reading the content
*/
fun ByteReadChannel(content: ByteArray): ByteReadChannel
/**
* Create a read-only channel from part of a byte array
* @param content source byte array
* @param offset starting position in the array
* @param length number of bytes to use
* @return ByteReadChannel for reading the content
*/
fun ByteReadChannel(content: ByteArray, offset: Int, length: Int): ByteReadChannel
/**
* Create a read-only channel from a text string
* @param text string to convert to bytes
* @param charset character encoding to use (default UTF-8)
* @return ByteReadChannel for reading the encoded text
*/
fun ByteReadChannel(text: String, charset: Charset = Charsets.UTF_8): ByteReadChannelUtility extensions for enhanced channel operations including byte order support and channel-to-channel copying.
/** Read 16-bit short with specified byte order */
suspend fun ByteReadChannel.readShort(byteOrder: ByteOrder): Short
/** Read 32-bit int with specified byte order */
suspend fun ByteReadChannel.readInt(byteOrder: ByteOrder): Int
/** Read 64-bit long with specified byte order */
suspend fun ByteReadChannel.readLong(byteOrder: ByteOrder): Long
/** Read 32-bit float with specified byte order */
suspend fun ByteReadChannel.readFloat(byteOrder: ByteOrder): Float
/** Read 64-bit double with specified byte order */
suspend fun ByteReadChannel.readDouble(byteOrder: ByteOrder): Double
/** Read 16-bit short in little-endian byte order */
suspend fun ByteReadChannel.readShortLittleEndian(): Short
/** Read 32-bit int in little-endian byte order */
suspend fun ByteReadChannel.readIntLittleEndian(): Int
/** Read 64-bit long in little-endian byte order */
suspend fun ByteReadChannel.readLongLittleEndian(): Long
/** Read 32-bit float in little-endian byte order */
suspend fun ByteReadChannel.readFloatLittleEndian(): Float
/** Read 64-bit double in little-endian byte order */
suspend fun ByteReadChannel.readDoubleLittleEndian(): Double
/**
* Copy all data from this channel to destination channel
* @param dst destination channel
* @return total bytes copied
*/
suspend fun ByteReadChannel.copyTo(dst: ByteWriteChannel): Long
/**
* Copy up to limit bytes from this channel to destination
* @param dst destination channel
* @param limit maximum bytes to copy
* @return actual bytes copied
*/
suspend fun ByteReadChannel.copyTo(dst: ByteWriteChannel, limit: Long): Long
/**
* Copy data and close destination when done
* @param dst destination channel to close after copying
* @param limit maximum bytes to copy
* @return actual bytes copied
*/
suspend fun ByteReadChannel.copyAndClose(dst: ByteWriteChannel, limit: Long): Long
/**
* Join this channel to destination channel
* @param dst destination channel
* @param closeOnEnd whether to close destination when source ends
*/
suspend fun ByteReadChannel.joinTo(dst: ByteWriteChannel, closeOnEnd: Boolean)Usage Examples for Extensions:
import io.ktor.utils.io.*
import io.ktor.utils.io.bits.ByteOrder
import kotlinx.coroutines.*
runBlocking {
val source = ByteReadChannel(ByteArray(1024) { it.toByte() })
val destination = ByteChannel()
// Copy data between channels
val bytesCopied = source.copyTo(destination, limit = 512)
// Read with different byte orders
val bigEndianInt = destination.readInt() // Default big-endian
val littleEndianInt = destination.readIntLittleEndian()
val customOrderInt = destination.readInt(ByteOrder.LITTLE_ENDIAN)
}Install with Tessl CLI
npx tessl i tessl/maven-io-ktor--ktor-io-watchosarm64