added iOS source code
[wl-app.git] / iOS / Pods / Alamofire / Source / AFError.swift
1 //
2 //  AFError.swift
3 //
4 //  Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
5 //
6 //  Permission is hereby granted, free of charge, to any person obtaining a copy
7 //  of this software and associated documentation files (the "Software"), to deal
8 //  in the Software without restriction, including without limitation the rights
9 //  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 //  copies of the Software, and to permit persons to whom the Software is
11 //  furnished to do so, subject to the following conditions:
12 //
13 //  The above copyright notice and this permission notice shall be included in
14 //  all copies or substantial portions of the Software.
15 //
16 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 //  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 //  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 //  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 //  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 //  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 //  THE SOFTWARE.
23 //
24
25 import Foundation
26
27 /// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
28 /// their own associated reasons.
29 ///
30 /// - invalidURL:                  Returned when a `URLConvertible` type fails to create a valid `URL`.
31 /// - parameterEncodingFailed:     Returned when a parameter encoding object throws an error during the encoding process.
32 /// - multipartEncodingFailed:     Returned when some step in the multipart encoding process fails.
33 /// - responseValidationFailed:    Returned when a `validate()` call fails.
34 /// - responseSerializationFailed: Returned when a response serializer encounters an error in the serialization process.
35 public enum AFError: Error {
36     /// The underlying reason the parameter encoding error occurred.
37     ///
38     /// - missingURL:                 The URL request did not have a URL to encode.
39     /// - jsonEncodingFailed:         JSON serialization failed with an underlying system error during the
40     ///                               encoding process.
41     /// - propertyListEncodingFailed: Property list serialization failed with an underlying system error during
42     ///                               encoding process.
43     public enum ParameterEncodingFailureReason {
44         case missingURL
45         case jsonEncodingFailed(error: Error)
46         case propertyListEncodingFailed(error: Error)
47     }
48
49     /// The underlying reason the multipart encoding error occurred.
50     ///
51     /// - bodyPartURLInvalid:                   The `fileURL` provided for reading an encodable body part isn't a
52     ///                                         file URL.
53     /// - bodyPartFilenameInvalid:              The filename of the `fileURL` provided has either an empty
54     ///                                         `lastPathComponent` or `pathExtension.
55     /// - bodyPartFileNotReachable:             The file at the `fileURL` provided was not reachable.
56     /// - bodyPartFileNotReachableWithError:    Attempting to check the reachability of the `fileURL` provided threw
57     ///                                         an error.
58     /// - bodyPartFileIsDirectory:              The file at the `fileURL` provided is actually a directory.
59     /// - bodyPartFileSizeNotAvailable:         The size of the file at the `fileURL` provided was not returned by
60     ///                                         the system.
61     /// - bodyPartFileSizeQueryFailedWithError: The attempt to find the size of the file at the `fileURL` provided
62     ///                                         threw an error.
63     /// - bodyPartInputStreamCreationFailed:    An `InputStream` could not be created for the provided `fileURL`.
64     /// - outputStreamCreationFailed:           An `OutputStream` could not be created when attempting to write the
65     ///                                         encoded data to disk.
66     /// - outputStreamFileAlreadyExists:        The encoded body data could not be writtent disk because a file
67     ///                                         already exists at the provided `fileURL`.
68     /// - outputStreamURLInvalid:               The `fileURL` provided for writing the encoded body data to disk is
69     ///                                         not a file URL.
70     /// - outputStreamWriteFailed:              The attempt to write the encoded body data to disk failed with an
71     ///                                         underlying error.
72     /// - inputStreamReadFailed:                The attempt to read an encoded body part `InputStream` failed with
73     ///                                         underlying system error.
74     public enum MultipartEncodingFailureReason {
75         case bodyPartURLInvalid(url: URL)
76         case bodyPartFilenameInvalid(in: URL)
77         case bodyPartFileNotReachable(at: URL)
78         case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
79         case bodyPartFileIsDirectory(at: URL)
80         case bodyPartFileSizeNotAvailable(at: URL)
81         case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
82         case bodyPartInputStreamCreationFailed(for: URL)
83
84         case outputStreamCreationFailed(for: URL)
85         case outputStreamFileAlreadyExists(at: URL)
86         case outputStreamURLInvalid(url: URL)
87         case outputStreamWriteFailed(error: Error)
88
89         case inputStreamReadFailed(error: Error)
90     }
91
92     /// The underlying reason the response validation error occurred.
93     ///
94     /// - dataFileNil:             The data file containing the server response did not exist.
95     /// - dataFileReadFailed:      The data file containing the server response could not be read.
96     /// - missingContentType:      The response did not contain a `Content-Type` and the `acceptableContentTypes`
97     ///                            provided did not contain wildcard type.
98     /// - unacceptableContentType: The response `Content-Type` did not match any type in the provided
99     ///                            `acceptableContentTypes`.
100     /// - unacceptableStatusCode:  The response status code was not acceptable.
101     public enum ResponseValidationFailureReason {
102         case dataFileNil
103         case dataFileReadFailed(at: URL)
104         case missingContentType(acceptableContentTypes: [String])
105         case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
106         case unacceptableStatusCode(code: Int)
107     }
108
109     /// The underlying reason the response serialization error occurred.
110     ///
111     /// - inputDataNil:                    The server response contained no data.
112     /// - inputDataNilOrZeroLength:        The server response contained no data or the data was zero length.
113     /// - inputFileNil:                    The file containing the server response did not exist.
114     /// - inputFileReadFailed:             The file containing the server response could not be read.
115     /// - stringSerializationFailed:       String serialization failed using the provided `String.Encoding`.
116     /// - jsonSerializationFailed:         JSON serialization failed with an underlying system error.
117     /// - propertyListSerializationFailed: Property list serialization failed with an underlying system error.
118     public enum ResponseSerializationFailureReason {
119         case inputDataNil
120         case inputDataNilOrZeroLength
121         case inputFileNil
122         case inputFileReadFailed(at: URL)
123         case stringSerializationFailed(encoding: String.Encoding)
124         case jsonSerializationFailed(error: Error)
125         case propertyListSerializationFailed(error: Error)
126     }
127
128     case invalidURL(url: URLConvertible)
129     case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
130     case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
131     case responseValidationFailed(reason: ResponseValidationFailureReason)
132     case responseSerializationFailed(reason: ResponseSerializationFailureReason)
133 }
134
135 // MARK: - Adapt Error
136
137 struct AdaptError: Error {
138     let error: Error
139 }
140
141 extension Error {
142     var underlyingAdaptError: Error? { return (self as? AdaptError)?.error }
143 }
144
145 // MARK: - Error Booleans
146
147 extension AFError {
148     /// Returns whether the AFError is an invalid URL error.
149     public var isInvalidURLError: Bool {
150         if case .invalidURL = self { return true }
151         return false
152     }
153
154     /// Returns whether the AFError is a parameter encoding error. When `true`, the `underlyingError` property will
155     /// contain the associated value.
156     public var isParameterEncodingError: Bool {
157         if case .parameterEncodingFailed = self { return true }
158         return false
159     }
160
161     /// Returns whether the AFError is a multipart encoding error. When `true`, the `url` and `underlyingError` properties
162     /// will contain the associated values.
163     public var isMultipartEncodingError: Bool {
164         if case .multipartEncodingFailed = self { return true }
165         return false
166     }
167
168     /// Returns whether the `AFError` is a response validation error. When `true`, the `acceptableContentTypes`,
169     /// `responseContentType`, and `responseCode` properties will contain the associated values.
170     public var isResponseValidationError: Bool {
171         if case .responseValidationFailed = self { return true }
172         return false
173     }
174
175     /// Returns whether the `AFError` is a response serialization error. When `true`, the `failedStringEncoding` and
176     /// `underlyingError` properties will contain the associated values.
177     public var isResponseSerializationError: Bool {
178         if case .responseSerializationFailed = self { return true }
179         return false
180     }
181 }
182
183 // MARK: - Convenience Properties
184
185 extension AFError {
186     /// The `URLConvertible` associated with the error.
187     public var urlConvertible: URLConvertible? {
188         switch self {
189         case .invalidURL(let url):
190             return url
191         default:
192             return nil
193         }
194     }
195
196     /// The `URL` associated with the error.
197     public var url: URL? {
198         switch self {
199         case .multipartEncodingFailed(let reason):
200             return reason.url
201         default:
202             return nil
203         }
204     }
205
206     /// The `Error` returned by a system framework associated with a `.parameterEncodingFailed`,
207     /// `.multipartEncodingFailed` or `.responseSerializationFailed` error.
208     public var underlyingError: Error? {
209         switch self {
210         case .parameterEncodingFailed(let reason):
211             return reason.underlyingError
212         case .multipartEncodingFailed(let reason):
213             return reason.underlyingError
214         case .responseSerializationFailed(let reason):
215             return reason.underlyingError
216         default:
217             return nil
218         }
219     }
220
221     /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
222     public var acceptableContentTypes: [String]? {
223         switch self {
224         case .responseValidationFailed(let reason):
225             return reason.acceptableContentTypes
226         default:
227             return nil
228         }
229     }
230
231     /// The response `Content-Type` of a `.responseValidationFailed` error.
232     public var responseContentType: String? {
233         switch self {
234         case .responseValidationFailed(let reason):
235             return reason.responseContentType
236         default:
237             return nil
238         }
239     }
240
241     /// The response code of a `.responseValidationFailed` error.
242     public var responseCode: Int? {
243         switch self {
244         case .responseValidationFailed(let reason):
245             return reason.responseCode
246         default:
247             return nil
248         }
249     }
250
251     /// The `String.Encoding` associated with a failed `.stringResponse()` call.
252     public var failedStringEncoding: String.Encoding? {
253         switch self {
254         case .responseSerializationFailed(let reason):
255             return reason.failedStringEncoding
256         default:
257             return nil
258         }
259     }
260 }
261
262 extension AFError.ParameterEncodingFailureReason {
263     var underlyingError: Error? {
264         switch self {
265         case .jsonEncodingFailed(let error), .propertyListEncodingFailed(let error):
266             return error
267         default:
268             return nil
269         }
270     }
271 }
272
273 extension AFError.MultipartEncodingFailureReason {
274     var url: URL? {
275         switch self {
276         case .bodyPartURLInvalid(let url), .bodyPartFilenameInvalid(let url), .bodyPartFileNotReachable(let url),
277              .bodyPartFileIsDirectory(let url), .bodyPartFileSizeNotAvailable(let url),
278              .bodyPartInputStreamCreationFailed(let url), .outputStreamCreationFailed(let url),
279              .outputStreamFileAlreadyExists(let url), .outputStreamURLInvalid(let url),
280              .bodyPartFileNotReachableWithError(let url, _), .bodyPartFileSizeQueryFailedWithError(let url, _):
281             return url
282         default:
283             return nil
284         }
285     }
286
287     var underlyingError: Error? {
288         switch self {
289         case .bodyPartFileNotReachableWithError(_, let error), .bodyPartFileSizeQueryFailedWithError(_, let error),
290              .outputStreamWriteFailed(let error), .inputStreamReadFailed(let error):
291             return error
292         default:
293             return nil
294         }
295     }
296 }
297
298 extension AFError.ResponseValidationFailureReason {
299     var acceptableContentTypes: [String]? {
300         switch self {
301         case .missingContentType(let types), .unacceptableContentType(let types, _):
302             return types
303         default:
304             return nil
305         }
306     }
307
308     var responseContentType: String? {
309         switch self {
310         case .unacceptableContentType(_, let responseType):
311             return responseType
312         default:
313             return nil
314         }
315     }
316
317     var responseCode: Int? {
318         switch self {
319         case .unacceptableStatusCode(let code):
320             return code
321         default:
322             return nil
323         }
324     }
325 }
326
327 extension AFError.ResponseSerializationFailureReason {
328     var failedStringEncoding: String.Encoding? {
329         switch self {
330         case .stringSerializationFailed(let encoding):
331             return encoding
332         default:
333             return nil
334         }
335     }
336
337     var underlyingError: Error? {
338         switch self {
339         case .jsonSerializationFailed(let error), .propertyListSerializationFailed(let error):
340             return error
341         default:
342             return nil
343         }
344     }
345 }
346
347 // MARK: - Error Descriptions
348
349 extension AFError: LocalizedError {
350     public var errorDescription: String? {
351         switch self {
352         case .invalidURL(let url):
353             return "URL is not valid: \(url)"
354         case .parameterEncodingFailed(let reason):
355             return reason.localizedDescription
356         case .multipartEncodingFailed(let reason):
357             return reason.localizedDescription
358         case .responseValidationFailed(let reason):
359             return reason.localizedDescription
360         case .responseSerializationFailed(let reason):
361             return reason.localizedDescription
362         }
363     }
364 }
365
366 extension AFError.ParameterEncodingFailureReason {
367     var localizedDescription: String {
368         switch self {
369         case .missingURL:
370             return "URL request to encode was missing a URL"
371         case .jsonEncodingFailed(let error):
372             return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
373         case .propertyListEncodingFailed(let error):
374             return "PropertyList could not be encoded because of error:\n\(error.localizedDescription)"
375         }
376     }
377 }
378
379 extension AFError.MultipartEncodingFailureReason {
380     var localizedDescription: String {
381         switch self {
382         case .bodyPartURLInvalid(let url):
383             return "The URL provided is not a file URL: \(url)"
384         case .bodyPartFilenameInvalid(let url):
385             return "The URL provided does not have a valid filename: \(url)"
386         case .bodyPartFileNotReachable(let url):
387             return "The URL provided is not reachable: \(url)"
388         case .bodyPartFileNotReachableWithError(let url, let error):
389             return (
390                 "The system returned an error while checking the provided URL for " +
391                 "reachability.\nURL: \(url)\nError: \(error)"
392             )
393         case .bodyPartFileIsDirectory(let url):
394             return "The URL provided is a directory: \(url)"
395         case .bodyPartFileSizeNotAvailable(let url):
396             return "Could not fetch the file size from the provided URL: \(url)"
397         case .bodyPartFileSizeQueryFailedWithError(let url, let error):
398             return (
399                 "The system returned an error while attempting to fetch the file size from the " +
400                 "provided URL.\nURL: \(url)\nError: \(error)"
401             )
402         case .bodyPartInputStreamCreationFailed(let url):
403             return "Failed to create an InputStream for the provided URL: \(url)"
404         case .outputStreamCreationFailed(let url):
405             return "Failed to create an OutputStream for URL: \(url)"
406         case .outputStreamFileAlreadyExists(let url):
407             return "A file already exists at the provided URL: \(url)"
408         case .outputStreamURLInvalid(let url):
409             return "The provided OutputStream URL is invalid: \(url)"
410         case .outputStreamWriteFailed(let error):
411             return "OutputStream write failed with error: \(error)"
412         case .inputStreamReadFailed(let error):
413             return "InputStream read failed with error: \(error)"
414         }
415     }
416 }
417
418 extension AFError.ResponseSerializationFailureReason {
419     var localizedDescription: String {
420         switch self {
421         case .inputDataNil:
422             return "Response could not be serialized, input data was nil."
423         case .inputDataNilOrZeroLength:
424             return "Response could not be serialized, input data was nil or zero length."
425         case .inputFileNil:
426             return "Response could not be serialized, input file was nil."
427         case .inputFileReadFailed(let url):
428             return "Response could not be serialized, input file could not be read: \(url)."
429         case .stringSerializationFailed(let encoding):
430             return "String could not be serialized with encoding: \(encoding)."
431         case .jsonSerializationFailed(let error):
432             return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
433         case .propertyListSerializationFailed(let error):
434             return "PropertyList could not be serialized because of error:\n\(error.localizedDescription)"
435         }
436     }
437 }
438
439 extension AFError.ResponseValidationFailureReason {
440     var localizedDescription: String {
441         switch self {
442         case .dataFileNil:
443             return "Response could not be validated, data file was nil."
444         case .dataFileReadFailed(let url):
445             return "Response could not be validated, data file could not be read: \(url)."
446         case .missingContentType(let types):
447             return (
448                 "Response Content-Type was missing and acceptable content types " +
449                 "(\(types.joined(separator: ","))) do not match \"*/*\"."
450             )
451         case .unacceptableContentType(let acceptableTypes, let responseType):
452             return (
453                 "Response Content-Type \"\(responseType)\" does not match any acceptable types: " +
454                 "\(acceptableTypes.joined(separator: ","))."
455             )
456         case .unacceptableStatusCode(let code):
457             return "Response status code was unacceptable: \(code)."
458         }
459     }
460 }