|
11 | 11 |
|
12 | 12 | extension AsyncSequence where Element: AsyncSequence {
|
13 | 13 | @inlinable
|
14 |
| - public func joined<Separator: AsyncSequence>(separator: Separator) -> AsyncJoinedSequence<Self, Separator> { |
15 |
| - return AsyncJoinedSequence(self, separator: separator) |
| 14 | + public func joined() -> AsyncJoinedSequence<Self> { |
| 15 | + return AsyncJoinedSequence(self) |
16 | 16 | }
|
17 | 17 | }
|
18 | 18 |
|
19 |
| -public struct AsyncJoinedSequence<Base: AsyncSequence, Separator: AsyncSequence>: AsyncSequence where Base.Element: AsyncSequence, Separator.Element == Base.Element.Element { |
| 19 | +@frozen |
| 20 | +public struct AsyncJoinedSequence<Base: AsyncSequence>: AsyncSequence where Base.Element: AsyncSequence { |
20 | 21 | public typealias Element = Base.Element.Element
|
21 | 22 | public typealias AsyncIterator = Iterator
|
22 | 23 |
|
| 24 | + @frozen |
23 | 25 | public struct Iterator: AsyncIteratorProtocol {
|
24 | 26 | @usableFromInline
|
25 | 27 | enum State {
|
26 |
| - @usableFromInline |
27 |
| - enum SeparatorState { |
28 |
| - case initial(Separator) |
29 |
| - case partialAsync(Separator.AsyncIterator, ContiguousArray<Element>) |
30 |
| - case cached(ContiguousArray<Element>) |
31 |
| - case partialCached(ContiguousArray<Element>.Iterator, ContiguousArray<Element>) |
32 |
| - |
33 |
| - @usableFromInline |
34 |
| - func startSeparator() -> SeparatorState { |
35 |
| - switch self { |
36 |
| - case .initial(let separatorSequence): |
37 |
| - return .partialAsync(separatorSequence.makeAsyncIterator(), []) |
38 |
| - case .cached(let array): |
39 |
| - return .partialCached(array.makeIterator(), array) |
40 |
| - default: |
41 |
| - fatalError("Invalid separator sequence state") |
42 |
| - } |
43 |
| - } |
44 |
| - |
45 |
| - @usableFromInline |
46 |
| - func next() async rethrows -> (Element?, SeparatorState) { |
47 |
| - switch self { |
48 |
| - case .partialAsync(var separatorIterator, var cache): |
49 |
| - guard let next = try await separatorIterator.next() else { |
50 |
| - return (nil, .cached(cache)) |
51 |
| - } |
52 |
| - cache.append(next) |
53 |
| - return (next, .partialAsync(separatorIterator, cache)) |
54 |
| - case .partialCached(var cacheIterator, let cache): |
55 |
| - guard let next = cacheIterator.next() else { |
56 |
| - return (nil, .cached(cache)) |
57 |
| - } |
58 |
| - return (next, .partialCached(cacheIterator, cache)) |
59 |
| - default: |
60 |
| - fatalError("Invalid separator sequence state") |
61 |
| - } |
62 |
| - } |
63 |
| - } |
64 |
| - |
65 |
| - case initial(Base.AsyncIterator, Separator) |
66 |
| - case sequence(Base.AsyncIterator, Base.Element.AsyncIterator, SeparatorState) |
67 |
| - case separator(Base.AsyncIterator, SeparatorState, Base.Element) |
| 28 | + case initial(Base.AsyncIterator) |
| 29 | + case sequence(Base.AsyncIterator, Base.Element.AsyncIterator) |
68 | 30 | case terminal
|
69 | 31 | }
|
70 |
| - |
| 32 | + |
71 | 33 | @usableFromInline
|
72 | 34 | var state: State
|
73 |
| - |
74 |
| - @usableFromInline |
75 |
| - init(_ iterator: Base.AsyncIterator, separator: Separator) { |
76 |
| - state = .initial(iterator, separator) |
| 35 | + |
| 36 | + @inlinable |
| 37 | + init(_ iterator: Base.AsyncIterator) { |
| 38 | + state = .initial(iterator) |
77 | 39 | }
|
78 |
| - |
| 40 | + |
79 | 41 | @inlinable
|
80 | 42 | public mutating func next() async rethrows -> Base.Element.Element? {
|
81 | 43 | do {
|
82 | 44 | switch state {
|
83 | 45 | case .terminal:
|
84 | 46 | return nil
|
85 |
| - case .initial(var outerIterator, let separator): |
| 47 | + case .initial(var outerIterator): |
86 | 48 | guard let innerSequence = try await outerIterator.next() else {
|
87 | 49 | state = .terminal
|
88 | 50 | return nil
|
89 | 51 | }
|
90 | 52 | let innerIterator = innerSequence.makeAsyncIterator()
|
91 |
| - state = .sequence(outerIterator, innerIterator, .initial(separator)) |
| 53 | + state = .sequence(outerIterator, innerIterator) |
92 | 54 | return try await next()
|
93 |
| - case .sequence(var outerIterator, var innerIterator, let separatorState): |
94 |
| - if let item = try await innerIterator.next() { |
95 |
| - state = .sequence(outerIterator, innerIterator, separatorState) |
96 |
| - return item |
97 |
| - } |
98 |
| - |
99 |
| - guard let nextInner = try await outerIterator.next() else { |
100 |
| - state = .terminal |
101 |
| - return nil |
102 |
| - } |
103 |
| - |
104 |
| - state = .separator(outerIterator, separatorState.startSeparator(), nextInner) |
105 |
| - return try await next() |
106 |
| - case .separator(let iterator, let separatorState, let nextBase): |
107 |
| - let (itemOpt, newSepState) = try await separatorState.next() |
108 |
| - guard let item = itemOpt else { |
109 |
| - state = .sequence(iterator, nextBase.makeAsyncIterator(), newSepState) |
110 |
| - return try await next() |
| 55 | + case .sequence(var outerIterator, var innerIterator): |
| 56 | + if let item = try await innerIterator.next() { |
| 57 | + state = .sequence(outerIterator, innerIterator) |
| 58 | + return item |
111 | 59 | }
|
112 |
| - state = .separator(iterator, newSepState, nextBase) |
113 |
| - return item |
| 60 | + |
| 61 | + guard let nextInner = try await outerIterator.next() else { |
| 62 | + state = .terminal |
| 63 | + return nil |
| 64 | + } |
| 65 | + |
| 66 | + state = .sequence(outerIterator, nextInner.makeAsyncIterator()) |
| 67 | + return try await next() |
114 | 68 | }
|
115 | 69 | } catch {
|
116 | 70 | state = .terminal
|
117 | 71 | throw error
|
118 | 72 | }
|
119 | 73 | }
|
120 | 74 | }
|
121 |
| - |
| 75 | + |
122 | 76 | @usableFromInline
|
123 | 77 | let base: Base
|
124 |
| - |
125 |
| - @usableFromInline |
126 |
| - let separator: Separator |
127 |
| - |
128 |
| - @usableFromInline |
129 |
| - init(_ base: Base, separator: Separator) { |
| 78 | + |
| 79 | + @inlinable |
| 80 | + init(_ base: Base) { |
130 | 81 | self.base = base
|
131 |
| - self.separator = separator |
132 | 82 | }
|
133 |
| - |
| 83 | + |
134 | 84 | @inlinable
|
135 | 85 | public func makeAsyncIterator() -> Iterator {
|
136 |
| - return Iterator(base.makeAsyncIterator(), separator: separator) |
| 86 | + return Iterator(base.makeAsyncIterator()) |
137 | 87 | }
|
138 | 88 | }
|
139 | 89 |
|
140 | 90 | extension AsyncJoinedSequence: Sendable
|
141 |
| - where Base: Sendable, Base.Element: Sendable, Base.Element.Element: Sendable, Base.AsyncIterator: Sendable, Separator: Sendable, Separator.AsyncIterator: Sendable, Base.Element.AsyncIterator: Sendable { } |
| 91 | +where Base: Sendable, Base.Element: Sendable, Base.Element.Element: Sendable, Base.AsyncIterator: Sendable, Base.Element.AsyncIterator: Sendable { } |
142 | 92 | extension AsyncJoinedSequence.Iterator: Sendable
|
143 |
| - where Base: Sendable, Base.Element: Sendable, Base.Element.Element: Sendable, Base.AsyncIterator: Sendable, Separator: Sendable, Separator.AsyncIterator: Sendable, Base.Element.AsyncIterator: Sendable { } |
| 93 | +where Base: Sendable, Base.Element: Sendable, Base.Element.Element: Sendable, Base.AsyncIterator: Sendable, Base.Element.AsyncIterator: Sendable { } |
144 | 94 | extension AsyncJoinedSequence.Iterator.State: Sendable
|
145 |
| - where Base: Sendable, Base.Element: Sendable, Base.Element.Element: Sendable, Base.AsyncIterator: Sendable, Separator: Sendable, Separator.AsyncIterator: Sendable, Base.Element.AsyncIterator: Sendable { } |
146 |
| -extension AsyncJoinedSequence.Iterator.State.SeparatorState: Sendable |
147 |
| - where Base: Sendable, Base.Element: Sendable, Base.Element.Element: Sendable, Base.AsyncIterator: Sendable, Separator: Sendable, Separator.AsyncIterator: Sendable, Base.Element.AsyncIterator: Sendable { } |
| 95 | +where Base: Sendable, Base.Element: Sendable, Base.Element.Element: Sendable, Base.AsyncIterator: Sendable, Base.Element.AsyncIterator: Sendable { } |
0 commit comments