To expand upon @Alexander's excellent answer, I wrote a version that accepts ByteArrays that have fewer than four values. I've found this particularly useful when parsing ByteArrays with a mix of signed and unsigned integers (in my case bluetooth characteristic update notifications)
that I need to slice into sub-arrays.
fun ByteArray.fromUnsignedBytesToInt(): Int {
//Note: UInt is always 32 bits (4 bytes) regardless of platform architecture
//See https://kotlinlang.org/docs/basic-types.html#unsigned-integers
val bytes = 4
val paddedArray = ByteArray(bytes)
for (i in 0 until bytes-this.size) paddedArray[i] = 0
for (i in bytes-this.size until paddedArray.size) paddedArray[i] = this[i-(bytes-this.size)]
return (((paddedArray[0].toULong() and 0xFFu) shl 24) or
((paddedArray[1].toULong() and 0xFFu) shl 16) or
((paddedArray[2].toULong() and 0xFFu) shl 8) or
(paddedArray[3].toULong() and 0xFFu)).toInt()
}
The test class below confirms the expected values:
import org.junit.Test
import org.junit.Assert.*
internal class ByteArrayExtKtTest {
@Test
fun testAsUnsignedToIntTwoBytes() {
val bytes = byteArrayOf (0x0A.toByte(), 0xBA.toByte())
assertEquals(2746, bytes.fromUnsignedBytesToInt())
}
@Test
fun testAsUnsignedToIntFourBytes() {
val bytes = byteArrayOf(1,1,1,1)
assertEquals(16843009, bytes.fromUnsignedBytesToInt())
}
}
val uint = bytes[index].toUInt()
– Cannonindex
. I need to convert the 4 bytes to a single unsigned integer. – IndorsegetUIntAt()
also accept the index which does the same – CannonUInt
is a 32 bit signed integer. 32 bits is 4 bytes. – IndorsegetUIntAt(index)
reads the 4 bytes starting atindex
and returns aUInt
of which the value corresponds to those 4 bytes. – Indorsebytes.getUIntAt(0)
returns16843009
, which is correct. – IndorseByteBuffer
and create extension function to make it reusable .. – Cannon