Asynchronous I/O library for Kotlin multiplatform providing channels, streams, and byte manipulation utilities optimized for watchOS ARM64
—
Byte order manipulation and primitive type conversion utilities supporting both big-endian and little-endian operations.
Extension functions for reversing byte order of primitive types to convert between big-endian and little-endian representations.
/**
* Reverse the byte order of a 16-bit short value.
* Converts between big-endian and little-endian representations.
* @return short with reversed byte order
*/
fun Short.reverseByteOrder(): Short
/**
* Reverse the byte order of a 32-bit int value.
* Converts between big-endian and little-endian representations.
* @return int with reversed byte order
*/
fun Int.reverseByteOrder(): Int
/**
* Reverse the byte order of a 64-bit long value.
* Converts between big-endian and little-endian representations.
* @return long with reversed byte order
*/
fun Long.reverseByteOrder(): Long
/**
* Reverse the byte order of a 32-bit float value.
* Converts between big-endian and little-endian representations.
* @return float with reversed byte order
*/
fun Float.reverseByteOrder(): Float
/**
* Reverse the byte order of a 64-bit double value.
* Converts between big-endian and little-endian representations.
* @return double with reversed byte order
*/
fun Double.reverseByteOrder(): Double
/**
* Reverse the byte order of an unsigned 16-bit short value.
* @return unsigned short with reversed byte order
*/
fun UShort.reverseByteOrder(): UShort
/**
* Reverse the byte order of an unsigned 32-bit int value.
* @return unsigned int with reversed byte order
*/
fun UInt.reverseByteOrder(): UInt
/**
* Reverse the byte order of an unsigned 64-bit long value.
* @return unsigned long with reversed byte order
*/
fun ULong.reverseByteOrder(): ULongUsage Examples:
import io.ktor.utils.io.bits.*
// Convert integers between endianness
val bigEndianInt = 0x12345678
val littleEndianInt = bigEndianInt.reverseByteOrder()
println("Big-endian: 0x${bigEndianInt.toString(16)}")
println("Little-endian: 0x${littleEndianInt.toString(16)}")
// Convert back
val backToBigEndian = littleEndianInt.reverseByteOrder()
println("Back to big-endian: 0x${backToBigEndian.toString(16)}")
// Float conversions
val originalFloat = 3.14159f
val reversedFloat = originalFloat.reverseByteOrder()
val restoredFloat = reversedFloat.reverseByteOrder()
println("Original: $originalFloat, Restored: $restoredFloat")
// Working with network data (typically big-endian)
fun networkToHost(networkValue: Int): Int {
return if (isLittleEndianPlatform()) {
networkValue.reverseByteOrder()
} else {
networkValue
}
}
fun hostToNetwork(hostValue: Int): Int {
return if (isLittleEndianPlatform()) {
hostValue.reverseByteOrder()
} else {
hostValue
}
}
// Usage with unsigned types
val unsignedValue: UInt = 0xFFEEDDCCu
val reversedUnsigned = unsignedValue.reverseByteOrder()
println("Unsigned: 0x${unsignedValue.toString(16)}")
println("Reversed: 0x${reversedUnsigned.toString(16)}")Extension properties for extracting specific byte and word portions from larger primitive types.
/**
* Extract the upper 8 bits (high byte) from a 16-bit short.
* @return upper byte of the short value
*/
val Short.highByte: Byte
/**
* Extract the lower 8 bits (low byte) from a 16-bit short.
* @return lower byte of the short value
*/
val Short.lowByte: Byte
/**
* Extract the upper 16 bits (high short) from a 32-bit int.
* @return upper short of the int value
*/
val Int.highShort: Short
/**
* Extract the lower 16 bits (low short) from a 32-bit int.
* @return lower short of the int value
*/
val Int.lowShort: Short
/**
* Extract the upper 32 bits (high int) from a 64-bit long.
* @return upper int of the long value
*/
val Long.highInt: Int
/**
* Extract the lower 32 bits (low int) from a 64-bit long.
* @return lower int of the long value
*/
val Long.lowInt: IntUsage Examples:
import io.ktor.utils.io.bits.*
// Extract bytes from short
val shortValue: Short = 0x1234
val highByte = shortValue.highByte // 0x12
val lowByte = shortValue.lowByte // 0x34
println("Short: 0x${shortValue.toString(16)}")
println("High byte: 0x${highByte.toUByte().toString(16)}")
println("Low byte: 0x${lowByte.toUByte().toString(16)}")
// Extract shorts from int
val intValue = 0x12345678
val highShort = intValue.highShort // 0x1234
val lowShort = intValue.lowShort // 0x5678
println("Int: 0x${intValue.toString(16)}")
println("High short: 0x${highShort.toUShort().toString(16)}")
println("Low short: 0x${lowShort.toUShort().toString(16)}")
// Extract ints from long
val longValue = 0x123456789ABCDEF0L
val highInt = longValue.highInt // 0x12345678
val lowInt = longValue.lowInt // 0x9ABCDEF0
println("Long: 0x${longValue.toString(16)}")
println("High int: 0x${highInt.toString(16)}")
println("Low int: 0x${lowInt.toString(16)}")
// Reconstruct values from parts
fun combineBytes(high: Byte, low: Byte): Short {
return ((high.toInt() and 0xFF) shl 8 or (low.toInt() and 0xFF)).toShort()
}
fun combineShorts(high: Short, low: Short): Int {
return (high.toInt() and 0xFFFF) shl 16 or (low.toInt() and 0xFFFF)
}
fun combineInts(high: Int, low: Int): Long {
return (high.toLong() and 0xFFFFFFFFL) shl 32 or (low.toLong() and 0xFFFFFFFFL)
}
val reconstructedShort = combineBytes(highByte, lowByte)
val reconstructedInt = combineShorts(highShort, lowShort)
val reconstructedLong = combineInts(highInt, lowInt)
println("Reconstructed short: 0x${reconstructedShort.toUShort().toString(16)}")
println("Reconstructed int: 0x${reconstructedInt.toString(16)}")
println("Reconstructed long: 0x${reconstructedLong.toString(16)}")Enumeration representing byte order for explicit endianness specification.
/**
* Byte order enumeration for specifying endianness.
*/
enum class ByteOrder {
/** Big-endian byte order (most significant byte first) */
BIG_ENDIAN,
/** Little-endian byte order (least significant byte first) */
LITTLE_ENDIAN;
companion object {
/** Native byte order of the current platform */
val nativeOrder: ByteOrder
}
}Usage Examples:
import io.ktor.utils.io.bits.*
// Check platform byte order
val platformOrder = ByteOrder.nativeOrder
println("Platform byte order: $platformOrder")
// Conditional byte order operations
fun convertToTargetEndian(value: Int, targetOrder: ByteOrder): Int {
return when {
targetOrder == ByteOrder.nativeOrder -> value
targetOrder == ByteOrder.LITTLE_ENDIAN && ByteOrder.nativeOrder == ByteOrder.BIG_ENDIAN ->
value.reverseByteOrder()
targetOrder == ByteOrder.BIG_ENDIAN && ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN ->
value.reverseByteOrder()
else -> value
}
}
// Network protocol handling
class NetworkProtocolHandler {
// Network byte order is typically big-endian
private val networkByteOrder = ByteOrder.BIG_ENDIAN
fun encodeForNetwork(hostValue: Int): Int {
return convertToTargetEndian(hostValue, networkByteOrder)
}
fun decodeFromNetwork(networkValue: Int): Int {
return convertToTargetEndian(networkValue, ByteOrder.nativeOrder)
}
}Common patterns for working with byte order in real applications.
// File format handling
class BinaryFileProcessor {
fun readLittleEndianInt(bytes: ByteArray, offset: Int): Int {
val value = (bytes[offset + 3].toInt() and 0xFF) shl 24 or
(bytes[offset + 2].toInt() and 0xFF) shl 16 or
(bytes[offset + 1].toInt() and 0xFF) shl 8 or
(bytes[offset].toInt() and 0xFF)
return if (ByteOrder.nativeOrder == ByteOrder.BIG_ENDIAN) {
value.reverseByteOrder()
} else {
value
}
}
fun writeLittleEndianInt(value: Int, bytes: ByteArray, offset: Int) {
val leValue = if (ByteOrder.nativeOrder == ByteOrder.BIG_ENDIAN) {
value.reverseByteOrder()
} else {
value
}
bytes[offset] = leValue.toByte()
bytes[offset + 1] = (leValue shr 8).toByte()
bytes[offset + 2] = (leValue shr 16).toByte()
bytes[offset + 3] = (leValue shr 24).toByte()
}
}
// Network packet processing
class PacketProcessor {
fun createPacketHeader(
packetType: Short,
packetLength: Int,
sequenceNumber: Long
): ByteArray {
val header = ByteArray(14) // 2 + 4 + 8 bytes
// Convert to network byte order (big-endian)
val networkType = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
packetType.reverseByteOrder()
} else {
packetType
}
val networkLength = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
packetLength.reverseByteOrder()
} else {
packetLength
}
val networkSequence = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
sequenceNumber.reverseByteOrder()
} else {
sequenceNumber
}
// Pack into byte array
header[0] = networkType.highByte
header[1] = networkType.lowByte
header[2] = networkLength.highShort.highByte
header[3] = networkLength.highShort.lowByte
header[4] = networkLength.lowShort.highByte
header[5] = networkLength.lowShort.lowByte
for (i in 0..7) {
header[6 + i] = (networkSequence shr (56 - i * 8)).toByte()
}
return header
}
fun parsePacketHeader(header: ByteArray): Triple<Short, Int, Long> {
// Parse network byte order data
val networkType = ((header[0].toInt() and 0xFF) shl 8 or
(header[1].toInt() and 0xFF)).toShort()
val networkLength = (header[2].toInt() and 0xFF) shl 24 or
(header[3].toInt() and 0xFF) shl 16 or
(header[4].toInt() and 0xFF) shl 8 or
(header[5].toInt() and 0xFF)
var networkSequence = 0L
for (i in 0..7) {
networkSequence = networkSequence shl 8 or (header[6 + i].toInt() and 0xFF).toLong()
}
// Convert to host byte order
val hostType = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
networkType.reverseByteOrder()
} else {
networkType
}
val hostLength = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
networkLength.reverseByteOrder()
} else {
networkLength
}
val hostSequence = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
networkSequence.reverseByteOrder()
} else {
networkSequence
}
return Triple(hostType, hostLength, hostSequence)
}
}
// Memory-mapped file handling
class MemoryMappedProcessor {
fun readMultiEndianData(memory: Memory, offset: Int): Pair<Int, Int> {
// Read as big-endian
val bigEndianValue = memory.loadIntAt(offset)
// Convert to little-endian
val littleEndianValue = bigEndianValue.reverseByteOrder()
return bigEndianValue to littleEndianValue
}
fun writeWithSpecificEndian(
memory: Memory,
offset: Int,
value: Int,
targetOrder: ByteOrder
) {
val valueToWrite = when {
targetOrder == ByteOrder.nativeOrder -> value
targetOrder == ByteOrder.BIG_ENDIAN &&
ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN -> value.reverseByteOrder()
targetOrder == ByteOrder.LITTLE_ENDIAN &&
ByteOrder.nativeOrder == ByteOrder.BIG_ENDIAN -> value.reverseByteOrder()
else -> value
}
memory.storeIntAt(offset, valueToWrite)
}
}Advanced Usage Examples:
import io.ktor.utils.io.bits.*
import io.ktor.utils.io.core.*
// Cross-platform data serialization
class CrossPlatformSerializer {
fun serializeData(data: List<Int>): ByteArray {
return buildPacket {
// Write count as big-endian
val count = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
data.size.reverseByteOrder()
} else {
data.size
}
writeInt(count)
// Write each value as big-endian
data.forEach { value ->
val networkValue = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
value.reverseByteOrder()
} else {
value
}
writeInt(networkValue)
}
}.readBytes()
}
fun deserializeData(bytes: ByteArray): List<Int> {
val packet = ByteReadPacket(bytes)
// Read count
val networkCount = packet.readInt()
val count = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
networkCount.reverseByteOrder()
} else {
networkCount
}
// Read values
return (0 until count).map {
val networkValue = packet.readInt()
if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
networkValue.reverseByteOrder()
} else {
networkValue
}
}
}
}
// Usage
val serializer = CrossPlatformSerializer()
val originalData = listOf(1, 2, 3, 0x12345678, -1)
val serialized = serializer.serializeData(originalData)
val deserialized = serializer.deserializeData(serialized)
println("Original: $originalData")
println("Deserialized: $deserialized")
println("Equal: ${originalData == deserialized}")Install with Tessl CLI
npx tessl i tessl/maven-io-ktor--ktor-io-watchosarm64