Swift 5.1 support

Use stdlib Result instead of TAsyncResult

Fix: deprecations for `withUnsafeBytes`

Bump CI job Xcode version

Hash (into)

Co-authored-by: Sophie Lambrakis <SLambrakis@users.noreply.github.com>
Co-authored-by: Alexander Edge <alex@alexedge.co.uk>
diff --git a/.travis.yml b/.travis.yml
index 400cfa1..f3dc7e4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -152,22 +152,11 @@
     # ------------------------- phase: swift ------------------------
     # We lint the podspec
     - os: osx
-      osx_image: xcode10.1
+      osx_image: xcode11.3
       language: swift
       script:
         - gem update cocoapods
-        - pod lib lint --allow-warnings --swift-version=3
-      env:
-        - JOB="pod lib lint"
-
-    - os: osx
-      osx_image: xcode10.2
-      language: swift
-      script:
-        - gem update cocoapods
-        - pod lib lint --allow-warnings --swift-version=4.0
-        - pod lib lint --allow-warnings --swift-version=4.2
-        - pod lib lint --allow-warnings --swift-version=5.0
+        - pod lib lint --allow-warnings --swift-version=5.1
       env:
         - JOB="pod lib lint"
 
diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc
index 4a2f87d..ac63ea0 100644
--- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc
@@ -855,37 +855,27 @@
   indent(out) << "extension " << tstruct->get_name() << " : Hashable";
   block_open(out);
   out << endl;
-  indent(out) << visibility << " var hashValue : Int";
+  indent(out) << visibility << " func hash(into hasher: inout Hasher)";
   block_open(out);
 
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
   if (!members.empty()) {
-    indent(out) << "let prime = 31" << endl;
-    indent(out) << "var result = 1" << endl;
     if (!tstruct->is_union()) {
       for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
         t_field* tfield = *m_iter;
-        string accessor = field_is_optional(tfield) ? "?." : ".";
-        string defaultor = field_is_optional(tfield) ? " ?? 0" : "";
-        indent(out) << "result = prime &* result &+ (" << maybe_escape_identifier(tfield->get_name()) << accessor
-                    <<  "hashValue" << defaultor << ")" << endl;
+        indent(out) << "hasher.combine(" << maybe_escape_identifier(tfield->get_name()) << ")" << endl;
       }
     } else {
       indent(out) << "switch self {" << endl;
       for (m_iter = members.begin(); m_iter != members.end(); m_iter++) {
         t_field *tfield = *m_iter;
-        indent(out) << "case ." << tfield->get_name() << "(let val): result = prime &* val.hashValue" << endl;
+        indent(out) << "case ." << tfield->get_name() << "(let val): hasher.combine(val)" << endl;
       }
       indent(out) << "}" << endl << endl;
     }
-    indent(out) << "return result" << endl;
   }
-  else {
-    indent(out) << "return 31" << endl;
-  }
-
   block_close(out);
   out << endl;
   block_close(out);
@@ -2877,8 +2867,8 @@
     }
 
     // completion
-    indent(out) << "///   - completion: TAsyncResult<" << type_name(tfunction->get_returntype())
-                << "> wrapping return and following Exceptions: ";
+    indent(out) << "///   - completion: Result<" << type_name(tfunction->get_returntype())
+                << ", Error> wrapping return and following Exceptions: ";
     t_struct* xs = tfunction->get_xceptions();
     const vector<t_field*>& xceptions = xs->get_members();
     vector<t_field*>::const_iterator x_iter;
@@ -2903,9 +2893,9 @@
   string result = "func " + (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name());
 
   if (!gen_cocoa_) {
-    string response_string = "(TAsyncResult<";
+    string response_string = "(Result<";
     response_string += (ttype->is_void()) ? "Void" : type_name(ttype);
-    response_string += ">) -> Void";
+    response_string += ", Error>) -> Void";
     result += "(" + argument_list(tfunction->get_arglist(), "", false)
             + (targlist->get_members().size() ? ", " : "")
             + "completion: @escaping " + response_string + ")";
diff --git a/lib/swift/Sources/TApplicationError.swift b/lib/swift/Sources/TApplicationError.swift
index bc39396..cfaf285 100644
--- a/lib/swift/Sources/TApplicationError.swift
+++ b/lib/swift/Sources/TApplicationError.swift
@@ -146,9 +146,12 @@
     try proto.writeFieldStop()
     try proto.writeStructEnd()
   }
-  
-  public var hashValue: Int {
-    return error.thriftErrorCode &+ (message?.hashValue ?? 0)
+}
+
+extension TApplicationError: Hashable {
+  public func hash(into hasher: inout Hasher) {
+    hasher.combine(error.thriftErrorCode)
+    hasher.combine(message)
   }
 }
 
