Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
//
2
//  Combine.swift
3
//
4
//  Copyright (c) 2020 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
#if !((os(iOS) && (arch(i386) || arch(arm))) || os(Windows) || os(Linux))
26
 
27
import Combine
28
import Dispatch
29
import Foundation
30
 
31
// MARK: - DataRequest / UploadRequest
32
 
33
/// A Combine `Publisher` that publishes the `DataResponse<Value, AFError>` of the provided `DataRequest`.
34
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
35
public struct DataResponsePublisher<Value>: Publisher {
36
    public typealias Output = DataResponse<Value, AFError>
37
    public typealias Failure = Never
38
 
39
    private typealias Handler = (@escaping (_ response: DataResponse<Value, AFError>) -> Void) -> DataRequest
40
 
41
    private let request: DataRequest
42
    private let responseHandler: Handler
43
 
44
    /// Creates an instance which will serialize responses using the provided `ResponseSerializer`.
45
    ///
46
    /// - Parameters:
47
    ///   - request:    `DataRequest` for which to publish the response.
48
    ///   - queue:      `DispatchQueue` on which the `DataResponse` value will be published. `.main` by default.
49
    ///   - serializer: `ResponseSerializer` used to produce the published `DataResponse`.
50
    public init<Serializer: ResponseSerializer>(_ request: DataRequest, queue: DispatchQueue, serializer: Serializer)
51
        where Value == Serializer.SerializedObject {
52
        self.request = request
53
        responseHandler = { request.response(queue: queue, responseSerializer: serializer, completionHandler: $0) }
54
    }
55
 
56
    /// Creates an instance which will serialize responses using the provided `DataResponseSerializerProtocol`.
57
    ///
58
    /// - Parameters:
59
    ///   - request:    `DataRequest` for which to publish the response.
60
    ///   - queue:      `DispatchQueue` on which the `DataResponse` value will be published. `.main` by default.
61
    ///   - serializer: `DataResponseSerializerProtocol` used to produce the published `DataResponse`.
62
    public init<Serializer: DataResponseSerializerProtocol>(_ request: DataRequest,
63
                                                            queue: DispatchQueue,
64
                                                            serializer: Serializer)
65
        where Value == Serializer.SerializedObject {
66
        self.request = request
67
        responseHandler = { request.response(queue: queue, responseSerializer: serializer, completionHandler: $0) }
68
    }
69
 
70
    /// Publishes only the `Result` of the `DataResponse` value.
71
    ///
72
    /// - Returns: The `AnyPublisher` publishing the `Result<Value, AFError>` value.
73
    public func result() -> AnyPublisher<Result<Value, AFError>, Never> {
74
        map(\.result).eraseToAnyPublisher()
75
    }
76
 
77
    /// Publishes the `Result` of the `DataResponse` as a single `Value` or fail with the `AFError` instance.
78
    ///
79
    /// - Returns: The `AnyPublisher<Value, AFError>` publishing the stream.
80
    public func value() -> AnyPublisher<Value, AFError> {
81
        setFailureType(to: AFError.self).flatMap(\.result.publisher).eraseToAnyPublisher()
82
    }
83
 
84
    public func receive<S>(subscriber: S) where S: Subscriber, DataResponsePublisher.Failure == S.Failure, DataResponsePublisher.Output == S.Input {
85
        subscriber.receive(subscription: Inner(request: request,
86
                                               responseHandler: responseHandler,
87
                                               downstream: subscriber))
88
    }
89
 
90
    private final class Inner<Downstream: Subscriber>: Subscription, Cancellable
91
        where Downstream.Input == Output {
92
        typealias Failure = Downstream.Failure
93
 
94
        @Protected
95
        private var downstream: Downstream?
96
        private let request: DataRequest
97
        private let responseHandler: Handler
98
 
99
        init(request: DataRequest, responseHandler: @escaping Handler, downstream: Downstream) {
100
            self.request = request
101
            self.responseHandler = responseHandler
102
            self.downstream = downstream
103
        }
104
 
105
        func request(_ demand: Subscribers.Demand) {
106
            assert(demand > 0)
107
 
108
            guard let downstream = downstream else { return }
109
 
110
            self.downstream = nil
111
            responseHandler { response in
112
                _ = downstream.receive(response)
113
                downstream.receive(completion: .finished)
114
            }.resume()
115
        }
116
 
117
        func cancel() {
118
            request.cancel()
119
            downstream = nil
120
        }
121
    }
122
}
123
 
