How to Cast [Int8] to [Uint8] in Swift

How to cast [Int8] to [UInt8] in Swift

I broadly agree with the other answers that you should just stick with map, however, if your array were truly huge, and it really was painful to create a whole second buffer just for converting to the same bit pattern, you could do it like this:

// first, change your process logic to be generic on any kind of container
func process<C: CollectionType where C.Generator.Element == UInt8>(chars: C) {
// just to prove it's working...
print(String(chars.map { UnicodeScalar($0) }))
}

// sample input
let a: [Int8] = [104, 101, 108, 108, 111] // ascii "Hello"

// access the underlying raw buffer as a pointer
a.withUnsafeBufferPointer { buf -> Void in
process(
UnsafeBufferPointer(
// cast the underlying pointer to the type you want
start: UnsafePointer(buf.baseAddress),
count: buf.count))
}
// this prints [h, e, l, l, o]

Note withUnsafeBufferPointer means what it says. It’s unsafe and you can corrupt memory if you get this wrong (be especially careful with the count). It works based on your external knowledge that, for example, if any of the integers are negative then your code doesn't mind them becoming corrupt unsigned integers. You might know that, but the Swift type system can't, so it won't allow it without resort to the unsafe types.

That said, the above code is correct and within the rules and these techniques are justifiable if you need the performance edge. You almost certainly won’t unless you’re dealing with gigantic amounts of data or writing a library that you will call a gazillion times.

It’s also worth noting that there are circumstances where an array is not actually backed by a contiguous buffer (for example if it were cast from an NSArray) in which case calling .withUnsafeBufferPointer will first copy all the elements into a contiguous array. Also, Swift arrays are growable so this copy of underlying elements happens often as the array grows. If performance is absolutely critical, you could consider allocating your own memory using UnsafeMutablePointer and using it fixed-size style using UnsafeBufferPointer.

For a humorous but definitely not within the rules example that you shouldn’t actually use, this will also work:

process(unsafeBitCast(a, [UInt8].self))

It's also worth noting that these solutions are not the same as a.map { UInt8($0) } since the latter will trap at runtime if you pass it a negative integer. If this is a possibility you may need to filter them first.

Swift converting signed array of Int [int8] to unsigned array of Int [UInt8]

If your intention is to convert signed 8-bit integers to
unsigned ones with the same bit representation (e.g. -1 -> 255):

let intArray: [Int8] =  [0, 1, 2, 127, -1, -2, -128]
let uintArray = intArray.map { UInt8(bitPattern: $0) }

print(uintArray)
// [0, 1, 2, 127, 255, 254, 128]

How to cast `Int8?` to `Int?`?

Your type is Optional<UInt8>. A UInt8 can always be converted to an Int with the function Int.init. But since it's wrapped in an Optional, you'll have to map that function over the optional, yielding a new value of type Optional<Int>:

seconds.map(Int.init)

Optional.map(_:) and its companion flatMap often make working with optionals a lot easier.

Int to UInt (and vice versa) bit casting in Swift

You can do:

let unsigned = UInt8(bitPattern: Int8(-1)) // -> 255
let signed = Int8(bitPattern: UInt8(0xff)) // -> -1

Many similar initializers exist:

extension Int8 {
init(_ v: UInt8)
init(_ v: UInt16)
init(truncatingBitPattern: UInt16)
init(_ v: Int16)
init(truncatingBitPattern: Int16)
init(_ v: UInt32)
init(truncatingBitPattern: UInt32)
init(_ v: Int32)
init(truncatingBitPattern: Int32)
init(_ v: UInt64)
init(truncatingBitPattern: UInt64)
init(_ v: Int64)
init(truncatingBitPattern: Int64)
init(_ v: UInt)
init(truncatingBitPattern: UInt)
init(_ v: Int)
init(truncatingBitPattern: Int)
init(bitPattern: UInt8)
}

swift 3 ios : convert UInt8 Array to int8

You can convert a [UInt8] to a [Int8] by using this:

for el in uint8Array {
uint8Array.append(UInt8(bitPattern: el))
}

Convert Int to Array of UInt8 in swift

You could do it this way:

let x: Int = 2019
let length: Int = 2 * MemoryLayout<UInt8>.size //You could specify the desired length

let a = withUnsafeBytes(of: x) { bytes in
Array(bytes.prefix(length))
}

let result = Array(a.reversed()) //[7, 227]

Or more generally, we could use a modified version of this snippet:

func bytes<U: FixedWidthInteger,V: FixedWidthInteger>(
of value : U,
to type : V.Type,
droppingZeros: Bool
) -> [V]{

let sizeInput = MemoryLayout<U>.size
let sizeOutput = MemoryLayout<V>.size

precondition(sizeInput >= sizeOutput, "The input memory size should be greater than the output memory size")

var value = value
let a = withUnsafePointer(to: &value, {
$0.withMemoryRebound(
to: V.self,
capacity: sizeInput,
{
Array(UnsafeBufferPointer(start: $0, count: sizeInput/sizeOutput))
})
})

let lastNonZeroIndex =
(droppingZeros ? a.lastIndex { $0 != 0 } : a.indices.last) ?? a.startIndex

return Array(a[...lastNonZeroIndex].reversed())
}

let x: Int = 2019
bytes(of: x, to: UInt8.self, droppingZeros: true) // [7, 227]
bytes(of: x, to: UInt8.self, droppingZeros: false) // [0, 0, 0, 0, 0, 0, 7, 227]


Related Topics



Leave a reply



Submit