147 lines
5.2 KiB
Swift
147 lines
5.2 KiB
Swift
/*
|
|
* 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
|
|
}
|
|
}
|
|
|
|
|