THRIFT-4902: Swift 4 and 5 compatibility (#1827)

diff --git a/.travis.yml b/.travis.yml
index 4a399a6..400cfa1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -148,7 +148,28 @@
       env:
         - JOB="Coverity Scan"
         - SCRIPT="covscan.sh"
-     
+
+    # ------------------------- phase: swift ------------------------
+    # We lint the podspec
+    - os: osx
+      osx_image: xcode10.1
+      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
+      env:
+        - JOB="pod lib lint"
 
   ### ------------------------- phase: osx --------------------------
   # disabled due to the time delays it imposes on build jobs
diff --git a/Thrift.podspec b/Thrift.podspec
index cb1c9b2..4c8fa68 100644
--- a/Thrift.podspec
+++ b/Thrift.podspec
@@ -1,16 +1,15 @@
 Pod::Spec.new do |s|
-  s.name          = "Thrift-swift3"
-  s.version       = "0.13.0"
+  s.name          = 'Thrift'
+  s.version       = '0.13.0'
   s.summary       = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC."
   s.description   = <<-DESC
 The Apache Thrift scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages.
                     DESC
-  s.homepage      = "http://thrift.apache.org"
+  s.homepage      = 'https://thrift.apache.org'
   s.license       = { :type => 'Apache License, Version 2.0', :url => 'https://www.apache.org/licenses/LICENSE-2.0' }
-  s.author        = { "Apache Thrift Developers" => "dev@thrift.apache.org" }
+  s.author        = { 'Apache Thrift Developers' => 'dev@thrift.apache.org' }
   s.ios.deployment_target = '9.0'
   s.osx.deployment_target = '10.10'
-  s.requires_arc  = true
-  s.source        = { :git => "https://github.com/apache/thrift.git", :tag => "v0.13.0" }
-  s.source_files  = "lib/swift/Sources/*.swift"
+  s.source        = { :git => 'https://github.com/apache/thrift.git', :tag => 'v0.13.0' }
+  s.source_files  = 'lib/swift/Sources/*.swift'
 end
diff --git a/lib/swift/Sources/TBinaryProtocol.swift b/lib/swift/Sources/TBinaryProtocol.swift
index a97249a..85acce0 100644
--- a/lib/swift/Sources/TBinaryProtocol.swift
+++ b/lib/swift/Sources/TBinaryProtocol.swift
@@ -325,7 +325,7 @@
   }
   
   public func write(_ value: UInt8) throws {
-    let buff = Data(bytes: [value])
+    let buff = Data([value])
     
     try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
       try self.transport.write(data: buff)
@@ -334,8 +334,8 @@
   
   public func write(_ value: Int16) throws {
     var buff = Data()
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 8))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value))]))
+    buff.append(Data([UInt8(0xff & (value >> 8))]))
+    buff.append(Data([UInt8(0xff & (value))]))
     try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
       try self.transport.write(data: buff)
     }
@@ -343,10 +343,10 @@
   
   public func write(_ value: Int32) throws {
     var buff = Data()
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 24))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 16))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 8))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value))]))
+    buff.append(Data([UInt8(0xff & (value >> 24))]))
+    buff.append(Data([UInt8(0xff & (value >> 16))]))
+    buff.append(Data([UInt8(0xff & (value >> 8))]))
+    buff.append(Data([UInt8(0xff & (value))]))
     
     try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
       try self.transport.write(data: buff)
@@ -355,14 +355,14 @@
   
   public func write(_ value: Int64) throws {
     var buff = Data()
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 56))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 48))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 40))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 32))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 24))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 16))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value >> 8))]))
-    buff.append(Data(bytes: [UInt8(0xff & (value))]))
+    buff.append(Data([UInt8(0xff & (value >> 56))]))
+    buff.append(Data([UInt8(0xff & (value >> 48))]))
+    buff.append(Data([UInt8(0xff & (value >> 40))]))
+    buff.append(Data([UInt8(0xff & (value >> 32))]))
+    buff.append(Data([UInt8(0xff & (value >> 24))]))
+    buff.append(Data([UInt8(0xff & (value >> 16))]))
+    buff.append(Data([UInt8(0xff & (value >> 8))]))
+    buff.append(Data([UInt8(0xff & (value))]))
     
     try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
       try self.transport.write(data: buff)
