Kotlin bit shifting
Asked Answered
P

3

8

I want to convert the code if this answer to Kotlin: https://mcmap.net/q/430222/-using-public-key-from-authorized_keys-with-java-security

I pasted this into Intellij:

private int decodeInt() {
    return ((bytes[pos++] & 0xFF) << 24) | ((bytes[pos++] & 0xFF) << 16)
            | ((bytes[pos++] & 0xFF) << 8) | (bytes[pos++] & 0xFF);
}

Intellij asks if I want to convert it to Kotlin, when I do this is the output:

private fun decodeInt(): Int {
    return (bytes[pos++] and 0xFF shl 24 or (bytes[pos++] and 0xFF shl 16)
            or (bytes[pos++] and 0xFF shl 8) or (bytes[pos++] and 0xFF))
}

At all 0xFF I get this error:

The integer literal does not conform to the expected type Byte

By appending .toByte() after it I was able to remove this error.

And at all shift left operations(shl) I get this error:

Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 

@SinceKotlin @InlineOnly public infix inline fun BigInteger.shl(n: Int): BigInteger defined in kotlin

I wasn't able to solve this one... I don't know a lot about bit shifting in Java/Kotlin...
What would be the working Kotlin code for this?

Piscatorial answered 31/1, 2018 at 22:5 Comment(0)
B
15

Convert explicitly like this: 0xFF.toByte()

As a general rule, press Alt+Enter when you need more information about an error or a possible solution.

The shift left method takes an Int as parameter. So, same thing, convert to the right type.

(bytes[pos++] and 0xFF.toByte()).toInt() shl 24
Beguin answered 31/1, 2018 at 22:15 Comment(2)
This has 8 conversions. It works, but it can be done with just 4 conversions.Solingen
@Paul Hicks You're probably right. I'll counter your donwvote on the basis that I don't see how your answer is any worse and the person who downvoted didn't say what's wrong with it.Beguin
S
2

shl expects Int, not Byte. You need 0xFF to be an Int (which it is), so don't call toByte(). You need (0xFF shl 24) to be an Int, so don't convert that. You need bytes[pos++] to be an Int.. convert that!

return (((bytes[pos++].toInt() and (0xFF shl 24)) or
         (bytes[pos++].toInt() and (0xFF shl 16)) or
         (bytes[pos++].toInt() and (0xFF shl 8)) or
         (bytes[pos++].toInt() and 0xFF))
Solingen answered 31/1, 2018 at 22:26 Comment(1)
Or possibly even better.. change bytes to be an Int array rather than a Byte array. It will be faster in most cases, though obviously use more memory.Solingen
H
0

you can create custom extensions like below. If you use "and" from these extensions, shl will not cause problems.

infix fun Byte.and(mask: Int): Int = toInt() and mask
infix fun Short.and(mask: Int): Int = toInt() and mask
infix fun Int.and(mask: Long): Long = toLong() and mask
Highway answered 6/12, 2023 at 13:57 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.