diff --git a/lib/swift/Sources/TClient.swift b/lib/swift/Sources/TClient.swift
index cc3288a..049027f 100644
--- a/lib/swift/Sources/TClient.swift
+++ b/lib/swift/Sources/TClient.swift
@@ -40,16 +40,3 @@
     self.factory = factory
   }
 }
-
-
-public enum TAsyncResult<T> {
-  case success(T)
-  case error(Swift.Error)
-  
-  public func value() throws -> T {
-    switch self {
-    case .success(let t): return t
-    case .error(let e): throw e
-    }
-  }
-}
diff --git a/lib/swift/Sources/TCompactProtocol.swift b/lib/swift/Sources/TCompactProtocol.swift
index 5b302d3..81a51f5 100644
--- a/lib/swift/Sources/TCompactProtocol.swift
+++ b/lib/swift/Sources/TCompactProtocol.swift
@@ -371,10 +371,7 @@
     try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
       buff = try self.transport.readAll(size: 8)
     }
-    
-    let i64: UInt64 = buff.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) -> UInt64 in
-      return UnsafePointer<UInt64>(OpaquePointer(ptr)).pointee
-    }
+    let i64: UInt64 = buff.withUnsafeBytes { $0.load(as: UInt64.self) }
     let bits = CFSwapInt64LittleToHost(i64)
     return Double(bitPattern: bits)
   }
