Fatal error: Not enough bits to represent the passed value (Int16) in Swift

Viewed 1086

I am translating a library from Java (Android) to -> Swift (iPhone)

Java code, works ok:

   long a = 48590108397870l;
   short b = ((short)(a & 65535));//b == -28370

Swift code:

    let a : Int64  = 48590108397870
    let b: Int16 = Int16(a & 65535)//Fatal error: Not enough bits to represent the passed value
2 Answers

a & 65535 is a value between 0 and 216-1, which fits in an UInt16, but not in an Int16. Contrary to many other languages, Swift does not truncate values implicitly.

Integers have an init(truncatingIfNeeded:) initializer which does what you want:

When the bit width of T (the type of source) is equal to or greater than this type’s bit width, the result is the truncated least-significant bits of source.

Example:

let a : Int64 = 48590108397870
let b = Int16(truncatingIfNeeded: a)
print(b) // -28370

Another option is to create an unsigned integer first, which is then converted to a signed integer with the same bit pattern:

let a : Int64 = 48590108397870
let b = Int16(bitPattern: UInt16(a & 0xFFFF))
print(b) // -28370

You can use withUnsafeBytes(of:_:) to convert the types.

Code:

let a: Int64 = 48590108397870
let b = a & 65535

let c: Int16? = withUnsafeBytes(of: b) { ptr -> Int16? in
    let binded = ptr.bindMemory(to: Int16.self)
    return binded.first
}

print("c: \(c)")
// Prints: c: Optional(-28370)
Related