@@ -101,16 +101,16 @@ public let FunctionsErrorDetailsKey: String = "details"
101
101
case unauthenticated = 16
102
102
}
103
103
104
- extension FunctionsErrorCode {
104
+ private extension FunctionsErrorCode {
105
105
/// Takes an HTTP status code and returns the corresponding `FIRFunctionsErrorCode` error code.
106
106
///
107
107
/// + This is the standard HTTP status code -> error mapping defined in:
108
108
/// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
109
109
///
110
- /// - Parameter status : An HTTP status code.
110
+ /// - Parameter httpStatusCode : An HTTP status code.
111
111
/// - Returns: A `FunctionsErrorCode`. Falls back to `internal` for unknown status codes.
112
- static func errorCode ( forHTTPStatus status : Int ) -> Self {
113
- switch status {
112
+ init ( httpStatusCode : Int ) {
113
+ self = switch httpStatusCode {
114
114
case 200 : . OK
115
115
case 400 : . invalidArgument
116
116
case 401 : . unauthenticated
@@ -127,102 +127,86 @@ extension FunctionsErrorCode {
127
127
}
128
128
}
129
129
130
- static func errorCode ( forName name : String ) -> FunctionsErrorCode {
131
- switch name {
132
- case " OK " : return . OK
133
- case " CANCELLED " : return . cancelled
134
- case " UNKNOWN " : return . unknown
135
- case " INVALID_ARGUMENT " : return . invalidArgument
136
- case " DEADLINE_EXCEEDED " : return . deadlineExceeded
137
- case " NOT_FOUND " : return . notFound
138
- case " ALREADY_EXISTS " : return . alreadyExists
139
- case " PERMISSION_DENIED " : return . permissionDenied
140
- case " RESOURCE_EXHAUSTED " : return . resourceExhausted
141
- case " FAILED_PRECONDITION " : return . failedPrecondition
142
- case " ABORTED " : return . aborted
143
- case " OUT_OF_RANGE " : return . outOfRange
144
- case " UNIMPLEMENTED " : return . unimplemented
145
- case " INTERNAL " : return . internal
146
- case " UNAVAILABLE " : return . unavailable
147
- case " DATA_LOSS " : return . dataLoss
148
- case " UNAUTHENTICATED " : return . unauthenticated
149
- default : return . internal
130
+ init ( errorName : String ) {
131
+ self = switch errorName {
132
+ case " OK " : . OK
133
+ case " CANCELLED " : . cancelled
134
+ case " UNKNOWN " : . unknown
135
+ case " INVALID_ARGUMENT " : . invalidArgument
136
+ case " DEADLINE_EXCEEDED " : . deadlineExceeded
137
+ case " NOT_FOUND " : . notFound
138
+ case " ALREADY_EXISTS " : . alreadyExists
139
+ case " PERMISSION_DENIED " : . permissionDenied
140
+ case " RESOURCE_EXHAUSTED " : . resourceExhausted
141
+ case " FAILED_PRECONDITION " : . failedPrecondition
142
+ case " ABORTED " : . aborted
143
+ case " OUT_OF_RANGE " : . outOfRange
144
+ case " UNIMPLEMENTED " : . unimplemented
145
+ case " INTERNAL " : . internal
146
+ case " UNAVAILABLE " : . unavailable
147
+ case " DATA_LOSS " : . dataLoss
148
+ case " UNAUTHENTICATED " : . unauthenticated
149
+ default : . internal
150
150
}
151
151
}
152
+ }
152
153
153
- var descriptionForErrorCode : String {
154
- switch self {
155
- case . OK:
156
- return " OK "
157
- case . cancelled:
158
- return " CANCELLED "
159
- case . unknown:
160
- return " UNKNOWN "
161
- case . invalidArgument:
162
- return " INVALID ARGUMENT "
163
- case . deadlineExceeded:
164
- return " DEADLINE EXCEEDED "
165
- case . notFound:
166
- return " NOT FOUND "
167
- case . alreadyExists:
168
- return " ALREADY EXISTS "
169
- case . permissionDenied:
170
- return " PERMISSION DENIED "
171
- case . resourceExhausted:
172
- return " RESOURCE EXHAUSTED "
173
- case . failedPrecondition:
174
- return " FAILED PRECONDITION "
175
- case . aborted:
176
- return " ABORTED "
177
- case . outOfRange:
178
- return " OUT OF RANGE "
179
- case . unimplemented:
180
- return " UNIMPLEMENTED "
181
- case . internal:
182
- return " INTERNAL "
183
- case . unavailable:
184
- return " UNAVAILABLE "
185
- case . dataLoss:
186
- return " DATA LOSS "
187
- case . unauthenticated:
188
- return " UNAUTHENTICATED "
189
- }
190
- }
154
+ /// The object used to report errors that occur during a function’s execution.
155
+ struct FunctionsError : CustomNSError {
156
+ static let errorDomain = FunctionsErrorDomain
157
+
158
+ let code : FunctionsErrorCode
159
+ let errorUserInfo : [ String : Any ]
160
+ var errorCode : FunctionsErrorCode . RawValue { code. rawValue }
191
161
192
- func generatedError( userInfo: [ String : Any ] ? = nil ) -> NSError {
193
- return NSError ( domain: FunctionsErrorDomain,
194
- code: rawValue,
195
- userInfo: userInfo ?? [ NSLocalizedDescriptionKey: descriptionForErrorCode] )
162
+ init ( _ code: FunctionsErrorCode , userInfo: [ String : Any ] ? = nil ) {
163
+ self . code = code
164
+ errorUserInfo = userInfo ?? [ NSLocalizedDescriptionKey: Self . errorDescription ( from: code) ]
196
165
}
197
166
198
- static func errorForResponse( status: Int ,
199
- body: Data ? ,
200
- serializer: FunctionsSerializer ) -> NSError ? {
167
+ /// Initializes a `FunctionsError` from the HTTP status code and response body.
168
+ ///
169
+ /// - Parameters:
170
+ /// - httpStatusCode: The HTTP status code reported during a function’s execution. Only a subset
171
+ /// of codes are supported.
172
+ /// - body: The optional response data which may contain information about the error. The
173
+ /// following schema is expected:
174
+ /// ```
175
+ /// {
176
+ /// "error": {
177
+ /// "status": "PERMISSION_DENIED",
178
+ /// "message": "You are not allowed to perform this operation",
179
+ /// "details": 123 // Any value supported by `FunctionsSerializer`
180
+ /// }
181
+ /// ```
182
+ /// - serializer: The `FunctionsSerializer` used to decode `details` in the error body.
183
+ init ? ( httpStatusCode: Int , body: Data ? , serializer: FunctionsSerializer ) {
201
184
// Start with reasonable defaults from the status code.
202
- var code = FunctionsErrorCode . errorCode ( forHTTPStatus : status )
203
- var description = code . descriptionForErrorCode
204
- var details : AnyObject ?
185
+ var code = FunctionsErrorCode ( httpStatusCode : httpStatusCode )
186
+ var description = Self . errorDescription ( from : code )
187
+ var details : Any ?
205
188
206
189
// Then look through the body for explicit details.
207
190
if let body,
208
- let json = try ? JSONSerialization . jsonObject ( with: body) as? NSDictionary ,
209
- let errorDetails = json [ " error " ] as? NSDictionary {
191
+ let json = try ? JSONSerialization . jsonObject ( with: body) as? [ String : Any ] ,
192
+ let errorDetails = json [ " error " ] as? [ String : Any ] {
210
193
if let status = errorDetails [ " status " ] as? String {
211
- code = . errorCode ( forName : status)
194
+ code = FunctionsErrorCode ( errorName : status)
212
195
213
196
// If the code in the body is invalid, treat the whole response as malformed.
214
197
guard code != . internal else {
215
- return code. generatedError ( userInfo: nil )
198
+ self . init ( code)
199
+ return
216
200
}
217
201
}
218
202
219
203
if let message = errorDetails [ " message " ] as? String {
220
204
description = message
221
205
} else {
222
- description = code . descriptionForErrorCode
206
+ description = Self . errorDescription ( from : code )
223
207
}
224
208
225
- details = errorDetails [ " details " ] as AnyObject ?
209
+ details = errorDetails [ " details " ] as Any ?
226
210
// Update `details` only if decoding succeeds;
227
211
// otherwise, keep the original object.
228
212
if let innerDetails = details,
@@ -243,6 +227,28 @@ extension FunctionsErrorCode {
243
227
if let details {
244
228
userInfo [ FunctionsErrorDetailsKey] = details
245
229
}
246
- return code. generatedError ( userInfo: userInfo)
230
+ self . init ( code, userInfo: userInfo)
231
+ }
232
+
233
+ private static func errorDescription( from code: FunctionsErrorCode ) -> String {
234
+ switch code {
235
+ case . OK: " OK "
236
+ case . cancelled: " CANCELLED "
237
+ case . unknown: " UNKNOWN "
238
+ case . invalidArgument: " INVALID ARGUMENT "
239
+ case . deadlineExceeded: " DEADLINE EXCEEDED "
240
+ case . notFound: " NOT FOUND "
241
+ case . alreadyExists: " ALREADY EXISTS "
242
+ case . permissionDenied: " PERMISSION DENIED "
243
+ case . resourceExhausted: " RESOURCE EXHAUSTED "
244
+ case . failedPrecondition: " FAILED PRECONDITION "
245
+ case . aborted: " ABORTED "
246
+ case . outOfRange: " OUT OF RANGE "
247
+ case . unimplemented: " UNIMPLEMENTED "
248
+ case . internal: " INTERNAL "
249
+ case . unavailable: " UNAVAILABLE "
250
+ case . dataLoss: " DATA LOSS "
251
+ case . unauthenticated: " UNAUTHENTICATED "
252
+ }
247
253
}
248
254
}
0 commit comments