Concurrency.swift 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. //
  2. // Concurrency.swift
  3. //
  4. // Copyright (c) 2021 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. #if compiler(>=5.6.0) && canImport(_Concurrency)
  25. // swiftformat:options --swiftversion 5.6
  26. import Foundation
  27. // MARK: - Request Event Streams
  28. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  29. extension Request {
  30. /// Creates a `StreamOf<Progress>` for the instance's upload progress.
  31. ///
  32. /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  33. ///
  34. /// - Returns: The `StreamOf<Progress>`.
  35. public func uploadProgress(bufferingPolicy: StreamOf<Progress>.BufferingPolicy = .unbounded) -> StreamOf<Progress> {
  36. stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  37. uploadProgress(queue: .singleEventQueue) { progress in
  38. continuation.yield(progress)
  39. }
  40. }
  41. }
  42. /// Creates a `StreamOf<Progress>` for the instance's download progress.
  43. ///
  44. /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  45. ///
  46. /// - Returns: The `StreamOf<Progress>`.
  47. public func downloadProgress(bufferingPolicy: StreamOf<Progress>.BufferingPolicy = .unbounded) -> StreamOf<Progress> {
  48. stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  49. downloadProgress(queue: .singleEventQueue) { progress in
  50. continuation.yield(progress)
  51. }
  52. }
  53. }
  54. /// Creates a `StreamOf<URLRequest>` for the `URLRequest`s produced for the instance.
  55. ///
  56. /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  57. ///
  58. /// - Returns: The `StreamOf<URLRequest>`.
  59. public func urlRequests(bufferingPolicy: StreamOf<URLRequest>.BufferingPolicy = .unbounded) -> StreamOf<URLRequest> {
  60. stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  61. onURLRequestCreation(on: .singleEventQueue) { request in
  62. continuation.yield(request)
  63. }
  64. }
  65. }
  66. /// Creates a `StreamOf<URLSessionTask>` for the `URLSessionTask`s produced for the instance.
  67. ///
  68. /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  69. ///
  70. /// - Returns: The `StreamOf<URLSessionTask>`.
  71. public func urlSessionTasks(bufferingPolicy: StreamOf<URLSessionTask>.BufferingPolicy = .unbounded) -> StreamOf<URLSessionTask> {
  72. stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  73. onURLSessionTaskCreation(on: .singleEventQueue) { task in
  74. continuation.yield(task)
  75. }
  76. }
  77. }
  78. /// Creates a `StreamOf<String>` for the cURL descriptions produced for the instance.
  79. ///
  80. /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  81. ///
  82. /// - Returns: The `StreamOf<String>`.
  83. public func cURLDescriptions(bufferingPolicy: StreamOf<String>.BufferingPolicy = .unbounded) -> StreamOf<String> {
  84. stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  85. cURLDescription(on: .singleEventQueue) { description in
  86. continuation.yield(description)
  87. }
  88. }
  89. }
  90. private func stream<T>(of type: T.Type = T.self,
  91. bufferingPolicy: StreamOf<T>.BufferingPolicy = .unbounded,
  92. yielder: @escaping (StreamOf<T>.Continuation) -> Void) -> StreamOf<T> {
  93. StreamOf<T>(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  94. yielder(continuation)
  95. // Must come after serializers run in order to catch retry progress.
  96. onFinish {
  97. continuation.finish()
  98. }
  99. }
  100. }
  101. }
  102. // MARK: - DataTask
  103. /// Value used to `await` a `DataResponse` and associated values.
  104. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  105. public struct DataTask<Value: Sendable>: Sendable {
  106. /// `DataResponse` produced by the `DataRequest` and its response handler.
  107. public var response: DataResponse<Value, AFError> {
  108. get async {
  109. if shouldAutomaticallyCancel {
  110. return await withTaskCancellationHandler {
  111. self.cancel()
  112. } operation: {
  113. await task.value
  114. }
  115. } else {
  116. return await task.value
  117. }
  118. }
  119. }
  120. /// `Result` of any response serialization performed for the `response`.
  121. public var result: Result<Value, AFError> {
  122. get async { await response.result }
  123. }
  124. /// `Value` returned by the `response`.
  125. public var value: Value {
  126. get async throws {
  127. try await result.get()
  128. }
  129. }
  130. private let request: DataRequest
  131. private let task: Task<DataResponse<Value, AFError>, Never>
  132. private let shouldAutomaticallyCancel: Bool
  133. fileprivate init(request: DataRequest, task: Task<DataResponse<Value, AFError>, Never>, shouldAutomaticallyCancel: Bool) {
  134. self.request = request
  135. self.task = task
  136. self.shouldAutomaticallyCancel = shouldAutomaticallyCancel
  137. }
  138. /// Cancel the underlying `DataRequest` and `Task`.
  139. public func cancel() {
  140. task.cancel()
  141. }
  142. /// Resume the underlying `DataRequest`.
  143. public func resume() {
  144. request.resume()
  145. }
  146. /// Suspend the underlying `DataRequest`.
  147. public func suspend() {
  148. request.suspend()
  149. }
  150. }
  151. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  152. extension DataRequest {
  153. /// Creates a `DataTask` to `await` a `Data` value.
  154. ///
  155. /// - Parameters:
  156. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  157. /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  158. /// properties. `false` by default.
  159. /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before completion.
  160. /// - emptyResponseCodes: HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
  161. /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  162. ///
  163. /// - Returns: The `DataTask`.
  164. public func serializingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  165. dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
  166. emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
  167. emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DataTask<Data> {
  168. serializingResponse(using: DataResponseSerializer(dataPreprocessor: dataPreprocessor,
  169. emptyResponseCodes: emptyResponseCodes,
  170. emptyRequestMethods: emptyRequestMethods),
  171. automaticallyCancelling: shouldAutomaticallyCancel)
  172. }
  173. /// Creates a `DataTask` to `await` serialization of a `Decodable` value.
  174. ///
  175. /// - Parameters:
  176. /// - type: `Decodable` type to decode from response data.
  177. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  178. /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  179. /// properties. `false` by default.
  180. /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
  181. /// `PassthroughPreprocessor()` by default.
  182. /// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
  183. /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
  184. /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  185. ///
  186. /// - Returns: The `DataTask`.
  187. public func serializingDecodable<Value: Decodable>(_ type: Value.Type = Value.self,
  188. automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  189. dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<Value>.defaultDataPreprocessor,
  190. decoder: DataDecoder = JSONDecoder(),
  191. emptyResponseCodes: Set<Int> = DecodableResponseSerializer<Value>.defaultEmptyResponseCodes,
  192. emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<Value>.defaultEmptyRequestMethods) -> DataTask<Value> {
  193. serializingResponse(using: DecodableResponseSerializer<Value>(dataPreprocessor: dataPreprocessor,
  194. decoder: decoder,
  195. emptyResponseCodes: emptyResponseCodes,
  196. emptyRequestMethods: emptyRequestMethods),
  197. automaticallyCancelling: shouldAutomaticallyCancel)
  198. }
  199. /// Creates a `DataTask` to `await` serialization of a `String` value.
  200. ///
  201. /// - Parameters:
  202. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  203. /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  204. /// properties. `false` by default.
  205. /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
  206. /// `PassthroughPreprocessor()` by default.
  207. /// - encoding: `String.Encoding` to use during serialization. Defaults to `nil`, in which case
  208. /// the encoding will be determined from the server response, falling back to the
  209. /// default HTTP character set, `ISO-8859-1`.
  210. /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
  211. /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  212. ///
  213. /// - Returns: The `DataTask`.
  214. public func serializingString(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  215. dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
  216. encoding: String.Encoding? = nil,
  217. emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
  218. emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> DataTask<String> {
  219. serializingResponse(using: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
  220. encoding: encoding,
  221. emptyResponseCodes: emptyResponseCodes,
  222. emptyRequestMethods: emptyRequestMethods),
  223. automaticallyCancelling: shouldAutomaticallyCancel)
  224. }
  225. /// Creates a `DataTask` to `await` serialization using the provided `ResponseSerializer` instance.
  226. ///
  227. /// - Parameters:
  228. /// - serializer: `ResponseSerializer` responsible for serializing the request, response, and data.
  229. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  230. /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  231. /// properties. `false` by default.
  232. ///
  233. /// - Returns: The `DataTask`.
  234. public func serializingResponse<Serializer: ResponseSerializer>(using serializer: Serializer,
  235. automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
  236. -> DataTask<Serializer.SerializedObject> {
  237. dataTask(automaticallyCancelling: shouldAutomaticallyCancel) {
  238. self.response(queue: .singleEventQueue,
  239. responseSerializer: serializer,
  240. completionHandler: $0)
  241. }
  242. }
  243. /// Creates a `DataTask` to `await` serialization using the provided `DataResponseSerializerProtocol` instance.
  244. ///
  245. /// - Parameters:
  246. /// - serializer: `DataResponseSerializerProtocol` responsible for serializing the request,
  247. /// response, and data.
  248. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  249. /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  250. /// properties. `false` by default.
  251. ///
  252. /// - Returns: The `DataTask`.
  253. public func serializingResponse<Serializer: DataResponseSerializerProtocol>(using serializer: Serializer,
  254. automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
  255. -> DataTask<Serializer.SerializedObject> {
  256. dataTask(automaticallyCancelling: shouldAutomaticallyCancel) {
  257. self.response(queue: .singleEventQueue,
  258. responseSerializer: serializer,
  259. completionHandler: $0)
  260. }
  261. }
  262. private func dataTask<Value>(automaticallyCancelling shouldAutomaticallyCancel: Bool,
  263. forResponse onResponse: @Sendable @escaping (@escaping (DataResponse<Value, AFError>) -> Void) -> Void)
  264. -> DataTask<Value> {
  265. let task = Task {
  266. await withTaskCancellationHandler {
  267. self.cancel()
  268. } operation: {
  269. await withCheckedContinuation { continuation in
  270. onResponse {
  271. continuation.resume(returning: $0)
  272. }
  273. }
  274. }
  275. }
  276. return DataTask<Value>(request: self, task: task, shouldAutomaticallyCancel: shouldAutomaticallyCancel)
  277. }
  278. }
  279. // MARK: - DownloadTask
  280. /// Value used to `await` a `DownloadResponse` and associated values.
  281. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  282. public struct DownloadTask<Value: Sendable>: Sendable {
  283. /// `DownloadResponse` produced by the `DownloadRequest` and its response handler.
  284. public var response: DownloadResponse<Value, AFError> {
  285. get async {
  286. if shouldAutomaticallyCancel {
  287. return await withTaskCancellationHandler {
  288. self.cancel()
  289. } operation: {
  290. await task.value
  291. }
  292. } else {
  293. return await task.value
  294. }
  295. }
  296. }
  297. /// `Result` of any response serialization performed for the `response`.
  298. public var result: Result<Value, AFError> {
  299. get async { await response.result }
  300. }
  301. /// `Value` returned by the `response`.
  302. public var value: Value {
  303. get async throws {
  304. try await result.get()
  305. }
  306. }
  307. private let task: Task<AFDownloadResponse<Value>, Never>
  308. private let request: DownloadRequest
  309. private let shouldAutomaticallyCancel: Bool
  310. fileprivate init(request: DownloadRequest, task: Task<AFDownloadResponse<Value>, Never>, shouldAutomaticallyCancel: Bool) {
  311. self.request = request
  312. self.task = task
  313. self.shouldAutomaticallyCancel = shouldAutomaticallyCancel
  314. }
  315. /// Cancel the underlying `DownloadRequest` and `Task`.
  316. public func cancel() {
  317. task.cancel()
  318. }
  319. /// Resume the underlying `DownloadRequest`.
  320. public func resume() {
  321. request.resume()
  322. }
  323. /// Suspend the underlying `DownloadRequest`.
  324. public func suspend() {
  325. request.suspend()
  326. }
  327. }
  328. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  329. extension DownloadRequest {
  330. /// Creates a `DownloadTask` to `await` a `Data` value.
  331. ///
  332. /// - Parameters:
  333. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  334. /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  335. /// properties. `false` by default.
  336. /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before completion.
  337. /// - emptyResponseCodes: HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
  338. /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  339. ///
  340. /// - Returns: The `DownloadTask`.
  341. public func serializingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  342. dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
  343. emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
  344. emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DownloadTask<Data> {
  345. serializingDownload(using: DataResponseSerializer(dataPreprocessor: dataPreprocessor,
  346. emptyResponseCodes: emptyResponseCodes,
  347. emptyRequestMethods: emptyRequestMethods),
  348. automaticallyCancelling: shouldAutomaticallyCancel)
  349. }
  350. /// Creates a `DownloadTask` to `await` serialization of a `Decodable` value.
  351. ///
  352. /// - Note: This serializer reads the entire response into memory before parsing.
  353. ///
  354. /// - Parameters:
  355. /// - type: `Decodable` type to decode from response data.
  356. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  357. /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  358. /// properties. `false` by default.
  359. /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
  360. /// `PassthroughPreprocessor()` by default.
  361. /// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
  362. /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
  363. /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  364. ///
  365. /// - Returns: The `DownloadTask`.
  366. public func serializingDecodable<Value: Decodable>(_ type: Value.Type = Value.self,
  367. automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  368. dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<Value>.defaultDataPreprocessor,
  369. decoder: DataDecoder = JSONDecoder(),
  370. emptyResponseCodes: Set<Int> = DecodableResponseSerializer<Value>.defaultEmptyResponseCodes,
  371. emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<Value>.defaultEmptyRequestMethods) -> DownloadTask<Value> {
  372. serializingDownload(using: DecodableResponseSerializer<Value>(dataPreprocessor: dataPreprocessor,
  373. decoder: decoder,
  374. emptyResponseCodes: emptyResponseCodes,
  375. emptyRequestMethods: emptyRequestMethods),
  376. automaticallyCancelling: shouldAutomaticallyCancel)
  377. }
  378. /// Creates a `DownloadTask` to `await` serialization of the downloaded file's `URL` on disk.
  379. ///
  380. /// - Parameters:
  381. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  382. /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  383. /// properties. `false` by default.
  384. ///
  385. /// - Returns: The `DownloadTask`.
  386. public func serializingDownloadedFileURL(automaticallyCancelling shouldAutomaticallyCancel: Bool = false) -> DownloadTask<URL> {
  387. serializingDownload(using: URLResponseSerializer(),
  388. automaticallyCancelling: shouldAutomaticallyCancel)
  389. }
  390. /// Creates a `DownloadTask` to `await` serialization of a `String` value.
  391. ///
  392. /// - Parameters:
  393. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  394. /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  395. /// properties. `false` by default.
  396. /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
  397. /// serializer. `PassthroughPreprocessor()` by default.
  398. /// - encoding: `String.Encoding` to use during serialization. Defaults to `nil`, in which case
  399. /// the encoding will be determined from the server response, falling back to the
  400. /// default HTTP character set, `ISO-8859-1`.
  401. /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
  402. /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  403. ///
  404. /// - Returns: The `DownloadTask`.
  405. public func serializingString(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  406. dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
  407. encoding: String.Encoding? = nil,
  408. emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
  409. emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> DownloadTask<String> {
  410. serializingDownload(using: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
  411. encoding: encoding,
  412. emptyResponseCodes: emptyResponseCodes,
  413. emptyRequestMethods: emptyRequestMethods),
  414. automaticallyCancelling: shouldAutomaticallyCancel)
  415. }
  416. /// Creates a `DownloadTask` to `await` serialization using the provided `ResponseSerializer` instance.
  417. ///
  418. /// - Parameters:
  419. /// - serializer: `ResponseSerializer` responsible for serializing the request, response, and data.
  420. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  421. /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  422. /// properties. `false` by default.
  423. ///
  424. /// - Returns: The `DownloadTask`.
  425. public func serializingDownload<Serializer: ResponseSerializer>(using serializer: Serializer,
  426. automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
  427. -> DownloadTask<Serializer.SerializedObject> {
  428. downloadTask(automaticallyCancelling: shouldAutomaticallyCancel) {
  429. self.response(queue: .singleEventQueue,
  430. responseSerializer: serializer,
  431. completionHandler: $0)
  432. }
  433. }
  434. /// Creates a `DownloadTask` to `await` serialization using the provided `DownloadResponseSerializerProtocol`
  435. /// instance.
  436. ///
  437. /// - Parameters:
  438. /// - serializer: `DownloadResponseSerializerProtocol` responsible for serializing the request,
  439. /// response, and data.
  440. /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  441. /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  442. /// properties. `false` by default.
  443. ///
  444. /// - Returns: The `DownloadTask`.
  445. public func serializingDownload<Serializer: DownloadResponseSerializerProtocol>(using serializer: Serializer,
  446. automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
  447. -> DownloadTask<Serializer.SerializedObject> {
  448. downloadTask(automaticallyCancelling: shouldAutomaticallyCancel) {
  449. self.response(queue: .singleEventQueue,
  450. responseSerializer: serializer,
  451. completionHandler: $0)
  452. }
  453. }
  454. private func downloadTask<Value>(automaticallyCancelling shouldAutomaticallyCancel: Bool,
  455. forResponse onResponse: @Sendable @escaping (@escaping (DownloadResponse<Value, AFError>) -> Void) -> Void)
  456. -> DownloadTask<Value> {
  457. let task = Task {
  458. await withTaskCancellationHandler {
  459. self.cancel()
  460. } operation: {
  461. await withCheckedContinuation { continuation in
  462. onResponse {
  463. continuation.resume(returning: $0)
  464. }
  465. }
  466. }
  467. }
  468. return DownloadTask<Value>(request: self, task: task, shouldAutomaticallyCancel: shouldAutomaticallyCancel)
  469. }
  470. }
  471. // MARK: - DataStreamTask
  472. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  473. public struct DataStreamTask {
  474. // Type of created streams.
  475. public typealias Stream<Success, Failure: Error> = StreamOf<DataStreamRequest.Stream<Success, Failure>>
  476. private let request: DataStreamRequest
  477. fileprivate init(request: DataStreamRequest) {
  478. self.request = request
  479. }
  480. /// Creates a `Stream` of `Data` values from the underlying `DataStreamRequest`.
  481. ///
  482. /// - Parameters:
  483. /// - shouldAutomaticallyCancel: `Bool` indicating whether the underlying `DataStreamRequest` should be canceled
  484. /// which observation of the stream stops. `true` by default.
  485. /// - bufferingPolicy: ` BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  486. ///
  487. /// - Returns: The `Stream`.
  488. public func streamingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = true, bufferingPolicy: Stream<Data, Never>.BufferingPolicy = .unbounded) -> Stream<Data, Never> {
  489. createStream(automaticallyCancelling: shouldAutomaticallyCancel, bufferingPolicy: bufferingPolicy) { onStream in
  490. self.request.responseStream(on: .streamCompletionQueue(forRequestID: request.id), stream: onStream)
  491. }
  492. }
  493. /// Creates a `Stream` of `UTF-8` `String`s from the underlying `DataStreamRequest`.
  494. ///
  495. /// - Parameters:
  496. /// - shouldAutomaticallyCancel: `Bool` indicating whether the underlying `DataStreamRequest` should be canceled
  497. /// which observation of the stream stops. `true` by default.
  498. /// - bufferingPolicy: ` BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  499. /// - Returns:
  500. public func streamingStrings(automaticallyCancelling shouldAutomaticallyCancel: Bool = true, bufferingPolicy: Stream<String, Never>.BufferingPolicy = .unbounded) -> Stream<String, Never> {
  501. createStream(automaticallyCancelling: shouldAutomaticallyCancel, bufferingPolicy: bufferingPolicy) { onStream in
  502. self.request.responseStreamString(on: .streamCompletionQueue(forRequestID: request.id), stream: onStream)
  503. }
  504. }
  505. /// Creates a `Stream` of `Decodable` values from the underlying `DataStreamRequest`.
  506. ///
  507. /// - Parameters:
  508. /// - type: `Decodable` type to be serialized from stream payloads.
  509. /// - shouldAutomaticallyCancel: `Bool` indicating whether the underlying `DataStreamRequest` should be canceled
  510. /// which observation of the stream stops. `true` by default.
  511. /// - bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  512. ///
  513. /// - Returns: The `Stream`.
  514. public func streamingDecodables<T>(_ type: T.Type = T.self,
  515. automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
  516. bufferingPolicy: Stream<T, AFError>.BufferingPolicy = .unbounded)
  517. -> Stream<T, AFError> where T: Decodable {
  518. streamingResponses(serializedUsing: DecodableStreamSerializer<T>(),
  519. automaticallyCancelling: shouldAutomaticallyCancel,
  520. bufferingPolicy: bufferingPolicy)
  521. }
  522. /// Creates a `Stream` of values using the provided `DataStreamSerializer` from the underlying `DataStreamRequest`.
  523. ///
  524. /// - Parameters:
  525. /// - serializer: `DataStreamSerializer` to use to serialize incoming `Data`.
  526. /// - shouldAutomaticallyCancel: `Bool` indicating whether the underlying `DataStreamRequest` should be canceled
  527. /// which observation of the stream stops. `true` by default.
  528. /// - bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  529. ///
  530. /// - Returns: The `Stream`.
  531. public func streamingResponses<Serializer: DataStreamSerializer>(serializedUsing serializer: Serializer,
  532. automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
  533. bufferingPolicy: Stream<Serializer.SerializedObject, AFError>.BufferingPolicy = .unbounded)
  534. -> Stream<Serializer.SerializedObject, AFError> {
  535. createStream(automaticallyCancelling: shouldAutomaticallyCancel, bufferingPolicy: bufferingPolicy) { onStream in
  536. self.request.responseStream(using: serializer,
  537. on: .streamCompletionQueue(forRequestID: request.id),
  538. stream: onStream)
  539. }
  540. }
  541. private func createStream<Success, Failure: Error>(automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
  542. bufferingPolicy: Stream<Success, Failure>.BufferingPolicy = .unbounded,
  543. forResponse onResponse: @escaping (@escaping (DataStreamRequest.Stream<Success, Failure>) -> Void) -> Void)
  544. -> Stream<Success, Failure> {
  545. StreamOf(bufferingPolicy: bufferingPolicy) {
  546. guard shouldAutomaticallyCancel,
  547. request.isInitialized || request.isResumed || request.isSuspended else { return }
  548. cancel()
  549. } builder: { continuation in
  550. onResponse { stream in
  551. continuation.yield(stream)
  552. if case .complete = stream.event {
  553. continuation.finish()
  554. }
  555. }
  556. }
  557. }
  558. /// Cancel the underlying `DataStreamRequest`.
  559. public func cancel() {
  560. request.cancel()
  561. }
  562. /// Resume the underlying `DataStreamRequest`.
  563. public func resume() {
  564. request.resume()
  565. }
  566. /// Suspend the underlying `DataStreamRequest`.
  567. public func suspend() {
  568. request.suspend()
  569. }
  570. }
  571. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  572. extension DataStreamRequest {
  573. /// Creates a `DataStreamTask` used to `await` streams of serialized values.
  574. ///
  575. /// - Returns: The `DataStreamTask`.
  576. public func streamTask() -> DataStreamTask {
  577. DataStreamTask(request: self)
  578. }
  579. }
  580. extension DispatchQueue {
  581. fileprivate static let singleEventQueue = DispatchQueue(label: "org.alamofire.concurrencySingleEventQueue",
  582. attributes: .concurrent)
  583. fileprivate static func streamCompletionQueue(forRequestID id: UUID) -> DispatchQueue {
  584. DispatchQueue(label: "org.alamofire.concurrencyStreamCompletionQueue-\(id)", target: .singleEventQueue)
  585. }
  586. }
  587. /// An asynchronous sequence generated from an underlying `AsyncStream`. Only produced by Alamofire.
  588. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  589. public struct StreamOf<Element>: AsyncSequence {
  590. public typealias AsyncIterator = Iterator
  591. public typealias BufferingPolicy = AsyncStream<Element>.Continuation.BufferingPolicy
  592. fileprivate typealias Continuation = AsyncStream<Element>.Continuation
  593. private let bufferingPolicy: BufferingPolicy
  594. private let onTermination: (() -> Void)?
  595. private let builder: (Continuation) -> Void
  596. fileprivate init(bufferingPolicy: BufferingPolicy = .unbounded,
  597. onTermination: (() -> Void)? = nil,
  598. builder: @escaping (Continuation) -> Void) {
  599. self.bufferingPolicy = bufferingPolicy
  600. self.onTermination = onTermination
  601. self.builder = builder
  602. }
  603. public func makeAsyncIterator() -> Iterator {
  604. var continuation: AsyncStream<Element>.Continuation?
  605. let stream = AsyncStream<Element> { innerContinuation in
  606. continuation = innerContinuation
  607. builder(innerContinuation)
  608. }
  609. return Iterator(iterator: stream.makeAsyncIterator()) {
  610. continuation?.finish()
  611. self.onTermination?()
  612. }
  613. }
  614. public struct Iterator: AsyncIteratorProtocol {
  615. private final class Token {
  616. private let onDeinit: () -> Void
  617. init(onDeinit: @escaping () -> Void) {
  618. self.onDeinit = onDeinit
  619. }
  620. deinit {
  621. onDeinit()
  622. }
  623. }
  624. private var iterator: AsyncStream<Element>.AsyncIterator
  625. private let token: Token
  626. init(iterator: AsyncStream<Element>.AsyncIterator, onCancellation: @escaping () -> Void) {
  627. self.iterator = iterator
  628. token = Token(onDeinit: onCancellation)
  629. }
  630. public mutating func next() async -> Element? {
  631. await iterator.next()
  632. }
  633. }
  634. }
  635. // swiftformat:options --swiftversion 5.6
  636. #endif