diff --git a/lib/swift/Sources/TCompactProtocol.swift b/lib/swift/Sources/TCompactProtocol.swift
index 59773c3..5b302d3 100644
--- a/lib/swift/Sources/TCompactProtocol.swift
+++ b/lib/swift/Sources/TCompactProtocol.swift
@@ -67,7 +67,7 @@
   /// Mark: - TCompactProtocol helpers
   
   func writebyteDirect(_ byte: UInt8) throws {
-    let byte = Data(bytes: [byte])
+    let byte = Data([byte])
     try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
       try self.transport.write(data: byte)
     }
@@ -90,7 +90,7 @@
     }
     
     try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
-      try self.transport.write(data: Data(bytes: i32buf[0..<idx]))
+      try self.transport.write(data: Data(i32buf[0..<idx]))
     }
   }
   
@@ -111,9 +111,8 @@
     }
     
     try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
-      try self.transport.write(data: Data(bytes: varint64out[0..<idx]))
+      try self.transport.write(data: Data(varint64out[0..<idx]))
     }
-  
   }
   
   func writeCollectionBegin(_ elementType: TType, size: Int32) throws {
@@ -249,7 +248,6 @@
       let got      = String(format:"%2X", protocolId)
       throw TProtocolError(message: "Wrong Protocol ID \(got)",
                            extendedError: .mismatchedProtocol(expected: expected, got: got))
-
     }
 
     let versionAndType: UInt8 = try read()
@@ -257,7 +255,6 @@
     if version != TCompactProtocol.version {
       throw TProtocolError(error: .badVersion(expected: "\(TCompactProtocol.version)",
                                               got:"\(version)"))
-
     }
     
     let type = (versionAndType >> UInt8(TCType.typeShiftAmount)) & TCType.typeBits
@@ -485,7 +482,6 @@
     }
     
     lastFieldId = UInt8(fieldID)
-      
   }
   
   public func writeFieldStop() throws {
diff --git a/lib/swift/Sources/TFramedTransport.swift b/lib/swift/Sources/TFramedTransport.swift
index ca385d6..59855eb 100644
--- a/lib/swift/Sources/TFramedTransport.swift
+++ b/lib/swift/Sources/TFramedTransport.swift
@@ -92,10 +92,10 @@
 
   private func encodeFrameSize(size: UInt32) -> Data {
     var data = Data()
-    data.append(Data(bytes: [UInt8(0xff & (size >> 24))]))
-    data.append(Data(bytes: [UInt8(0xff & (size >> 16))]))
-    data.append(Data(bytes: [UInt8(0xff & (size >> 8))]))
-    data.append(Data(bytes: [UInt8(0xff & (size))]))
+    data.append(Data([UInt8(0xff & (size >> 24))]))
+    data.append(Data([UInt8(0xff & (size >> 16))]))
+    data.append(Data([UInt8(0xff & (size >> 8))]))
+    data.append(Data([UInt8(0xff & (size))]))
 
     return data
   }
diff --git a/lib/swift/Sources/TMap.swift b/lib/swift/Sources/TMap.swift
index 8980377..dcf1481 100644
--- a/lib/swift/Sources/TMap.swift
+++ b/lib/swift/Sources/TMap.swift
@@ -21,7 +21,7 @@
   public typealias Storage = Dictionary<Key, Value>
   public typealias Element = Storage.Element
   public typealias Index = Storage.Index
-  public typealias IndexDistance = Storage.IndexDistance
+  public typealias IndexDistance = Int
   public typealias Indices = Storage.Indices
   public typealias SubSequence = Storage.SubSequence
   internal var storage = Storage()
@@ -33,11 +33,7 @@
   }
   
   public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
