Created
March 6, 2015 13:40
-
-
Save natecook1000/3c5264f31a76ee89ce76 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// integerWithBytes.swift | |
// as seen in http://natecook.com/blog/2015/03/a-sanatorium-for-swift-generics/ | |
// | |
// (c) 2015 Nate Cook, licensed under the MIT license | |
protocol BitshiftOperationsType { | |
func <<(lhs: Self, rhs: Self) -> Self | |
func >>(lhs: Self, rhs: Self) -> Self | |
func <<=(inout lhs: Self, rhs: Self) | |
func >>=(inout lhs: Self, rhs: Self) | |
} | |
protocol ByteConvertible { | |
init(_ value: UInt8) | |
init(truncatingBitPattern: UInt64) | |
} | |
extension Int : BitshiftOperationsType, ByteConvertible { } | |
extension Int8 : BitshiftOperationsType, ByteConvertible { } | |
extension Int16 : BitshiftOperationsType, ByteConvertible { } | |
extension Int32 : BitshiftOperationsType, ByteConvertible { } | |
extension Int64 : BitshiftOperationsType, ByteConvertible { | |
init(truncatingBitPattern value: UInt64) { | |
self = Int64(bitPattern: value) | |
} | |
} | |
extension UInt : BitshiftOperationsType, ByteConvertible { } | |
extension UInt8 : BitshiftOperationsType, ByteConvertible { } | |
extension UInt16 : BitshiftOperationsType, ByteConvertible { } | |
extension UInt32 : BitshiftOperationsType, ByteConvertible { } | |
extension UInt64 : BitshiftOperationsType, ByteConvertible { | |
init(truncatingBitPattern value: UInt64) { | |
self = value | |
} | |
} | |
func integerWithBytes<T: IntegerType where T: ByteConvertible, T: BitshiftOperationsType> | |
(bytes: [UInt8]) -> T? | |
{ | |
if bytes.count != sizeof(T) { | |
return nil | |
} | |
if sizeof(T) == 1 { | |
return T(truncatingBitPattern: UInt64(bytes[0])) | |
} | |
var result: T = 0 | |
for byte in bytes.reverse() { | |
result = result << 8 | T(byte) | |
} | |
return result | |
} | |
let bytes: [UInt8] = [0xFF, 0xFF, 0xFF, 0xFF] | |
let unsignedInteger: UInt32? = integerWithBytes(bytes) | |
let signedInteger: Int32? = integerWithBytes(bytes) | |
let shouldBeNil: UInt32? = integerWithBytes([1]) | |
let shouldBeOne: UInt32? = integerWithBytes([1, 0, 0, 0]) | |
let test1: UInt8? = integerWithBytes([1]) | |
let test2: UInt8? = integerWithBytes([0xFF]) | |
let test3: Int8? = integerWithBytes([1]) | |
let test4: Int8? = integerWithBytes([0xFF]) | |
let maxInt: Int? = integerWithBytes([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F]) | |
Int.max == maxInt | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment