blob: a5d14f9eaa75b64ce1803d5fd709afa20734322b [file] [log] [blame]
Chris Simpsona9b6c702018-04-08 07:11:37 -04001/*
2* Licensed to the Apache Software Foundation (ASF) under one
3* or more contributor license agreements. See the NOTICE file
4* distributed with this work for additional information
5* regarding copyright ownership. The ASF licenses this file
6* to you under the Apache License, Version 2.0 (the
7* "License"); you may not use this file except in compliance
8* with the License. You may obtain a copy of the License at
9*
10* http://www.apache.org/licenses/LICENSE-2.0
11*
12* Unless required by applicable law or agreed to in writing,
13* software distributed under the License is distributed on an
14* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15* KIND, either express or implied. See the License for the
16* specific language governing permissions and limitations
17* under the License.
18*/
19
20import Foundation
21
22public struct TProtocolError : TError {
23 public init() { }
24
25 public enum Code : TErrorCode {
26 case unknown
27 case invalidData
28 case negativeSize
29 case sizeLimit(limit: Int, got: Int)
30 case badVersion(expected: String, got: String)
31 case notImplemented
32 case depthLimit
33
34 public var thriftErrorCode: Int {
35 switch self {
36 case .unknown: return 0
37 case .invalidData: return 1
38 case .negativeSize: return 2
39 case .sizeLimit: return 3
40 case .badVersion: return 4
41 case .notImplemented: return 5
42 case .depthLimit: return 6
43 }
44
45 }
46 public var description: String {
47 switch self {
48 case .unknown: return "Unknown TProtocolError"
49 case .invalidData: return "Invalid Data"
50 case .negativeSize: return "Negative Size"
51 case .sizeLimit(let limit, let got):
52 return "Message exceeds size limit of \(limit) (received: \(got)"
53 case .badVersion(let expected, let got):
54 return "Bad Version. (Expected: \(expected), Got: \(got)"
55 case .notImplemented: return "Not Implemented"
56 case .depthLimit: return "Depth Limit"
57 }
58 }
59 }
60
61 public enum ExtendedErrorCode : TErrorCode {
62 case unknown
63 case missingRequiredField(fieldName: String)
64 case unexpectedType(type: TType)
65 case mismatchedProtocol(expected: String, got: String)
66 public var thriftErrorCode: Int {
67 switch self {
68 case .unknown: return 1000
69 case .missingRequiredField: return 1001
70 case .unexpectedType: return 1002
71 case .mismatchedProtocol: return 1003
72 }
73 }
74 public var description: String {
75 switch self {
76 case .unknown: return "Unknown TProtocolExtendedError"
77 case .missingRequiredField(let fieldName): return "Missing Required Field: \(fieldName)"
78 case .unexpectedType(let type): return "Unexpected Type \(type.self)"
79 case .mismatchedProtocol(let expected, let got): return "Mismatched Protocol. (Expected: \(expected), got \(got))"
80 }
81 }
82 }
83
84 public var extendedError: ExtendedErrorCode? = nil
85
86 public init(error: Code = .unknown,
87 message: String? = nil,
88 extendedError: ExtendedErrorCode? = nil) {
89 self.error = error
90 self.message = message
91 self.extendedError = extendedError
92 }
93
94 /// Mark: TError
95 public var error: Code = .unknown
96 public var message: String? = nil
97 public static var defaultCase: Code { return .unknown }
98
99 public var description: String {
100 var out = "\(TProtocolError.self): (\(error.thriftErrorCode) \(error.description)\n"
101 if let extendedError = extendedError {
102 out += "TProtocolExtendedError (\(extendedError.thriftErrorCode)): \(extendedError.description)"
103 }
104 if let message = message {
105 out += "Message: \(message)"
106 }
107 return out
108 }
109}
110
111
112/// Wrapper for Transport errors in Protocols. Inspired by Thrift-Cocoa PROTOCOL_TRANSPORT_ERROR
113/// macro. Modified to be more Swift-y. Catches any TError thrown within the block and
114/// rethrows a given TProtocolError, the original error's description is appended to the new
115/// TProtocolError's message. sourceFile, sourceLine, sourceMethod are auto-populated and should
116/// be ignored when calling.
117///
118/// - parameter error: TProtocolError to throw if the block throws
119/// - parameter sourceFile: throwing file, autopopulated
120/// - parameter sourceLine: throwing line, autopopulated
121/// - parameter sourceMethod: throwing method, autopopulated
122/// - parameter block: throwing block
123///
124/// - throws: TProtocolError Default is TProtocolError.ErrorCode.unknown. Underlying
125/// error's description appended to TProtocolError.message
126func ProtocolTransportTry(error: TProtocolError = TProtocolError(),
127 sourceFile: String = #file,
128 sourceLine: Int = #line,
129 sourceMethod: String = #function,
130 block: () throws -> ()) throws {
131 // Need mutable copy
132 var error = error
133 do {
134 try block()
135 } catch let err as TError {
136 var message = error.message ?? ""
137 message += "\nFile: \(sourceFile)\n"
138 message += "Line: \(sourceLine)\n"
139 message += "Method: \(sourceMethod)"
140 message += "\nOriginal Error:\n" + err.description
141 error.message = message
142 throw error
143 }
144}
145
146