Dimitrio
Dimitrio

Reputation: 151

split uint32 value to uint8 values in swift

in C I have

uint32 value = 39434;
uint8 firstByte = (unsigned char)value;
uint8 secondByte = (unsigned char)(value >> 8);

Is there any possibility to achieve the same in Swift?

Upvotes: 2

Views: 3302

Answers (2)

dfrib
dfrib

Reputation: 73166

An alternative to the bitpattern-dedicated initalizer init(truncatingBitPattern:) is to manually mask all bytes but the byte of interest, and shift this byte appropriately; followed by using the "standard" UInt8 value conversion initializer:

let val : UInt32 = 39434

let byte1 = UInt8(val & 0x000000FF)         // 10
let byte2 = UInt8((val & 0x0000FF00) >> 8)  // 154
let byte3 = UInt8((val & 0x00FF0000) >> 16) // 0
let byte4 = UInt8((val & 0xFF000000) >> 24) // 0

/* ... */
let val : UInt32 = UINT32_MAX

let byte1 = UInt8(val & 0x000000FF)         // 255
let byte2 = UInt8((val & 0x0000FF00) >> 8)  // 255
let byte3 = UInt8((val & 0x00FF0000) >> 16) // 255
let byte4 = UInt8((val & 0xFF000000) >> 24) // 255

Or, to simplify, e.g. as a computed property in an extension

extension UInt32 {
    var asByteArray: [UInt8] {
        return [0, 8, 16, 24]
            .map { UInt8(self >> $0 & 0x000000FF) }
    }
}

/* example usage */
val.asByteArray 
    /* [10, 154, 0, 0], 
       [255, 255, 255, 255], for the examples above */

This is, however, naturally not as safe as using the dedicated initializer, as it places the responsibility of masking and correct shifting on the developer rather than the compiler. If not taking care, the non-truncated conversion from the four bytes into one will yield a runtime integer overflow.

Upvotes: 1

Martin R
Martin R

Reputation: 539675

It is quite similar in Swift:

let value : UInt32 = 39434
let firstByte = UInt8(truncatingBitPattern: value) // 10
let secondByte = UInt8(truncatingBitPattern: value >> 8) // 154

The special initializer init(truncatingBitPattern:) is required here because Swift (in contrast to C), does not implicitly truncate integers:

let firstByte = UInt8(value)

would result in a runtime exception if value does not fit into the range of UInt8.

See also Split UInt32 into [UInt8] in swift for possible solutions which give you an array with the four bytes of the input value.

Upvotes: 5

Related Questions