/* * 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 } }