Anton Tropashko
Anton Tropashko

Reputation: 5806

A proper way to marshall an array of UInt32 to UInt8

This

    let eByteArr = withUnsafeBytes(of: &entropySliceHashes32) { (bytes) -> [UInt8] in
        return bytes.map { $0 }
    }

somehow maps 16 bytes (four 4 byte unsigned ints) into 8 bytes:

(lldb) p entropySliceHashes32
([UInt32]) $R0 = 4 values {
  [0] = 414878621
  [1] = 3484496398
  [2] = 2937522763
  [3] = 3119551166
}

(lldb) p eByteArr
([UInt8]) $R1 = 8 values {
  [0] = 16
  [1] = 224
  [2] = 4
  [3] = 112
  [4] = 1
  [5] = 0
  [6] = 0
  [7] = 0
}

What's a succinct low overhead way to change representation of the underlying 16 byte heap in swift3?

Upvotes: 0

Views: 157

Answers (2)

Martin R
Martin R

Reputation: 539815

As Jeremy already said, you have to call the withUnsafeBytes method on the array to get an UnsafeRawBufferPointer to the element storage.

Now

  • UnsafeRawBufferPointer is a Collection (and in particular a Sequence) of UInt8, and
  • Array has a

    /// Creates an array containing the elements of a sequence.
    ///
    /// - Parameter s: The sequence of elements to turn into an array.
    public init<S>(_ s: S) where S : Sequence, S.Iterator.Element == Element
    

    initializer.

Therefore you can create an [UInt8] array from a raw buffer pointer ptr with Array(ptr):

let eByteArr = entropySliceHashes32.withUnsafeBytes {
    ptr in return Array(ptr)
}

which can be shortened to

let eByteArr = entropySliceHashes32.withUnsafeBytes { Array($0) }

Upvotes: 2

JeremyP
JeremyP

Reputation: 86651

I think your function is actually mapping the raw bytes of the array struct itself, not the contents.

I think you can get the expected result like this:

let eByteArr = entropySliceHashes32.withUnsafeBytes { 
    (bytes) -> [UInt8] in
    return bytes.map { $0 }
}

i.e. use the method on the array, not the free standing function.

Upvotes: 2

Related Questions