Java to Swift code conversion Fatal Error: Not enough bits to represent the passed value

Viewed 105

I'm trying to build an iOS app based on an existing Android app and have to convert a function involving bit-shifting from Java to Swift. This is the original function in Java:

public static void BUF_U32_BE(byte[] d, int loc, int val) {
    d[loc] = (byte)(val >> 24);
    d[loc+1] = (byte)(val >> 16);
    d[loc+2] = (byte)(val >> 8);
    d[loc+3] = (byte)(val & 0xFF);
}

This was my attempt at converting the function to Swift:

func BUF_U32_BE(byteArray: [UInt8], loc:  Int, val: Int)  -> [UInt8]{
    var d = byteArray;
    d[loc] = UInt8((val >> 24));
    d[loc+1] = UInt8((val >> 16));
    d[loc+2] = UInt8((val >> 8));
    d[loc+3] = UInt8((val & 0xFF));
    return d;
}

When running the Swift version, I get the error:

Fatal Error: Not enough bits to represent the passed value

This is the line that produces the error:

d[loc+1] = UInt8((val >> 16));

What could be causing this issue and what should I do to fix it?

1 Answers

You're looking for UInt8.init(truncatingIfNeeded:).


As an aside this byteArray: [UInt8] parameter is pretty wonky. It's passed in, copied, mutated, and returned. It's never read from. That's quite strange. I think you're expecting this to right into the byteArray at the loc index, but since you're making a copy, that doesn't actually happen.

In Swift, we would simply return a tuple for fixed numbers of values like this:

// FIXME: `BUF_U32_BE` is a bad name. Perhaps `splitIntoBytes(_:)`?
func BUF_U32_BE(val: Int) -> (UInt8, UInt8, UInt8, UInt8) {
    return (
        UInt8(truncatingIfNeeded: val >> 24),
        UInt8(truncatingIfNeeded: val >> 16),
        UInt8(truncatingIfNeeded: val >>  8),
        UInt8(truncatingIfNeeded: val >>  0),
    )
}
Related