Skip to content

Instantly share code, notes, and snippets.

@vukcevich
Forked from natecook1000/integerWithBytes.swift
Last active August 29, 2015 14:17
Show Gist options
  • Save vukcevich/8c5aedcf7065f96577b1 to your computer and use it in GitHub Desktop.
Save vukcevich/8c5aedcf7065f96577b1 to your computer and use it in GitHub Desktop.
// 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