-
Notifications
You must be signed in to change notification settings - Fork 162
/
Copy pathAsyncMapErrorSequence.swift
99 lines (83 loc) · 3.15 KB
/
AsyncMapErrorSequence.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
extension AsyncSequence {
/// Converts any failure into a new error.
///
/// - Parameter transform: A closure that takes the failure as a parameter and returns a new error.
/// - Returns: An asynchronous sequence that maps the error thrown into the one produced by the transform closure.
///
/// Use the ``mapError(_:)`` operator when you need to replace one error type with another.
public func mapError<ErrorType>(transform: @Sendable @escaping (Error) -> ErrorType) -> AsyncMapErrorSequence<Self, ErrorType> {
.init(base: self, transform: transform)
}
}
/// An asynchronous sequence that converts any failure into a new error.
public struct AsyncMapErrorSequence<Base: AsyncSequence, ErrorType: Error>: AsyncSequence {
public typealias AsyncIterator = Iterator
public typealias Element = Base.Element
private let base: Base
private let transform: @Sendable (Error) -> ErrorType
init(
base: Base,
transform: @Sendable @escaping (Error) -> ErrorType
) {
self.base = base
self.transform = transform
}
public func makeAsyncIterator() -> Iterator {
Iterator(
base: base.makeAsyncIterator(),
transform: transform
)
}
}
extension AsyncMapErrorSequence {
/// The iterator that produces elements of the map sequence.
public struct Iterator: AsyncIteratorProtocol {
public typealias Element = Base.Element
private var base: Base.AsyncIterator
private let transform: @Sendable (Error) -> ErrorType
init(
base: Base.AsyncIterator,
transform: @Sendable @escaping (Error) -> ErrorType
) {
self.base = base
self.transform = transform
}
#if compiler(>=6.0)
public mutating func next() async throws(ErrorType) -> Element? {
do {
return try await base.next()
} catch {
throw transform(error)
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
public mutating func next(isolation actor: isolated (any Actor)?) async throws(ErrorType) -> Element? {
do {
return try await base.next(isolation: actor)
} catch {
throw transform(error)
}
}
#else
public mutating func next() async throws -> Element? {
do {
return try await base.next()
} catch {
throw transform(error)
}
}
#endif
}
}
extension AsyncMapErrorSequence: Sendable where Base: Sendable, Base.Element: Sendable {}