Generics.swift 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. //
  2. // Generics.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 02/09/14.
  6. // Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. /** Protocol and extensions for integerFrom(bits:). Bit hakish for me, but I can't do it in any other way */
  9. protocol Initiable {
  10. init(_ v: Int)
  11. init(_ v: UInt)
  12. }
  13. extension Int:Initiable {}
  14. extension UInt:Initiable {}
  15. extension UInt8:Initiable {}
  16. extension UInt16:Initiable {}
  17. extension UInt32:Initiable {}
  18. extension UInt64:Initiable {}
  19. /** build bit pattern from array of bits */
  20. @_specialize(UInt8)
  21. func integerFrom<T: UnsignedInteger>(_ bits: Array<Bit>) -> T
  22. {
  23. var bitPattern:T = 0
  24. for idx in bits.indices {
  25. if bits[idx] == Bit.one {
  26. let bit = T(UIntMax(1) << UIntMax(idx))
  27. bitPattern = bitPattern | bit
  28. }
  29. }
  30. return bitPattern
  31. }
  32. /// Array of bytes, little-endian representation. Don't use if not necessary.
  33. /// I found this method slow
  34. func arrayOfBytes<T>(value:T, length:Int? = nil) -> Array<UInt8> {
  35. let totalBytes = length ?? MemoryLayout<T>.size
  36. let valuePointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
  37. valuePointer.pointee = value
  38. let bytesPointer = UnsafeMutablePointer<UInt8>(OpaquePointer(valuePointer))
  39. var bytes = Array<UInt8>(repeating: 0, count: totalBytes)
  40. for j in 0..<min(MemoryLayout<T>.size,totalBytes) {
  41. bytes[totalBytes - 1 - j] = (bytesPointer + j).pointee
  42. }
  43. valuePointer.deinitialize()
  44. valuePointer.deallocate(capacity: 1)
  45. return bytes
  46. }
  47. // MARK: - shiftLeft
  48. // helper to be able to make shift operation on T
  49. @_specialize(Int)
  50. func << <T:SignedInteger>(lhs: T, rhs: Int) -> Int {
  51. let a = lhs as! Int
  52. let b = rhs
  53. return a << b
  54. }
  55. @_specialize(UInt)
  56. func << <T:UnsignedInteger>(lhs: T, rhs: Int) -> UInt {
  57. let a = lhs as! UInt
  58. let b = rhs
  59. return a << b
  60. }
  61. // Generic function itself
  62. // FIXME: this generic function is not as generic as I would. It crashes for smaller types
  63. @_specialize(Int)
  64. func shiftLeft<T: SignedInteger>(_ value: T, by count: Int) -> T where T: Initiable {
  65. if (value == 0) {
  66. return 0;
  67. }
  68. let bitsCount = (MemoryLayout<T>.size * 8)
  69. let shiftCount = Int(Swift.min(count, bitsCount - 1))
  70. var shiftedValue:T = 0;
  71. for bitIdx in 0..<bitsCount {
  72. let bit = T(IntMax(1 << bitIdx))
  73. if ((value & bit) == bit) {
  74. shiftedValue = shiftedValue | T(bit << shiftCount)
  75. }
  76. }
  77. if (shiftedValue != 0 && count >= bitsCount) {
  78. // clear last bit that couldn't be shifted out of range
  79. shiftedValue = shiftedValue & T(~(1 << (bitsCount - 1)))
  80. }
  81. return shiftedValue
  82. }
  83. // for any f*** other Integer type - this part is so non-Generic
  84. func shiftLeft(_ value: UInt, by count: Int) -> UInt {
  85. return UInt(shiftLeft(Int(value), by: count))
  86. }
  87. func shiftLeft(_ value: UInt8, by count: Int) -> UInt8 {
  88. return UInt8(shiftLeft(UInt(value), by: count))
  89. }
  90. func shiftLeft(_ value: UInt16, by count: Int) -> UInt16 {
  91. return UInt16(shiftLeft(UInt(value), by: count))
  92. }
  93. func shiftLeft(_ value: UInt32, by count: Int) -> UInt32 {
  94. return UInt32(shiftLeft(UInt(value), by: count))
  95. }
  96. func shiftLeft(_ value: UInt64, by count: Int) -> UInt64 {
  97. return UInt64(shiftLeft(UInt(value), by: count))
  98. }
  99. func shiftLeft(_ value: Int8, by count: Int) -> Int8 {
  100. return Int8(shiftLeft(Int(value), by: count))
  101. }
  102. func shiftLeft(_ value: Int16, by count: Int) -> Int16 {
  103. return Int16(shiftLeft(Int(value), by: count))
  104. }
  105. func shiftLeft(_ value: Int32, by count: Int) -> Int32 {
  106. return Int32(shiftLeft(Int(value), by: count))
  107. }
  108. func shiftLeft(_ value: Int64, by count: Int) -> Int64 {
  109. return Int64(shiftLeft(Int(value), by: count))
  110. }