Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
integerWithBytes Swift way
// Playground - noun: a place where people can play
import Foundation
typealias Byte = UInt8
protocol GenericIntegerType: IntegerType {
init(_ v: Int)
init(_ v: UInt)
init(_ v: Int8)
init(_ v: UInt8)
init(_ v: Int16)
init(_ v: UInt16)
init(_ v: Int32)
init(_ v: UInt32)
init(_ v: Int64)
init(_ v: UInt64)
}
protocol GenericSignedIntegerBitPattern {
init(bitPattern: UIntMax)
init(truncatingBitPattern: IntMax)
}
protocol GenericUnsignedIntegerBitPattern {
init(truncatingBitPattern: UIntMax)
}
extension Int:GenericIntegerType, GenericSignedIntegerBitPattern {
init(bitPattern: UIntMax) {
self.init(bitPattern: UInt(truncatingBitPattern: bitPattern))
}
}
extension UInt:GenericIntegerType, GenericUnsignedIntegerBitPattern {}
extension Int8:GenericIntegerType, GenericSignedIntegerBitPattern {
init(bitPattern: UIntMax) {
self.init(bitPattern: UInt8(truncatingBitPattern: bitPattern))
}
}
extension UInt8:GenericIntegerType, GenericUnsignedIntegerBitPattern {}
extension Int16:GenericIntegerType, GenericSignedIntegerBitPattern {
init(bitPattern: UIntMax) {
self.init(bitPattern: UInt16(truncatingBitPattern: bitPattern))
}
}
extension UInt16:GenericIntegerType, GenericUnsignedIntegerBitPattern {}
extension Int32:GenericIntegerType, GenericSignedIntegerBitPattern {
init(bitPattern: UIntMax) {
self.init(bitPattern: UInt32(truncatingBitPattern: bitPattern))
}
}
extension UInt32:GenericIntegerType, GenericUnsignedIntegerBitPattern {}
extension Int64:GenericIntegerType, GenericSignedIntegerBitPattern {
// init(bitPattern: UInt64) already defined
init(truncatingBitPattern: IntMax) {
self.init(truncatingBitPattern)
}
}
extension UInt64:GenericIntegerType, GenericUnsignedIntegerBitPattern {
// init(bitPattern: Int64) already defined
init(truncatingBitPattern: UIntMax) {
self.init(truncatingBitPattern)
}
}
func integerWithBytes<T: GenericIntegerType where T: UnsignedIntegerType, T: GenericUnsignedIntegerBitPattern>(bytes:[UInt8]) -> T? {
if (bytes.count < sizeof(T)) {
return nil
}
let maxBytes = sizeof(T)
var i:UIntMax = 0
for (var j = 0; j < maxBytes; j++) {
i = i | T(bytes[j]).toUIntMax() << UIntMax(j * 8)
}
return T(truncatingBitPattern: i)
}
func integerWithBytes<T: GenericIntegerType where T: SignedIntegerType, T: GenericSignedIntegerBitPattern>(bytes:[UInt8]) -> T? {
if (bytes.count < sizeof(T)) {
return nil
}
let maxBytes = sizeof(T)
var i:IntMax = 0
for (var j = 0; j < maxBytes; j++) {
i = i | T(bitPattern: UIntMax(bytes[j].toUIntMax())).toIntMax() << (j * 8).toIntMax()
}
return T(truncatingBitPattern: i)
}
let bytes:[UInt8] = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
integerWithBytes(bytes) as Int8?
integerWithBytes(bytes) as UInt8?
integerWithBytes(bytes) as Int16?
integerWithBytes(bytes) as UInt16?
integerWithBytes(bytes) as Int32?
integerWithBytes(bytes) as UInt32?
integerWithBytes(bytes) as Int64?
integerWithBytes(bytes) as UInt64?

mplewis commented Mar 4, 2015

Thanks for this! Moving bytes between types of integers in Java is hard enough. Just having a reliable conversion module is incredibly helpful for any language.

Owner

krzyzanowskim commented Mar 4, 2015

Thanks! this is more exercise than anything else, but yes It's worth to know how the things getting complicated when it comes to types.

Hi Krzyzanowskim,
Great effort and useful area through!

I am doing some encryption algorithm and trying to do some shift operation using swift 2.0 like this but it always throws crash error (EXC_BAD_INSTRUCTION). It is a signed number. How to solve this issue, please assist. In Java and C it gives me this number : -2147483646

let n : Int = 10
let s : Int = 2

let sh = (n >> s) | (n << -s) //error

Hi @krzyzanowskim ,
I've found your gist and your blog article very useful, thanks!

While working on some bit representation, I think it's better to change the
T(bytes[j])
to
T(bytes[maxBytes - j - 1])
because the input array does not represent the correct byte order of the returned integer IMHO.

For example, with a decimal number 43605, having this binary representation
1010 1010 0101 0101
I think the correct byte array that integerWithBytes should accept is
[170, 85]
and not the reversed one
[85, 170]

Thank you,
Gabriele.

kballard commented Jan 4, 2016

This is ridiculous. You've apparently gone to great lengths to do this as complicated as possible. It's a hell of a lot simpler just to say

func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T? {
    guard bytes.count >= sizeof(T) else { return nil }
    return bytes.withUnsafeBufferPointer({ UnsafePointer<T>($0.baseAddress).memory })
}

@kballard , could you please elaborate on how to use that function with a practical example please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment