Explorar o código

Collection.toInteger() is neat but painfully slow therefore deprecated

Marcin Krzyżanowski %!s(int64=9) %!d(string=hai) anos
pai
achega
144f94ca38

+ 5 - 3
Sources/CryptoSwift/Collection+Extension.swift

@@ -42,20 +42,22 @@ extension Collection where Self.Iterator.Element == UInt8, Self.Index == Int {
     }
 
     /// Initialize integer from array of bytes. Caution: may be slow!
+    @available(*, deprecated: 0.6.0, message: "Dont use it. Too generic to be fast")
     func toInteger<T:Integer>() -> T where T: ByteConvertible, T: BitshiftOperationsType {
         if self.count == 0 {
             return 0;
         }
 
+        let size = MemoryLayout<T>.size
         var bytes = self.reversed() //FIXME: check it this is equivalent of Array(...)
-        if bytes.count < MemoryLayout<T>.size {
-            let paddingCount = MemoryLayout<T>.size - bytes.count
+        if bytes.count < size {
+            let paddingCount = size - bytes.count
             if (paddingCount > 0) {
                 bytes += Array<UInt8>(repeating: 0, count: paddingCount)
             }
         }
 
-        if MemoryLayout<T>.size == 1 {
+        if size == 1 {
             return T(truncatingBitPattern: UInt64(bytes[0]))
         }
 

+ 3 - 3
Sources/CryptoSwift/Int+Extension.swift

@@ -31,9 +31,9 @@ extension Int {
 /* array of bytes */
 extension Int {
     /** Int with collection of bytes (little-endian) */
-    init<T: Collection>(bytes: T) where T.Iterator.Element == UInt8, T.Index == Int {
-        self = bytes.toInteger()
-    }
+    //init<T: Collection>(bytes: T) where T.Iterator.Element == UInt8, T.Index == Int {
+    //    self = bytes.toInteger()
+    //}
 
     /** Array of bytes with optional padding (little-endian) */
     func bytes(totalBytes: Int = MemoryLayout<Int>.size) -> Array<UInt8> {

+ 8 - 1
Sources/CryptoSwift/UInt16+Extension.swift

@@ -9,7 +9,14 @@
 /** array of bytes */
 extension UInt16 {
     init<T: Collection>(bytes: T) where T.Iterator.Element == UInt8, T.Index == Int {
-        self = bytes.toInteger()
+        self = UInt16(bytes: bytes, fromIndex: bytes.startIndex)
+    }
+
+    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Iterator.Element == UInt8, T.Index == Int {
+        let val0 = UInt16(bytes[index.advanced(by: 0)]) << 8
+        let val1 = UInt16(bytes[index.advanced(by: 1)])
+
+        self = val0 | val1
     }
 
     func bytes(totalBytes: Int = MemoryLayout<UInt16>.size) -> Array<UInt8> {

+ 10 - 1
Sources/CryptoSwift/UInt32+Extension.swift

@@ -19,7 +19,16 @@ extension UInt32: _UInt32Type {}
 /** array of bytes */
 extension UInt32 {
     init<T: Collection>(bytes: T) where T.Iterator.Element == UInt8, T.Index == Int {
-        self = bytes.toInteger()
+        self = UInt32(bytes: bytes, fromIndex: bytes.startIndex)
+    }
+
+    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Iterator.Element == UInt8, T.Index == Int {
+        let val0 = UInt32(bytes[index.advanced(by: 0)]) << 24
+        let val1 = UInt32(bytes[index.advanced(by: 1)]) << 16
+        let val2 = UInt32(bytes[index.advanced(by: 2)]) << 8
+        let val3 = UInt32(bytes[index.advanced(by: 3)])
+
+        self = val0 | val1 | val2 | val3
     }
 
     func bytes(totalBytes: Int = MemoryLayout<UInt32>.size) -> Array<UInt8> {

+ 13 - 1
Sources/CryptoSwift/UInt64+Extension.swift

@@ -9,9 +9,21 @@
 /** array of bytes */
 extension UInt64 {
     init<T: Collection>(bytes: T) where T.Iterator.Element == UInt8, T.Index == Int {
-        self = bytes.toInteger()
+        self = UInt64(bytes: bytes, fromIndex: bytes.startIndex)
     }
 
+    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Iterator.Element == UInt8, T.Index == Int {
+        let val0 = UInt64(bytes[index.advanced(by: 0)]) << 56
+        let val1 = UInt64(bytes[index.advanced(by: 1)]) << 48
+        let val2 = UInt64(bytes[index.advanced(by: 2)]) << 40
+        let val3 = UInt64(bytes[index.advanced(by: 3)]) << 32
+        let val4 = UInt64(bytes[index.advanced(by: 4)]) << 24
+        let val5 = UInt64(bytes[index.advanced(by: 5)]) << 16
+        let val6 = UInt64(bytes[index.advanced(by: 6)]) << 8
+        let val7 = UInt64(bytes[index.advanced(by: 7)])
+
+        self = val0 | val1 | val2 | val3 | val4 | val5 | val6 | val7
+    }
     func bytes(totalBytes: Int = MemoryLayout<UInt64>.size) -> Array<UInt8> {
         return arrayOfBytes(value: self, length: totalBytes)
     }

+ 0 - 16
Tests/CryptoSwiftTests/ExtensionsTest.swift

@@ -19,21 +19,6 @@ final class ExtensionsTest: XCTestCase {
             self.stopMeasuring()
         })
     }
-
-    
-    func testIntExtension() {
-        let i1:Int = 1024
-        let i1Array = i1.bytes(totalBytes: 32 / 8) // 32 bit
-        let i1recovered = Int(bytes: i1Array)
-        
-        XCTAssertEqual(i1, i1recovered, "Bytes conversion failed")
-        
-        let i2:Int = 1024
-        let i2Array = i2.bytes(totalBytes: 160 / 8) // 160 bit
-        let i2recovered = Int(bytes: i2Array)
-        
-        XCTAssertEqual(i2, i2recovered, "Bytes conversion failed")
-    }
     
     func testBytes() {
         let size = MemoryLayout<UInt32>.size // 32 or 64  bit
@@ -89,7 +74,6 @@ final class ExtensionsTest: XCTestCase {
 
     static let allTests =  [
         ("testArrayChunksPerformance", testArrayChunksPerformance),
-        ("testIntExtension", testIntExtension),
         ("testBytes", testBytes),
         ("testToUInt32Array", testToUInt32Array),
         ("testDataInit", testDataInit),