124
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
125
extension DataResponsePublisher where Value == Data? {
126
    /// Creates an instance which publishes a `DataResponse<Data?, AFError>` value without serialization.
127
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
128
    public init(_ request: DataRequest, queue: DispatchQueue) {
129
        self.request = request
130
        responseHandler = { request.response(queue: queue, completionHandler: $0) }
131
    }
132
}
133
 
134
extension DataRequest {
135
    /// Creates a `DataResponsePublisher` for this instance using the given `ResponseSerializer` and `DispatchQueue`.
136
    ///
137
    /// - Parameters:
138
    ///   - serializer: `ResponseSerializer` used to serialize response `Data`.
139
    ///   - queue:      `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
140
    ///
141
    /// - Returns:      The `DataResponsePublisher`.
142
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
143
    public func publishResponse<Serializer: ResponseSerializer, T>(using serializer: Serializer, on queue: DispatchQueue = .main) -> DataResponsePublisher<T>
144
        where Serializer.SerializedObject == T {
145
        DataResponsePublisher(self, queue: queue, serializer: serializer)
146
    }
147
 
148
    /// Creates a `DataResponsePublisher` for this instance and uses a `DataResponseSerializer` to serialize the
149
    /// response.
150
    ///
151
    /// - Parameters:
152
    ///   - queue:               `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
153
    ///   - preprocessor:        `DataPreprocessor` which filters the `Data` before serialization. `PassthroughPreprocessor()`
154
    ///                          by default.
155
    ///   - emptyResponseCodes:  `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
156
    ///                          default.
157
    ///   - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
158
    ///                          status code. `[.head]` by default.
159
    /// - Returns:               The `DataResponsePublisher`.
160
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
161
    public func publishData(queue: DispatchQueue = .main,
162
                            preprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
163
                            emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
164
                            emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DataResponsePublisher<Data> {
165
        publishResponse(using: DataResponseSerializer(dataPreprocessor: preprocessor,
166
                                                      emptyResponseCodes: emptyResponseCodes,
167
                                                      emptyRequestMethods: emptyRequestMethods),
168
                        on: queue)
169
    }
170
 
171
    /// Creates a `DataResponsePublisher` for this instance and uses a `StringResponseSerializer` to serialize the
172
    /// response.
173
    ///
174
    /// - Parameters:
175
    ///   - queue:               `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
176
    ///   - preprocessor:        `DataPreprocessor` which filters the `Data` before serialization. `PassthroughPreprocessor()`
177
    ///                          by default.
178
    ///   - encoding:            `String.Encoding` to parse the response. `nil` by default, in which case the encoding
179
    ///                          will be determined by the server response, falling back to the default HTTP character
180
    ///                          set, `ISO-8859-1`.
181
    ///   - emptyResponseCodes:  `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
182
    ///                          default.
183
    ///   - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
184
    ///                          status code. `[.head]` by default.
185
    ///
186
    /// - Returns:               The `DataResponsePublisher`.
187
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
188
    public func publishString(queue: DispatchQueue = .main,
189
                              preprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
190
                              encoding: String.Encoding? = nil,
191
                              emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
192
                              emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> DataResponsePublisher<String> {
193
        publishResponse(using: StringResponseSerializer(dataPreprocessor: preprocessor,
194
                                                        encoding: encoding,
195
                                                        emptyResponseCodes: emptyResponseCodes,
196
                                                        emptyRequestMethods: emptyRequestMethods),
197
                        on: queue)
198
    }
199
 
200
    @_disfavoredOverload
201
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
202
    @available(*, deprecated, message: "Renamed publishDecodable(type:queue:preprocessor:decoder:emptyResponseCodes:emptyRequestMethods).")
203
    public func publishDecodable<T: Decodable>(type: T.Type = T.self,
204
                                               queue: DispatchQueue = .main,
205
                                               preprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
206
                                               decoder: DataDecoder = JSONDecoder(),
207
                                               emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
208
                                               emptyResponseMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DataResponsePublisher<T> {
209
        publishResponse(using: DecodableResponseSerializer(dataPreprocessor: preprocessor,
210
                                                           decoder: decoder,
211
                                                           emptyResponseCodes: emptyResponseCodes,
212
                                                           emptyRequestMethods: emptyResponseMethods),
213
                        on: queue)
214
    }
215
 
216
    /// Creates a `DataResponsePublisher` for this instance and uses a `DecodableResponseSerializer` to serialize the
217
    /// response.
218
    ///
219
    /// - Parameters:
220
    ///   - type:                `Decodable` type to which to decode response `Data`. Inferred from the context by
221
    ///                          default.
222
    ///   - queue:               `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
223
    ///   - preprocessor:        `DataPreprocessor` which filters the `Data` before serialization.
224
    ///                          `PassthroughPreprocessor()` by default.
225
    ///   - decoder:             `DataDecoder` instance used to decode response `Data`. `JSONDecoder()` by default.
226
    ///   - emptyResponseCodes:  `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
227
    ///                          default.
228
    ///   - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
229
    ///                          status code. `[.head]` by default.
230
    ///
231
    /// - Returns:               The `DataResponsePublisher`.
232
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
233
    public func publishDecodable<T: Decodable>(type: T.Type = T.self,
234
                                               queue: DispatchQueue = .main,
235
                                               preprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
236
                                               decoder: DataDecoder = JSONDecoder(),
237
                                               emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
238
                                               emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DataResponsePublisher<T> {
239
        publishResponse(using: DecodableResponseSerializer(dataPreprocessor: preprocessor,
240
                                                           decoder: decoder,
241
                                                           emptyResponseCodes: emptyResponseCodes,
242
                                                           emptyRequestMethods: emptyRequestMethods),
243
                        on: queue)
244
    }
245
 
246
    /// Creates a `DataResponsePublisher` for this instance which does not serialize the response before publishing.
247
    ///
248
    ///   - queue: `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
249
    ///
250
    /// - Returns: The `DataResponsePublisher`.
251
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
252
    public func publishUnserialized(queue: DispatchQueue = .main) -> DataResponsePublisher<Data?> {
253
        DataResponsePublisher(self, queue: queue)
254
    }
255
}
256
 
257
// A Combine `Publisher` that publishes a sequence of `Stream<Value, AFError>` values received by the provided `DataStreamRequest`.
258
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
259
public struct DataStreamPublisher<Value>: Publisher {
260
    public typealias Output = DataStreamRequest.Stream<Value, AFError>
261
    public typealias Failure = Never
262
 
263
    private typealias Handler = (@escaping DataStreamRequest.Handler<Value, AFError>) -> DataStreamRequest
264
 
265
    private let request: DataStreamRequest
266
    private let streamHandler: Handler
267
 
268
    /// Creates an instance which will serialize responses using the provided `DataStreamSerializer`.
269
    ///
270
    /// - Parameters:
271
    ///   - request:    `DataStreamRequest` for which to publish the response.
272
    ///   - queue:      `DispatchQueue` on which the `Stream<Value, AFError>` values will be published. `.main` by
273
    ///                 default.
274
    ///   - serializer: `DataStreamSerializer` used to produce the published `Stream<Value, AFError>` values.
275
    public init<Serializer: DataStreamSerializer>(_ request: DataStreamRequest, queue: DispatchQueue, serializer: Serializer)
276
        where Value == Serializer.SerializedObject {
277
        self.request = request
278
        streamHandler = { request.responseStream(using: serializer, on: queue, stream: $0) }
279
    }
280
 
281
    /// Publishes only the `Result` of the `DataStreamRequest.Stream`'s `Event`s.
282
    ///
283
    /// - Returns: The `AnyPublisher` publishing the `Result<Value, AFError>` value.
284
    public func result() -> AnyPublisher<Result<Value, AFError>, Never> {
285
        compactMap { stream in
286
            switch stream.event {
287
            case let .stream(result):
288
                return result
289
            // If the stream has completed with an error, send the error value downstream as a `.failure`.
290
            case let .complete(completion):
291
                return completion.error.map(Result.failure)
292
            }
293
        }
294
        .eraseToAnyPublisher()
295
    }
296
 
297
    /// Publishes the streamed values of the `DataStreamRequest.Stream` as a sequence of `Value` or fail with the
298
    /// `AFError` instance.
299
    ///
300
    /// - Returns: The `AnyPublisher<Value, AFError>` publishing the stream.
301
    public func value() -> AnyPublisher<Value, AFError> {
302
        result().setFailureType(to: AFError.self).flatMap(\.publisher).eraseToAnyPublisher()
303
    }
304
 
305
    public func receive<S>(subscriber: S) where S: Subscriber, DataStreamPublisher.Failure == S.Failure, DataStreamPublisher.Output == S.Input {
306
        subscriber.receive(subscription: Inner(request: request,
307
                                               streamHandler: streamHandler,
308
                                               downstream: subscriber))
309
    }
310
 
311
    private final class Inner<Downstream: Subscriber>: Subscription, Cancellable
312
        where Downstream.Input == Output {
313
        typealias Failure = Downstream.Failure
314
 
315
        @Protected
316
        private var downstream: Downstream?
317
        private let request: DataStreamRequest
318
        private let streamHandler: Handler
319
 
320
        init(request: DataStreamRequest, streamHandler: @escaping Handler, downstream: Downstream) {
321
            self.request = request
322
            self.streamHandler = streamHandler
323
            self.downstream = downstream
324
        }
325
 
326
        func request(_ demand: Subscribers.Demand) {
327
            assert(demand > 0)
328
 
329
            guard let downstream = downstream else { return }
330
 
331
            self.downstream = nil
332
            streamHandler { stream in
333
                _ = downstream.receive(stream)
334
                if case .complete = stream.event {
335
                    downstream.receive(completion: .finished)
336
                }
337
            }.resume()
338
        }
339
 
340
        func cancel() {
341
            request.cancel()
342
            downstream = nil
343
        }
344
    }
345
}
346
 
347
extension DataStreamRequest {
348
    /// Creates a `DataStreamPublisher` for this instance using the given `DataStreamSerializer` and `DispatchQueue`.
349
    ///
350
    /// - Parameters:
351
    ///   - serializer: `DataStreamSerializer` used to serialize the streamed `Data`.
352
    ///   - queue:      `DispatchQueue` on which the `DataRequest.Stream` values will be published. `.main` by default.
353
    /// - Returns:      The `DataStreamPublisher`.
354
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
355
    public func publishStream<Serializer: DataStreamSerializer>(using serializer: Serializer,
356
                                                                on queue: DispatchQueue = .main) -> DataStreamPublisher<Serializer.SerializedObject> {
357
        DataStreamPublisher(self, queue: queue, serializer: serializer)
358
    }
359
 
360
    /// Creates a `DataStreamPublisher` for this instance which uses a `PassthroughStreamSerializer` to stream `Data`
361
    /// unserialized.
362
    ///
363
    /// - Parameters:
364
    ///   - queue:      `DispatchQueue` on which the `DataRequest.Stream` values will be published. `.main` by default.
365
    /// - Returns:      The `DataStreamPublisher`.
366
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
367
    public func publishData(queue: DispatchQueue = .main) -> DataStreamPublisher<Data> {
368
        publishStream(using: PassthroughStreamSerializer(), on: queue)
369
    }
370
 
371
    /// Creates a `DataStreamPublisher` for this instance which uses a `StringStreamSerializer` to serialize stream
372
    /// `Data` values into `String` values.
373
    ///
374
    /// - Parameters:
375
    ///   - queue:      `DispatchQueue` on which the `DataRequest.Stream` values will be published. `.main` by default.
376
    /// - Returns:      The `DataStreamPublisher`.
377
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
378
    public func publishString(queue: DispatchQueue = .main) -> DataStreamPublisher<String> {
379
        publishStream(using: StringStreamSerializer(), on: queue)
380
    }
381
 
382
    /// Creates a `DataStreamPublisher` for this instance which uses a `DecodableStreamSerializer` with the provided
383
    /// parameters to serialize stream `Data` values into the provided type.
384
    ///
385
    /// - Parameters:
386
    ///   - type:         `Decodable` type to which to decode stream `Data`. Inferred from the context by default.
387
    ///   - queue:        `DispatchQueue` on which the `DataRequest.Stream` values will be published. `.main` by default.
388
    ///   - decoder:      `DataDecoder` instance used to decode stream `Data`. `JSONDecoder()` by default.
389
    ///   - preprocessor: `DataPreprocessor` which filters incoming stream `Data` before serialization.
390
    ///                   `PassthroughPreprocessor()` by default.
391
    /// - Returns:        The `DataStreamPublisher`.
392
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
393
    public func publishDecodable<T: Decodable>(type: T.Type = T.self,
394
                                               queue: DispatchQueue = .main,
395
                                               decoder: DataDecoder = JSONDecoder(),
396
                                               preprocessor: DataPreprocessor = PassthroughPreprocessor()) -> DataStreamPublisher<T> {
397
        publishStream(using: DecodableStreamSerializer(decoder: decoder,
398
                                                       dataPreprocessor: preprocessor),
399
                      on: queue)
400
    }
401
}
402
 
403
/// A Combine `Publisher` that publishes the `DownloadResponse<Value, AFError>` of the provided `DownloadRequest`.
404
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
405
public struct DownloadResponsePublisher<Value>: Publisher {
406
    public typealias Output = DownloadResponse<Value, AFError>
407
    public typealias Failure = Never
408
 
409
    private typealias Handler = (@escaping (_ response: DownloadResponse<Value, AFError>) -> Void) -> DownloadRequest
410
 
411
    private let request: DownloadRequest
412
    private let responseHandler: Handler
413
 
414
    /// Creates an instance which will serialize responses using the provided `ResponseSerializer`.
415
    ///
416
    /// - Parameters:
417
    ///   - request:    `DownloadRequest` for which to publish the response.
418
    ///   - queue:      `DispatchQueue` on which the `DownloadResponse` value will be published. `.main` by default.
419
    ///   - serializer: `ResponseSerializer` used to produce the published `DownloadResponse`.
420
    public init<Serializer: ResponseSerializer>(_ request: DownloadRequest, queue: DispatchQueue, serializer: Serializer)
421
        where Value == Serializer.SerializedObject {
422
        self.request = request
423
        responseHandler = { request.response(queue: queue, responseSerializer: serializer, completionHandler: $0) }
424
    }
425
 
426
    /// Creates an instance which will serialize responses using the provided `DownloadResponseSerializerProtocol` value.
427
    ///
428
    /// - Parameters:
429
    ///   - request:    `DownloadRequest` for which to publish the response.
430
    ///   - queue:      `DispatchQueue` on which the `DataResponse` value will be published. `.main` by default.
431
    ///   - serializer: `DownloadResponseSerializerProtocol` used to produce the published `DownloadResponse`.
432
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
433
    public init<Serializer: DownloadResponseSerializerProtocol>(_ request: DownloadRequest,
434
                                                                queue: DispatchQueue,
435
                                                                serializer: Serializer)
436
        where Value == Serializer.SerializedObject {
437
        self.request = request
438
        responseHandler = { request.response(queue: queue, responseSerializer: serializer, completionHandler: $0) }
439
    }
440
 
441
    /// Publishes only the `Result` of the `DownloadResponse` value.
442
    ///
443
    /// - Returns: The `AnyPublisher` publishing the `Result<Value, AFError>` value.
444
    public func result() -> AnyPublisher<Result<Value, AFError>, Never> {
445
        map(\.result).eraseToAnyPublisher()
446
    }
447
 
448
    /// Publishes the `Result` of the `DownloadResponse` as a single `Value` or fail with the `AFError` instance.
449
    ///
450
    /// - Returns: The `AnyPublisher<Value, AFError>` publishing the stream.
451
    public func value() -> AnyPublisher<Value, AFError> {
452
        setFailureType(to: AFError.self).flatMap(\.result.publisher).eraseToAnyPublisher()
453
    }
454
 
455
    public func receive<S>(subscriber: S) where S: Subscriber, DownloadResponsePublisher.Failure == S.Failure, DownloadResponsePublisher.Output == S.Input {
456
        subscriber.receive(subscription: Inner(request: request,
457
                                               responseHandler: responseHandler,
458
                                               downstream: subscriber))
459
    }
460
 
461
    private final class Inner<Downstream: Subscriber>: Subscription, Cancellable
462
        where Downstream.Input == Output {
463
        typealias Failure = Downstream.Failure
464
 
465
        @Protected
466
        private var downstream: Downstream?
467
        private let request: DownloadRequest
468
        private let responseHandler: Handler
469
 
470
        init(request: DownloadRequest, responseHandler: @escaping Handler, downstream: Downstream) {
471
            self.request = request
472
            self.responseHandler = responseHandler
473
            self.downstream = downstream
474
        }
475
 
476
        func request(_ demand: Subscribers.Demand) {
477
            assert(demand > 0)
478
 
479
            guard let downstream = downstream else { return }
480
 
481
            self.downstream = nil
482
            responseHandler { response in
483
                _ = downstream.receive(response)
484
                downstream.receive(completion: .finished)
485
            }.resume()
486
        }
487
 
488
        func cancel() {
489
            request.cancel()
490
            downstream = nil
491
        }
492
    }
493
}
494
 
495
extension DownloadRequest {
496
    /// Creates a `DownloadResponsePublisher` for this instance using the given `ResponseSerializer` and `DispatchQueue`.
497
    ///
498
    /// - Parameters:
499
    ///   - serializer: `ResponseSerializer` used to serialize the response `Data` from disk.
500
    ///   - queue:      `DispatchQueue` on which the `DownloadResponse` will be published.`.main` by default.
501
    ///
502
    /// - Returns:      The `DownloadResponsePublisher`.
503
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
504
    public func publishResponse<Serializer: ResponseSerializer, T>(using serializer: Serializer, on queue: DispatchQueue = .main) -> DownloadResponsePublisher<T>
505
        where Serializer.SerializedObject == T {
506
        DownloadResponsePublisher(self, queue: queue, serializer: serializer)
507
    }
508
 
509
    /// Creates a `DownloadResponsePublisher` for this instance using the given `DownloadResponseSerializerProtocol` and
510
    /// `DispatchQueue`.
511
    ///
512
    /// - Parameters:
513
    ///   - serializer: `DownloadResponseSerializer` used to serialize the response `Data` from disk.
514
    ///   - queue:      `DispatchQueue` on which the `DownloadResponse` will be published.`.main` by default.
515
    ///
516
    /// - Returns:      The `DownloadResponsePublisher`.
517
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
518
    public func publishResponse<Serializer: DownloadResponseSerializerProtocol, T>(using serializer: Serializer, on queue: DispatchQueue = .main) -> DownloadResponsePublisher<T>
519
        where Serializer.SerializedObject == T {
520
        DownloadResponsePublisher(self, queue: queue, serializer: serializer)
521
    }
522
 
523
    /// Creates a `DownloadResponsePublisher` for this instance and uses a `URLResponseSerializer` to serialize the
524
    /// response.
525
    ///
526
    /// - Parameter queue: `DispatchQueue` on which the `DownloadResponse` will be published. `.main` by default.
527
    ///
528
    /// - Returns:         The `DownloadResponsePublisher`.
529
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
530
    public func publishURL(queue: DispatchQueue = .main) -> DownloadResponsePublisher<URL> {
531
        publishResponse(using: URLResponseSerializer(), on: queue)
532
    }
533
 
534
    /// Creates a `DownloadResponsePublisher` for this instance and uses a `DataResponseSerializer` to serialize the
535
    /// response.
536
    ///
537
    /// - Parameters:
538
    ///   - queue:               `DispatchQueue` on which the `DownloadResponse` will be published. `.main` by default.
539
    ///   - preprocessor:        `DataPreprocessor` which filters the `Data` before serialization. `PassthroughPreprocessor()`
540
    ///                          by default.
541
    ///   - emptyResponseCodes:  `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
542
    ///                          default.
543
    ///   - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
544
    ///                          status code. `[.head]` by default.
545
    ///
546
    /// - Returns:               The `DownloadResponsePublisher`.
547
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
548
    public func publishData(queue: DispatchQueue = .main,
549
                            preprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
550
                            emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
551
                            emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DownloadResponsePublisher<Data> {
552
        publishResponse(using: DataResponseSerializer(dataPreprocessor: preprocessor,
553
                                                      emptyResponseCodes: emptyResponseCodes,
554
                                                      emptyRequestMethods: emptyRequestMethods),
555
                        on: queue)
556
    }
557
 
558
    /// Creates a `DownloadResponsePublisher` for this instance and uses a `StringResponseSerializer` to serialize the
559
    /// response.
560
    ///
561
    /// - Parameters:
562
    ///   - queue:               `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
563
    ///   - preprocessor:        `DataPreprocessor` which filters the `Data` before serialization. `PassthroughPreprocessor()`
564
    ///                          by default.
565
    ///   - encoding:            `String.Encoding` to parse the response. `nil` by default, in which case the encoding
566
    ///                          will be determined by the server response, falling back to the default HTTP character
567
    ///                          set, `ISO-8859-1`.
568
    ///   - emptyResponseCodes:  `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
569
    ///                          default.
570
    ///   - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
571
    ///                          status code. `[.head]` by default.
572
    ///
573
    /// - Returns:               The `DownloadResponsePublisher`.
574
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
575
    public func publishString(queue: DispatchQueue = .main,
576
                              preprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
577
                              encoding: String.Encoding? = nil,
578
                              emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
579
                              emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> DownloadResponsePublisher<String> {
580
        publishResponse(using: StringResponseSerializer(dataPreprocessor: preprocessor,
581
                                                        encoding: encoding,
582
                                                        emptyResponseCodes: emptyResponseCodes,
583
                                                        emptyRequestMethods: emptyRequestMethods),
584
                        on: queue)
585
    }
586
 
587
    @_disfavoredOverload
588
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
589
    @available(*, deprecated, message: "Renamed publishDecodable(type:queue:preprocessor:decoder:emptyResponseCodes:emptyRequestMethods).")
590
    public func publishDecodable<T: Decodable>(type: T.Type = T.self,
591
                                               queue: DispatchQueue = .main,
592
                                               preprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
593
                                               decoder: DataDecoder = JSONDecoder(),
594
                                               emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
595
                                               emptyResponseMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DownloadResponsePublisher<T> {
596
        publishResponse(using: DecodableResponseSerializer(dataPreprocessor: preprocessor,
597
                                                           decoder: decoder,
598
                                                           emptyResponseCodes: emptyResponseCodes,
599
                                                           emptyRequestMethods: emptyResponseMethods),
600
                        on: queue)
601
    }
602
 
603
    /// Creates a `DownloadResponsePublisher` for this instance and uses a `DecodableResponseSerializer` to serialize
604
    /// the response.
605
    ///
606
    /// - Parameters:
607
    ///   - type:                `Decodable` type to which to decode response `Data`. Inferred from the context by default.
608
    ///   - queue:               `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
609
    ///   - preprocessor:        `DataPreprocessor` which filters the `Data` before serialization.
610
    ///                          `PassthroughPreprocessor()` by default.
611
    ///   - decoder:             `DataDecoder` instance used to decode response `Data`. `JSONDecoder()` by default.
612
    ///   - emptyResponseCodes:  `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
613
    ///                          default.
614
    ///   - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless
615
    ///                          of status code. `[.head]` by default.
616
    ///
617
    /// - Returns:               The `DownloadResponsePublisher`.
618
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
619
    public func publishDecodable<T: Decodable>(type: T.Type = T.self,
620
                                               queue: DispatchQueue = .main,
621
                                               preprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
622
                                               decoder: DataDecoder = JSONDecoder(),
623
                                               emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
624
                                               emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DownloadResponsePublisher<T> {
625
        publishResponse(using: DecodableResponseSerializer(dataPreprocessor: preprocessor,
626
                                                           decoder: decoder,
627
                                                           emptyResponseCodes: emptyResponseCodes,
628
                                                           emptyRequestMethods: emptyRequestMethods),
629
                        on: queue)
630
    }
631
}
632
 
633
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
634
extension DownloadResponsePublisher where Value == URL? {
635
    /// Creates an instance which publishes a `DownloadResponse<URL?, AFError>` value without serialization.
636
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
637
    public init(_ request: DownloadRequest, queue: DispatchQueue) {
638
        self.request = request
639
        responseHandler = { request.response(queue: queue, completionHandler: $0) }
640
    }
641
}
642
 
643
extension DownloadRequest {
644
    /// Creates a `DownloadResponsePublisher` for this instance which does not serialize the response before publishing.
645
    ///
646
    /// - Parameter queue: `DispatchQueue` on which the `DownloadResponse` will be published. `.main` by default.
647
    ///
648
    /// - Returns:         The `DownloadResponsePublisher`.
649
    @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
650
    public func publishUnserialized(on queue: DispatchQueue = .main) -> DownloadResponsePublisher<URL?> {
651
        DownloadResponsePublisher(self, queue: queue)
652
    }
653
}
654
 
655
#endif