Android Kotlin Byte Shifting +=

1.6k views Asked by At

I'm trying to convert a BLE native Byte handling helper to Kotlin. In the process, I noticed that in

JAVA

myByteArray[offset] += (byte)(exponent & 0xFF);

it works as expected, but when converted to kotlin KOTLIN

myByteArray[offset] += (exponent and 0x0F shl 4).toByte()

I get errors that an Integer is expected. So I assume the

"+="

is my problem and causing an integer to be assumed. So I have two questions.

1) What exactly does += do with bytes. I understand that

b += 1

is the equivelent of

b = (byte)(b + 1)

but what exactly is happening to the bytes. Is there shifting going on, or is it converting to an int, adding the values then back to a byte?

2) What is the equivelent in Kotlin and why is it failing in Kotlin. I also tried doing

  myByteArray[offset] = myByteArray[offset] + (exponent and 0x0F shl 4).toByte()

For the record, this is converting an Integer value into a 32bit Float if you are curious. Not sure if that helps at all.

The full code if you are interested for this is:

mantissa = intToSignedBits(mantissa, 12)
exponent = intToSignedBits(exponent, 4)
myByteArray[offset++] = (mantissa and 0xFF).toByte()
myByteArray[offset] = (mantissa shr 8 and 0x0F).toByte()
myByteArray[offset] += (exponent and 0x0F shl 4).toByte() //hates this line

NOTE* It says

this

because I wrote it as a ByteArray extension, so think of this as the byteArray itself.

KOTLIN version of it (ERRORS)

enter image description here

JAVA version of it (NO ERRORS):

enter image description here

I desire more than just an answer, but I'll take it lol. I would like to understand a bit more of what is going on here so I can solve this on my own in the future as well. Thanks in advance to any who take the time to explain and help.

Also while we are on the subject ;).

  private int unsignedByteToInt(byte b) {
        return b & 0xFF;
   }

why does this work in Java, but fail in Kotlin.

   private fun unsignedByteToInt(b: Byte): Int {
        return b and 0xFF
   }

Gotta be honest, I'm tired of writing Java helper classes to handle bytes, so I'm trying to figure out the idioms of Kotlin byte handling. "and" seems to only have overloads for Ints and bytes are not treated as Ints in Kotlin.

So as a bonus question, if you can explain that one, I would also appreciate it.

2

There are 2 answers

8
TheWanderer On BEST ANSWER

I believe you should be using Byte#plus(Byte).

So in your case:

myByteArray[offset] = myByteArray[offset].plus((exponent and 0x0F shl 4).toByte())

.toByte() probably isn't necessary in this case, since plus() takes basically any number, but I'm not able to test it.

4
Pawel On

Did You notice that breaking down your statement works?

val newBytes = (myByteArray[offset]+(exponent and 0x0F shl 4)).toByte()
myByteArray[offset] = newBytes

Main culprit of this behavior is plus operator signature. Those are all the overloads of plus for Byte:

/** Adds the other value to this value. */
public operator fun plus(other: Byte): Int
/** Adds the other value to this value. */
public operator fun plus(other: Short): Int
/** Adds the other value to this value. */
public operator fun plus(other: Int): Int
/** Adds the other value to this value. */
public operator fun plus(other: Long): Long
/** Adds the other value to this value. */
public operator fun plus(other: Float): Float
/** Adds the other value to this value. */
public operator fun plus(other: Double): Double

None of those return a Byte and there are no overloads of plusAssign, so they are implicitly created.

First it performs plus(Byte) returning Int then tries assignment, but it requires a Byte so it causes your error.