blob: a5d14f9eaa75b64ce1803d5fd709afa20734322b [file] [log] [blame]
/*
* 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
}
}