-    return updateValue(value, forKey: key)
-  }
-  
-  public mutating func removeAtIndex(_ index: DictionaryIndex<Key, Value>) -> (Key, Value) {
-    return removeAtIndex(index)
+    return storage.updateValue(value, forKey: key)
   }
   
   public mutating func removeValueForKey(_ key: Key) -> Value? {
diff --git a/lib/swift/Sources/TProtocol.swift b/lib/swift/Sources/TProtocol.swift
index b111e71..b4e5dbe 100644
--- a/lib/swift/Sources/TProtocol.swift
+++ b/lib/swift/Sources/TProtocol.swift
@@ -18,7 +18,6 @@
 */
 
 import Foundation
-//
 
 public enum TMessageType: Int32 {
   case call = 1
@@ -99,19 +98,19 @@
 }
 
 public extension TProtocol {
-  public func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws {
+  func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws {
     try writeFieldBegin(name: name, type: type, fieldID: id)
     try value.write(to: self)
     try writeFieldEnd()
   }
 
-  public func validateValue(_ value: Any?, named name: String) throws {
+  func validateValue(_ value: Any?, named name: String) throws {
     if value == nil {
       throw TProtocolError(error: .unknown, message: "Missing required value for field: \(name)")
     }
   }
   
-  public func readResultMessageBegin() throws {
+  func readResultMessageBegin() throws {
     let (_, type, _) = try readMessageBegin();
     if type == .exception {
       let x = try readException()
@@ -120,17 +119,17 @@
     return
   }
   
-  public func readException() throws -> TApplicationError {
+  func readException() throws -> TApplicationError {
     return try TApplicationError.read(from: self)
   }
   
-  public func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws {
+  func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws {
     try writeMessageBegin(name: name, type: .exception, sequenceID: sequenceID)
     try ex.write(to: self)
     try writeMessageEnd()
   }
   
-  public func skip(type: TType) throws {
+  func skip(type: TType) throws {
     switch type {
     case .bool:   _ = try read() as Bool
     case .i8:   _ = try read() as UInt8
diff --git a/lib/swift/Sources/TSSLSocketTransport.swift b/lib/swift/Sources/TSSLSocketTransport.swift
index c2b5902..d350f82 100644
--- a/lib/swift/Sources/TSSLSocketTransport.swift
+++ b/lib/swift/Sources/TSSLSocketTransport.swift
@@ -20,6 +20,13 @@
 import Foundation
 import CoreFoundation
 
+#if !swift(>=4.2)
+// Swift 3/4 compatibility
+fileprivate extension RunLoopMode {
+  static let `default` = defaultRunLoopMode
+}
+#endif
+
 #if os(Linux)
 public class TSSLSocketTransport {
   init(hostname: String, port: UInt16) {
@@ -98,18 +105,18 @@
       
       CFReadStreamSetProperty(readStream?.takeRetainedValue(),
                               .SSLSettings,
-                              settings as CFTypeRef!)
+                              settings as CFTypeRef)
       
       CFWriteStreamSetProperty(writeStream?.takeRetainedValue(),
                               .SSLSettings,
-                              settings as CFTypeRef!)
+                              settings as CFTypeRef)
       
       inputStream = readStream!.takeRetainedValue()
-      inputStream?.schedule(in: .current, forMode: .defaultRunLoopMode)
+      inputStream?.schedule(in: .current, forMode: .default)
       inputStream?.open()
       
       outputStream = writeStream!.takeRetainedValue()
-      outputStream?.schedule(in: .current, forMode: .defaultRunLoopMode)
+      outputStream?.schedule(in: .current, forMode: .default)
       outputStream?.open()
       
       readStream?.release()
diff --git a/lib/swift/Sources/TSet.swift b/lib/swift/Sources/TSet.swift
index 1ecd170..6891c11 100644
--- a/lib/swift/Sources/TSet.swift
+++ b/lib/swift/Sources/TSet.swift
@@ -32,7 +32,7 @@
   
   public typealias Indices = Storage.Indices
   public typealias Index = Storage.Index
-  public typealias IndexDistance = Storage.IndexDistance
+  public typealias IndexDistance = Int
   public typealias SubSequence = Storage.SubSequence
   
   
diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift
index 0224e67..7367c7e 100644
--- a/lib/swift/Sources/TSocketServer.swift
+++ b/lib/swift/Sources/TSocketServer.swift
@@ -105,7 +105,6 @@
                                                 [weak self] notification in
                                                 guard let strongSelf = self else { return }
                                                 strongSelf.connectionAccepted(strongSelf.socketFileHandle)
-
     }
 
     // tell socket to listen
diff --git a/lib/swift/Sources/TSocketTransport.swift b/lib/swift/Sources/TSocketTransport.swift
index 0316e37..2132503 100644
--- a/lib/swift/Sources/TSocketTransport.swift
+++ b/lib/swift/Sources/TSocketTransport.swift
@@ -29,6 +29,13 @@
 import Foundation
 import CoreFoundation
 
+#if !swift(>=4.2)
+// Swift 3/4 compatibility
+fileprivate extension RunLoopMode {
+  static let `default` = defaultRunLoopMode
+}
+#endif
+
 private struct Sys {
   #if os(Linux)
   static let read = Glibc.read
@@ -72,7 +79,7 @@
     var readStream:  Unmanaged<CFReadStream>?
     var writeStream:  Unmanaged<CFWriteStream>?
     CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
-                                       hostname as CFString!,
+                                       hostname as CFString,
                                        UInt32(port),
                                        &readStream,
                                        &writeStream)
@@ -88,11 +95,11 @@
         }
 
       inputStream = readStream as InputStream
-      inputStream.schedule(in: .current, forMode: .defaultRunLoopMode)
+      inputStream.schedule(in: .current, forMode: .default)
       inputStream.open()
       
       outputStream = writeStream as OutputStream
-      outputStream.schedule(in: .current, forMode: .defaultRunLoopMode)
+      outputStream.schedule(in: .current, forMode: .default)
       outputStream.open()
       
     } else {
@@ -140,7 +147,6 @@
     }
     
     
-    
     #if os(Linux)
       let sock = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0)
       var addr = sockaddr_in(sin_family: sa_family_t(AF_INET),
@@ -184,7 +190,7 @@
     var buff = Array<UInt8>.init(repeating: 0, count: size)
     let readBytes = Sys.read(socketDescriptor, &buff, size)
     
-    return Data(bytes: buff[0..<readBytes])
+    return Data(buff[0..<readBytes])
   }
   
   public func write(data: Data) {
diff --git a/lib/swift/Sources/TStreamTransport.swift b/lib/swift/Sources/TStreamTransport.swift
index 26bc1b8..d9c9574 100644
--- a/lib/swift/Sources/TStreamTransport.swift
+++ b/lib/swift/Sources/TStreamTransport.swift
@@ -20,6 +20,13 @@
 import Foundation
 import CoreFoundation
 
+#if !swift(>=4.2)
+// Swift 3/4 compatibility
+fileprivate extension RunLoopMode {
+  static let `default` = defaultRunLoopMode
+}
+#endif
+
 #if os(Linux)
   /// Currently unavailable in Linux
   /// Remove comments and build to fix
@@ -64,7 +71,7 @@
         if bytesRead <= 0 {
           throw TTransportError(error: .notOpen)
         }
-        read.append(Data(bytes: buffer))
+        read.append(Data(buffer))
       }
       return read
     }
@@ -85,7 +92,7 @@
           break
         }
         
-        read.append(Data(bytes: buffer))
+        read.append(Data(buffer))
       }
       return read
     }
@@ -124,7 +131,7 @@
         
         input?.delegate = nil
         input?.close()
-        input?.remove(from: .current, forMode: .defaultRunLoopMode)
+        input?.remove(from: .current, forMode: .default)
         input = nil
       }
       
@@ -135,7 +142,7 @@
         }
         output?.delegate = nil
         output?.close()
-        output?.remove(from: .current, forMode: .defaultRunLoopMode)
+        output?.remove(from: .current, forMode: .default)
         output = nil
       }
     }
diff --git a/lib/swift/Sources/TStruct.swift b/lib/swift/Sources/TStruct.swift
index f172a32..38e51e7 100644
--- a/lib/swift/Sources/TStruct.swift
+++ b/lib/swift/Sources/TStruct.swift
@@ -29,10 +29,10 @@
 }
 
 public extension TStruct {
-  public static var fieldIds: [String: (id: Int32, type: TType)] { return [:] }
-  public static var thriftType: TType { return .struct }
+  static var fieldIds: [String: (id: Int32, type: TType)] { return [:] }
+  static var thriftType: TType { return .struct }
   
-  public func write(to proto: TProtocol) throws {
+  func write(to proto: TProtocol) throws {
     // Write struct name first
     try proto.writeStructBegin(name: Self.structName)
     
@@ -45,7 +45,7 @@
     try proto.writeStructEnd()
   }
   
-  public var hashValue: Int {
+  var hashValue: Int {
     let prime = 31
     var result = 1
     self.forEach { _, value, _ in