0
# Byte Order Utilities
1
2
Byte order manipulation and primitive type conversion utilities supporting both big-endian and little-endian operations.
3
4
## Capabilities
5
6
### Byte Order Reversal Functions
7
8
Extension functions for reversing byte order of primitive types to convert between big-endian and little-endian representations.
9
10
```kotlin { .api }
11
/**
12
* Reverse the byte order of a 16-bit short value.
13
* Converts between big-endian and little-endian representations.
14
* @return short with reversed byte order
15
*/
16
fun Short.reverseByteOrder(): Short
17
18
/**
19
* Reverse the byte order of a 32-bit int value.
20
* Converts between big-endian and little-endian representations.
21
* @return int with reversed byte order
22
*/
23
fun Int.reverseByteOrder(): Int
24
25
/**
26
* Reverse the byte order of a 64-bit long value.
27
* Converts between big-endian and little-endian representations.
28
* @return long with reversed byte order
29
*/
30
fun Long.reverseByteOrder(): Long
31
32
/**
33
* Reverse the byte order of a 32-bit float value.
34
* Converts between big-endian and little-endian representations.
35
* @return float with reversed byte order
36
*/
37
fun Float.reverseByteOrder(): Float
38
39
/**
40
* Reverse the byte order of a 64-bit double value.
41
* Converts between big-endian and little-endian representations.
42
* @return double with reversed byte order
43
*/
44
fun Double.reverseByteOrder(): Double
45
46
/**
47
* Reverse the byte order of an unsigned 16-bit short value.
48
* @return unsigned short with reversed byte order
49
*/
50
fun UShort.reverseByteOrder(): UShort
51
52
/**
53
* Reverse the byte order of an unsigned 32-bit int value.
54
* @return unsigned int with reversed byte order
55
*/
56
fun UInt.reverseByteOrder(): UInt
57
58
/**
59
* Reverse the byte order of an unsigned 64-bit long value.
60
* @return unsigned long with reversed byte order
61
*/
62
fun ULong.reverseByteOrder(): ULong
63
```
64
65
**Usage Examples:**
66
67
```kotlin
68
import io.ktor.utils.io.bits.*
69
70
// Convert integers between endianness
71
val bigEndianInt = 0x12345678
72
val littleEndianInt = bigEndianInt.reverseByteOrder()
73
println("Big-endian: 0x${bigEndianInt.toString(16)}")
74
println("Little-endian: 0x${littleEndianInt.toString(16)}")
75
76
// Convert back
77
val backToBigEndian = littleEndianInt.reverseByteOrder()
78
println("Back to big-endian: 0x${backToBigEndian.toString(16)}")
79
80
// Float conversions
81
val originalFloat = 3.14159f
82
val reversedFloat = originalFloat.reverseByteOrder()
83
val restoredFloat = reversedFloat.reverseByteOrder()
84
println("Original: $originalFloat, Restored: $restoredFloat")
85
86
// Working with network data (typically big-endian)
87
fun networkToHost(networkValue: Int): Int {
88
return if (isLittleEndianPlatform()) {
89
networkValue.reverseByteOrder()
90
} else {
91
networkValue
92
}
93
}
94
95
fun hostToNetwork(hostValue: Int): Int {
96
return if (isLittleEndianPlatform()) {
97
hostValue.reverseByteOrder()
98
} else {
99
hostValue
100
}
101
}
102
103
// Usage with unsigned types
104
val unsignedValue: UInt = 0xFFEEDDCCu
105
val reversedUnsigned = unsignedValue.reverseByteOrder()
106
println("Unsigned: 0x${unsignedValue.toString(16)}")
107
println("Reversed: 0x${reversedUnsigned.toString(16)}")
108
```
109
110
### Bit Extraction Properties
111
112
Extension properties for extracting specific byte and word portions from larger primitive types.
113
114
```kotlin { .api }
115
/**
116
* Extract the upper 8 bits (high byte) from a 16-bit short.
117
* @return upper byte of the short value
118
*/
119
val Short.highByte: Byte
120
121
/**
122
* Extract the lower 8 bits (low byte) from a 16-bit short.
123
* @return lower byte of the short value
124
*/
125
val Short.lowByte: Byte
126
127
/**
128
* Extract the upper 16 bits (high short) from a 32-bit int.
129
* @return upper short of the int value
130
*/
131
val Int.highShort: Short
132
133
/**
134
* Extract the lower 16 bits (low short) from a 32-bit int.
135
* @return lower short of the int value
136
*/
137
val Int.lowShort: Short
138
139
/**
140
* Extract the upper 32 bits (high int) from a 64-bit long.
141
* @return upper int of the long value
142
*/
143
val Long.highInt: Int
144
145
/**
146
* Extract the lower 32 bits (low int) from a 64-bit long.
147
* @return lower int of the long value
148
*/
149
val Long.lowInt: Int
150
```
151
152
**Usage Examples:**
153
154
```kotlin
155
import io.ktor.utils.io.bits.*
156
157
// Extract bytes from short
158
val shortValue: Short = 0x1234
159
val highByte = shortValue.highByte // 0x12
160
val lowByte = shortValue.lowByte // 0x34
161
162
println("Short: 0x${shortValue.toString(16)}")
163
println("High byte: 0x${highByte.toUByte().toString(16)}")
164
println("Low byte: 0x${lowByte.toUByte().toString(16)}")
165
166
// Extract shorts from int
167
val intValue = 0x12345678
168
val highShort = intValue.highShort // 0x1234
169
val lowShort = intValue.lowShort // 0x5678
170
171
println("Int: 0x${intValue.toString(16)}")
172
println("High short: 0x${highShort.toUShort().toString(16)}")
173
println("Low short: 0x${lowShort.toUShort().toString(16)}")
174
175
// Extract ints from long
176
val longValue = 0x123456789ABCDEF0L
177
val highInt = longValue.highInt // 0x12345678
178
val lowInt = longValue.lowInt // 0x9ABCDEF0
179
180
println("Long: 0x${longValue.toString(16)}")
181
println("High int: 0x${highInt.toString(16)}")
182
println("Low int: 0x${lowInt.toString(16)}")
183
184
// Reconstruct values from parts
185
fun combineBytes(high: Byte, low: Byte): Short {
186
return ((high.toInt() and 0xFF) shl 8 or (low.toInt() and 0xFF)).toShort()
187
}
188
189
fun combineShorts(high: Short, low: Short): Int {
190
return (high.toInt() and 0xFFFF) shl 16 or (low.toInt() and 0xFFFF)
191
}
192
193
fun combineInts(high: Int, low: Int): Long {
194
return (high.toLong() and 0xFFFFFFFFL) shl 32 or (low.toLong() and 0xFFFFFFFFL)
195
}
196
197
val reconstructedShort = combineBytes(highByte, lowByte)
198
val reconstructedInt = combineShorts(highShort, lowShort)
199
val reconstructedLong = combineInts(highInt, lowInt)
200
201
println("Reconstructed short: 0x${reconstructedShort.toUShort().toString(16)}")
202
println("Reconstructed int: 0x${reconstructedInt.toString(16)}")
203
println("Reconstructed long: 0x${reconstructedLong.toString(16)}")
204
```
205
206
### ByteOrder Enum
207
208
Enumeration representing byte order for explicit endianness specification.
209
210
```kotlin { .api }
211
/**
212
* Byte order enumeration for specifying endianness.
213
*/
214
enum class ByteOrder {
215
/** Big-endian byte order (most significant byte first) */
216
BIG_ENDIAN,
217
218
/** Little-endian byte order (least significant byte first) */
219
LITTLE_ENDIAN;
220
221
companion object {
222
/** Native byte order of the current platform */
223
val nativeOrder: ByteOrder
224
}
225
}
226
```
227
228
**Usage Examples:**
229
230
```kotlin
231
import io.ktor.utils.io.bits.*
232
233
// Check platform byte order
234
val platformOrder = ByteOrder.nativeOrder
235
println("Platform byte order: $platformOrder")
236
237
// Conditional byte order operations
238
fun convertToTargetEndian(value: Int, targetOrder: ByteOrder): Int {
239
return when {
240
targetOrder == ByteOrder.nativeOrder -> value
241
targetOrder == ByteOrder.LITTLE_ENDIAN && ByteOrder.nativeOrder == ByteOrder.BIG_ENDIAN ->
242
value.reverseByteOrder()
243
targetOrder == ByteOrder.BIG_ENDIAN && ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN ->
244
value.reverseByteOrder()
245
else -> value
246
}
247
}
248
249
// Network protocol handling
250
class NetworkProtocolHandler {
251
// Network byte order is typically big-endian
252
private val networkByteOrder = ByteOrder.BIG_ENDIAN
253
254
fun encodeForNetwork(hostValue: Int): Int {
255
return convertToTargetEndian(hostValue, networkByteOrder)
256
}
257
258
fun decodeFromNetwork(networkValue: Int): Int {
259
return convertToTargetEndian(networkValue, ByteOrder.nativeOrder)
260
}
261
}
262
```
263
264
### Practical Usage Patterns
265
266
Common patterns for working with byte order in real applications.
267
268
```kotlin { .api }
269
// File format handling
270
class BinaryFileProcessor {
271
fun readLittleEndianInt(bytes: ByteArray, offset: Int): Int {
272
val value = (bytes[offset + 3].toInt() and 0xFF) shl 24 or
273
(bytes[offset + 2].toInt() and 0xFF) shl 16 or
274
(bytes[offset + 1].toInt() and 0xFF) shl 8 or
275
(bytes[offset].toInt() and 0xFF)
276
277
return if (ByteOrder.nativeOrder == ByteOrder.BIG_ENDIAN) {
278
value.reverseByteOrder()
279
} else {
280
value
281
}
282
}
283
284
fun writeLittleEndianInt(value: Int, bytes: ByteArray, offset: Int) {
285
val leValue = if (ByteOrder.nativeOrder == ByteOrder.BIG_ENDIAN) {
286
value.reverseByteOrder()
287
} else {
288
value
289
}
290
291
bytes[offset] = leValue.toByte()
292
bytes[offset + 1] = (leValue shr 8).toByte()
293
bytes[offset + 2] = (leValue shr 16).toByte()
294
bytes[offset + 3] = (leValue shr 24).toByte()
295
}
296
}
297
298
// Network packet processing
299
class PacketProcessor {
300
fun createPacketHeader(
301
packetType: Short,
302
packetLength: Int,
303
sequenceNumber: Long
304
): ByteArray {
305
val header = ByteArray(14) // 2 + 4 + 8 bytes
306
307
// Convert to network byte order (big-endian)
308
val networkType = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
309
packetType.reverseByteOrder()
310
} else {
311
packetType
312
}
313
314
val networkLength = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
315
packetLength.reverseByteOrder()
316
} else {
317
packetLength
318
}
319
320
val networkSequence = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
321
sequenceNumber.reverseByteOrder()
322
} else {
323
sequenceNumber
324
}
325
326
// Pack into byte array
327
header[0] = networkType.highByte
328
header[1] = networkType.lowByte
329
330
header[2] = networkLength.highShort.highByte
331
header[3] = networkLength.highShort.lowByte
332
header[4] = networkLength.lowShort.highByte
333
header[5] = networkLength.lowShort.lowByte
334
335
for (i in 0..7) {
336
header[6 + i] = (networkSequence shr (56 - i * 8)).toByte()
337
}
338
339
return header
340
}
341
342
fun parsePacketHeader(header: ByteArray): Triple<Short, Int, Long> {
343
// Parse network byte order data
344
val networkType = ((header[0].toInt() and 0xFF) shl 8 or
345
(header[1].toInt() and 0xFF)).toShort()
346
347
val networkLength = (header[2].toInt() and 0xFF) shl 24 or
348
(header[3].toInt() and 0xFF) shl 16 or
349
(header[4].toInt() and 0xFF) shl 8 or
350
(header[5].toInt() and 0xFF)
351
352
var networkSequence = 0L
353
for (i in 0..7) {
354
networkSequence = networkSequence shl 8 or (header[6 + i].toInt() and 0xFF).toLong()
355
}
356
357
// Convert to host byte order
358
val hostType = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
359
networkType.reverseByteOrder()
360
} else {
361
networkType
362
}
363
364
val hostLength = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
365
networkLength.reverseByteOrder()
366
} else {
367
networkLength
368
}
369
370
val hostSequence = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
371
networkSequence.reverseByteOrder()
372
} else {
373
networkSequence
374
}
375
376
return Triple(hostType, hostLength, hostSequence)
377
}
378
}
379
380
// Memory-mapped file handling
381
class MemoryMappedProcessor {
382
fun readMultiEndianData(memory: Memory, offset: Int): Pair<Int, Int> {
383
// Read as big-endian
384
val bigEndianValue = memory.loadIntAt(offset)
385
386
// Convert to little-endian
387
val littleEndianValue = bigEndianValue.reverseByteOrder()
388
389
return bigEndianValue to littleEndianValue
390
}
391
392
fun writeWithSpecificEndian(
393
memory: Memory,
394
offset: Int,
395
value: Int,
396
targetOrder: ByteOrder
397
) {
398
val valueToWrite = when {
399
targetOrder == ByteOrder.nativeOrder -> value
400
targetOrder == ByteOrder.BIG_ENDIAN &&
401
ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN -> value.reverseByteOrder()
402
targetOrder == ByteOrder.LITTLE_ENDIAN &&
403
ByteOrder.nativeOrder == ByteOrder.BIG_ENDIAN -> value.reverseByteOrder()
404
else -> value
405
}
406
407
memory.storeIntAt(offset, valueToWrite)
408
}
409
}
410
```
411
412
**Advanced Usage Examples:**
413
414
```kotlin
415
import io.ktor.utils.io.bits.*
416
import io.ktor.utils.io.core.*
417
418
// Cross-platform data serialization
419
class CrossPlatformSerializer {
420
fun serializeData(data: List<Int>): ByteArray {
421
return buildPacket {
422
// Write count as big-endian
423
val count = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
424
data.size.reverseByteOrder()
425
} else {
426
data.size
427
}
428
writeInt(count)
429
430
// Write each value as big-endian
431
data.forEach { value ->
432
val networkValue = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
433
value.reverseByteOrder()
434
} else {
435
value
436
}
437
writeInt(networkValue)
438
}
439
}.readBytes()
440
}
441
442
fun deserializeData(bytes: ByteArray): List<Int> {
443
val packet = ByteReadPacket(bytes)
444
445
// Read count
446
val networkCount = packet.readInt()
447
val count = if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
448
networkCount.reverseByteOrder()
449
} else {
450
networkCount
451
}
452
453
// Read values
454
return (0 until count).map {
455
val networkValue = packet.readInt()
456
if (ByteOrder.nativeOrder == ByteOrder.LITTLE_ENDIAN) {
457
networkValue.reverseByteOrder()
458
} else {
459
networkValue
460
}
461
}
462
}
463
}
464
465
// Usage
466
val serializer = CrossPlatformSerializer()
467
val originalData = listOf(1, 2, 3, 0x12345678, -1)
468
val serialized = serializer.serializeData(originalData)
469
val deserialized = serializer.deserializeData(serialized)
470
471
println("Original: $originalData")
472
println("Deserialized: $deserialized")
473
println("Equal: ${originalData == deserialized}")
474
```