THRIFT-3773: Swift 3 changes, Squashed (#1084)

Client: swift
diff --git a/lib/swift/Sources/TProtocolError.swift b/lib/swift/Sources/TProtocolError.swift
new file mode 100644
index 0000000..a5d14f9
--- /dev/null
+++ b/lib/swift/Sources/TProtocolError.swift
@@ -0,0 +1,146 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+
+public struct TProtocolError : TError {
+  public init() { }
+
+  public enum Code : TErrorCode {
+    case unknown
+    case invalidData
+    case negativeSize
+    case sizeLimit(limit: Int, got: Int)
+    case badVersion(expected: String, got: String)
+    case notImplemented
+    case depthLimit
+
+    public var thriftErrorCode: Int {
+      switch self {
+      case .unknown:        return 0
+      case .invalidData:    return 1
+      case .negativeSize:   return 2
+      case .sizeLimit:      return 3
+      case .badVersion:     return 4
+      case .notImplemented: return 5
+      case .depthLimit:     return 6
+      }
+
+    }
+    public var description: String {
+      switch self {
+      case .unknown:        return "Unknown TProtocolError"
+      case .invalidData:    return "Invalid Data"
+      case .negativeSize:   return "Negative Size"
+      case .sizeLimit(let limit, let got):
+        return "Message exceeds size limit of \(limit) (received: \(got)"
+      case .badVersion(let expected, let got):
+        return "Bad Version. (Expected: \(expected), Got: \(got)"
+      case .notImplemented: return "Not Implemented"
+      case .depthLimit:     return "Depth Limit"
+      }
+    }
+  }
+
+  public enum ExtendedErrorCode : TErrorCode {
+    case unknown
+    case missingRequiredField(fieldName: String)
+    case unexpectedType(type: TType)
+    case mismatchedProtocol(expected: String, got: String)
+    public var thriftErrorCode: Int {
+      switch self {
+      case .unknown:              return 1000
+      case .missingRequiredField: return 1001
+      case .unexpectedType:       return 1002
+      case .mismatchedProtocol:   return 1003
+      }
+    }
+    public var description: String {
+      switch self {
+      case .unknown:                                    return "Unknown TProtocolExtendedError"
+      case .missingRequiredField(let fieldName):        return "Missing Required Field: \(fieldName)"
+      case .unexpectedType(let type):                   return "Unexpected Type \(type.self)"
+      case .mismatchedProtocol(let expected, let got):  return "Mismatched Protocol.  (Expected: \(expected), got \(got))"
+      }
+    }
+  }
+
+  public var extendedError: ExtendedErrorCode? = nil
+
+  public init(error: Code = .unknown,
+              message: String? = nil,
+              extendedError: ExtendedErrorCode? = nil) {
+    self.error = error
+    self.message = message
+    self.extendedError = extendedError
+  }
+
+  /// Mark: TError
+  public var error: Code = .unknown
+  public var message: String? = nil
+  public static var defaultCase: Code { return .unknown }
+
+  public var description: String {
+    var out = "\(TProtocolError.self):  (\(error.thriftErrorCode) \(error.description)\n"
+    if let extendedError = extendedError {
+      out += "TProtocolExtendedError (\(extendedError.thriftErrorCode)): \(extendedError.description)"
+    }
+    if let message = message {
+      out += "Message: \(message)"
+    }
+    return out
+  }
+}
+
+
+/// Wrapper for Transport errors in Protocols.  Inspired by Thrift-Cocoa PROTOCOL_TRANSPORT_ERROR
+/// macro.  Modified to be more Swift-y.  Catches any TError thrown within the block and
+/// rethrows a given TProtocolError, the original error's description is appended to the new
+/// TProtocolError's message.  sourceFile, sourceLine, sourceMethod are auto-populated and should
+/// be ignored when calling.
+///
+/// - parameter error:        TProtocolError to throw if the block throws
+/// - parameter sourceFile:   throwing file, autopopulated
+/// - parameter sourceLine:   throwing line, autopopulated
+/// - parameter sourceMethod: throwing method, autopopulated
+/// - parameter block:        throwing block
+///
+/// - throws: TProtocolError  Default is TProtocolError.ErrorCode.unknown.  Underlying
+///                           error's description appended to TProtocolError.message
+func ProtocolTransportTry(error: TProtocolError = TProtocolError(),
+                          sourceFile: String = #file,
+                          sourceLine: Int = #line,
+                          sourceMethod: String = #function,
+                          block: () throws -> ()) throws {
+  // Need mutable copy
+  var error = error
+  do {
+    try block()
+  } catch let err as TError {
+    var message = error.message ?? ""
+    message += "\nFile: \(sourceFile)\n"
+    message += "Line: \(sourceLine)\n"
+    message += "Method: \(sourceMethod)"
+    message += "\nOriginal Error:\n" + err.description
+    error.message = message
+    throw error
+  }
+}
+
+