-
Notifications
You must be signed in to change notification settings - Fork 161
/
Copy pathAsyncMapErrorSequence.swift
105 lines (87 loc) · 3.95 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
100
101
102
103
104
105
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#if compiler(>=6.0)
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.
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
public func mapError<MappedError: Error>(_ transform: @Sendable @escaping (Self.Failure) -> MappedError) -> some AsyncSequence<Self.Element, MappedError> {
AsyncMapErrorSequence(base: self, transform: transform)
}
/// 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.
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
public func mapError<MappedError: Error>(_ transform: @Sendable @escaping (Self.Failure) -> MappedError) -> (some AsyncSequence<Self.Element, MappedError> & Sendable) where Self: Sendable, Self.Element: Sendable {
AsyncMapErrorSequence(base: self, transform: transform)
}
}
/// An asynchronous sequence that converts any failure into a new error.
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
fileprivate struct AsyncMapErrorSequence<Base: AsyncSequence, MappedError: Error>: AsyncSequence {
typealias AsyncIterator = Iterator
typealias Element = Base.Element
typealias Failure = Base.Failure
private let base: Base
private let transform: @Sendable (Failure) -> MappedError
init(
base: Base,
transform: @Sendable @escaping (Failure) -> MappedError
) {
self.base = base
self.transform = transform
}
func makeAsyncIterator() -> Iterator {
Iterator(
base: base.makeAsyncIterator(),
transform: transform
)
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension AsyncMapErrorSequence {
/// The iterator that produces elements of the map sequence.
fileprivate struct Iterator: AsyncIteratorProtocol {
typealias Element = Base.Element
private var base: Base.AsyncIterator
private let transform: @Sendable (Failure) -> MappedError
init(
base: Base.AsyncIterator,
transform: @Sendable @escaping (Failure) -> MappedError
) {
self.base = base
self.transform = transform
}
mutating func next() async throws(MappedError) -> Element? {
try await self.next(isolation: nil)
}
mutating func next(isolation actor: isolated (any Actor)?) async throws(MappedError) -> Element? {
do {
return try await base.next(isolation: actor)
} catch {
throw transform(error)
}
}
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension AsyncMapErrorSequence: Sendable where Base: Sendable, Base.Element: Sendable {}
@available(*, unavailable)
extension AsyncMapErrorSequence.Iterator: Sendable {}
#endif