diff --git a/lib/swift/Sources/TEnum.swift b/lib/swift/Sources/TEnum.swift
index fedfdb1..2e91f63 100644
--- a/lib/swift/Sources/TEnum.swift
+++ b/lib/swift/Sources/TEnum.swift
@@ -24,7 +24,10 @@
 
 extension TEnum {
   public static var thriftType: TType { return .i32 }
-  public var hashValue: Int { return rawValue.hashValue }
+
+  public func hash(into hasher: inout Hasher) {
+    hasher.combine(rawValue)
+  }
 
   public func write(to proto: TProtocol) throws {
     try proto.write(rawValue)
diff --git a/lib/swift/Sources/TFileTransport.swift b/lib/swift/Sources/TFileTransport.swift
index fe2253d..75eba40 100644
--- a/lib/swift/Sources/TFileTransport.swift
+++ b/lib/swift/Sources/TFileTransport.swift
@@ -88,7 +88,7 @@
   
   public func write(data: Data) throws {
     let bytesWritten = data.withUnsafeBytes {
-      fwrite($0, 1, data.count, self.fileHandle)
+      fwrite($0.baseAddress!, 1, data.count, self.fileHandle)
     }
     if bytesWritten != data.count {
       throw TTransportError(error: .unknown)
diff --git a/lib/swift/Sources/TList.swift b/lib/swift/Sources/TList.swift
index c239d10..1508d90 100644
--- a/lib/swift/Sources/TList.swift
+++ b/lib/swift/Sources/TList.swift
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-public struct TList<Element : TSerializable> : RandomAccessCollection, MutableCollection, ExpressibleByArrayLiteral, TSerializable, Hashable {
+public struct TList<Element : TSerializable & Hashable> : RandomAccessCollection, MutableCollection, ExpressibleByArrayLiteral, TSerializable, Hashable {
   public typealias Storage = Array<Element>
   public typealias Indices = Storage.Indices
 
@@ -31,13 +31,8 @@
   }
 
   /// Mark: Hashable
-  public var hashValue : Int {
-    let prime = 31
-    var result = 1
-    for element in storage {
-      result = prime &* result &+ element.hashValue
-    }
-    return result
+  public func hash(into hasher: inout Hasher) {
+    hasher.combine(storage)
   }
   
   /// Mark: TSerializable
diff --git a/lib/swift/Sources/TMap.swift b/lib/swift/Sources/TMap.swift
index dcf1481..8f52067 100644
--- a/lib/swift/Sources/TMap.swift
+++ b/lib/swift/Sources/TMap.swift
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-public struct TMap<Key : TSerializable & Hashable, Value : TSerializable>: Collection, ExpressibleByDictionaryLiteral, Hashable, TSerializable {
+public struct TMap<Key : TSerializable & Hashable, Value : TSerializable & Hashable>: Collection, ExpressibleByDictionaryLiteral, Hashable, TSerializable {
   public typealias Storage = Dictionary<Key, Value>
   public typealias Element = Storage.Element
   public typealias Index = Storage.Index
@@ -111,15 +111,9 @@
   }
 
   /// Mark: Hashable
-  
-  public var hashValue: Int {
-    let prime = 31
-    var result = 1
-    for (key, value) in storage {
-      result = prime &* result &+ key.hashValue
-      result = prime &* result &+ value.hashValue
-    }
-    return result
+
+  public func hash(into hasher: inout Hasher) {
+    hasher.combine(storage)
   }
   
   /// Mark: TSerializable
diff --git a/lib/swift/Sources/TSerializable.swift b/lib/swift/Sources/TSerializable.swift
index b45096b..1374700 100644
--- a/lib/swift/Sources/TSerializable.swift
+++ b/lib/swift/Sources/TSerializable.swift
@@ -21,7 +21,6 @@
 
 
 public protocol TSerializable {
-  var hashValue: Int { get }
 
   /// TType for instance
   static var thriftType: TType { get }
@@ -43,10 +42,6 @@
   public var thriftType: TType { return Self.thriftType }
 }
 
-public func ==<T>(lhs: T, rhs: T) -> Bool where T : TSerializable {
-  return lhs.hashValue == rhs.hashValue
-}
-
 /// Default read/write for primitave Thrift types:
 /// Bool, Int8 (byte), Int16, Int32, Int64, Double, String
 
diff --git a/lib/swift/Sources/TSet.swift b/lib/swift/Sources/TSet.swift
index 6891c11..d340fec 100644
--- a/lib/swift/Sources/TSet.swift
+++ b/lib/swift/Sources/TSet.swift
@@ -126,13 +126,8 @@
 
   
   /// Mark: Hashable
-  public var hashValue : Int {
-    let prime = 31
-    var result = 1
-    for element in storage {
-      result = prime &* result &+ element.hashValue
-    }
-    return result
+  public func hash(into hasher: inout Hasher) {
+    hasher.combine(storage)
   }
   
   /// Mark: TSerializable
diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift
index a3c6389..6cfb5a1 100644
--- a/lib/swift/Sources/TSocketServer.swift
+++ b/lib/swift/Sources/TSocketServer.swift
@@ -82,7 +82,7 @@
       let address = Data(bytes: ptr, count: MemoryLayout<sockaddr_in>.size)
 
       let cfaddr = address.withUnsafeBytes {
-        CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0, address.count, nil)
+        CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0.bindMemory(to: UInt8.self).baseAddress!, address.count, nil)
       }
       if CFSocketSetAddress(sock, cfaddr) != CFSocketError.success { //kCFSocketSuccess {
         CFSocketInvalidate(sock)
diff --git a/lib/swift/Sources/TSocketTransport.swift b/lib/swift/Sources/TSocketTransport.swift
index 2132503..57f6215 100644
--- a/lib/swift/Sources/TSocketTransport.swift
+++ b/lib/swift/Sources/TSocketTransport.swift
@@ -198,7 +198,7 @@
     var writeBuffer = data
     while bytesToWrite > 0 {
       let written = writeBuffer.withUnsafeBytes {
-        Sys.write(socketDescriptor, $0, writeBuffer.count)
+        Sys.write(socketDescriptor, $0.baseAddress!, writeBuffer.count)
       }
       writeBuffer = writeBuffer.subdata(in: written ..< writeBuffer.count)
       bytesToWrite -= written
diff --git a/lib/swift/Sources/TStreamTransport.swift b/lib/swift/Sources/TStreamTransport.swift
index d9c9574..5dd7dba 100644
--- a/lib/swift/Sources/TStreamTransport.swift
+++ b/lib/swift/Sources/TStreamTransport.swift
@@ -104,10 +104,7 @@
       
       var bytesWritten = 0
       while bytesWritten < data.count {
-        bytesWritten = data.withUnsafeBytes {
-          return output.write($0, maxLength: data.count)
-        }
-        
+        bytesWritten = data.withUnsafeBytes { output.write($0.bindMemory(to: UInt8.self).baseAddress!, maxLength: data.count) }
         if bytesWritten == -1 {
           throw TTransportError(error: .notOpen)
         } else if bytesWritten == 0 {
diff --git a/lib/swift/Sources/TStruct.swift b/lib/swift/Sources/TStruct.swift
index 38e51e7..f120833 100644
--- a/lib/swift/Sources/TStruct.swift
+++ b/lib/swift/Sources/TStruct.swift
@@ -45,15 +45,6 @@
     try proto.writeStructEnd()
   }
   
-  var hashValue: Int {
-    let prime = 31
-    var result = 1
-    self.forEach { _, value, _ in
-      result = prime &* result &+ (value.hashValue)
-    }
-    return result
-  }
-  
   /// Provides a block for handling each (available) thrift property using reflection
   /// Caveat: Skips over optional values