Skip to content

Commit d34bd54

Browse files
committed
Conditionally conform EnumeratedSequence to Collections
1 parent 0dfca46 commit d34bd54

File tree

5 files changed

+314
-89
lines changed

5 files changed

+314
-89
lines changed

stdlib/public/core/Algorithm.swift

Lines changed: 0 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -74,91 +74,3 @@ public func max<T: Comparable>(_ x: T, _ y: T, _ z: T, _ rest: T...) -> T {
7474
}
7575
return maxValue
7676
}
77-
78-
/// An enumeration of the elements of a sequence or collection.
79-
///
80-
/// `EnumeratedSequence` is a sequence of pairs (*n*, *x*), where *n*s are
81-
/// consecutive `Int` values starting at zero, and *x*s are the elements of a
82-
/// base sequence.
83-
///
84-
/// To create an instance of `EnumeratedSequence`, call `enumerated()` on a
85-
/// sequence or collection. The following example enumerates the elements of
86-
/// an array.
87-
///
88-
/// var s = ["foo", "bar"].enumerated()
89-
/// for (n, x) in s {
90-
/// print("\(n): \(x)")
91-
/// }
92-
/// // Prints "0: foo"
93-
/// // Prints "1: bar"
94-
@frozen
95-
public struct EnumeratedSequence<Base: Sequence> {
96-
@usableFromInline
97-
internal var _base: Base
98-
99-
/// Construct from a `Base` sequence.
100-
@inlinable
101-
internal init(_base: Base) {
102-
self._base = _base
103-
}
104-
}
105-
106-
extension EnumeratedSequence: Sendable where Base: Sendable {}
107-
108-
extension EnumeratedSequence {
109-
/// The iterator for `EnumeratedSequence`.
110-
///
111-
/// An instance of this iterator wraps a base iterator and yields
112-
/// successive `Int` values, starting at zero, along with the elements of the
113-
/// underlying base iterator. The following example enumerates the elements of
114-
/// an array:
115-
///
116-
/// var iterator = ["foo", "bar"].enumerated().makeIterator()
117-
/// iterator.next() // (0, "foo")
118-
/// iterator.next() // (1, "bar")
119-
/// iterator.next() // nil
120-
///
121-
/// To create an instance, call
122-
/// `enumerated().makeIterator()` on a sequence or collection.
123-
@frozen
124-
public struct Iterator {
125-
@usableFromInline
126-
internal var _base: Base.Iterator
127-
@usableFromInline
128-
internal var _count: Int
129-
130-
/// Construct from a `Base` iterator.
131-
@inlinable
132-
internal init(_base: Base.Iterator) {
133-
self._base = _base
134-
self._count = 0
135-
}
136-
}
137-
}
138-
139-
extension EnumeratedSequence.Iterator: Sendable where Base.Iterator: Sendable {}
140-
141-
extension EnumeratedSequence.Iterator: IteratorProtocol, Sequence {
142-
/// The type of element returned by `next()`.
143-
public typealias Element = (offset: Int, element: Base.Element)
144-
145-
/// Advances to the next element and returns it, or `nil` if no next element
146-
/// exists.
147-
///
148-
/// Once `nil` has been returned, all subsequent calls return `nil`.
149-
@inlinable
150-
public mutating func next() -> Element? {
151-
guard let b = _base.next() else { return nil }
152-
let result = (offset: _count, element: b)
153-
_count += 1
154-
return result
155-
}
156-
}
157-
158-
extension EnumeratedSequence: Sequence {
159-
/// Returns an iterator over the elements of this sequence.
160-
@inlinable
161-
public __consuming func makeIterator() -> Iterator {
162-
return Iterator(_base: _base.makeIterator())
163-
}
164-
}

stdlib/public/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ split_embedded_sources(
7575
EMBEDDED DropWhile.swift
7676
NORMAL Dump.swift
7777
EMBEDDED EmptyCollection.swift
78+
EMBEDDED EnumeratedSequence.swift
7879
EMBEDDED Equatable.swift
7980
EMBEDDED ErrorType.swift
8081
EMBEDDED ExistentialCollection.swift
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// An enumeration of the elements of a sequence or collection.
14+
///
15+
/// `EnumeratedSequence` is a sequence of pairs (*n*, *x*), where *n*s are
16+
/// consecutive `Int` values starting at zero, and *x*s are the elements of a
17+
/// base sequence.
18+
///
19+
/// To create an instance of `EnumeratedSequence`, call `enumerated()` on a
20+
/// sequence or collection. The following example enumerates the elements of
21+
/// an array.
22+
///
23+
/// var s = ["foo", "bar"].enumerated()
24+
/// for (n, x) in s {
25+
/// print("\(n): \(x)")
26+
/// }
27+
/// // Prints "0: foo"
28+
/// // Prints "1: bar"
29+
@frozen
30+
public struct EnumeratedSequence<Base: Sequence> {
31+
@usableFromInline
32+
internal var _base: Base
33+
34+
/// Construct from a `Base` sequence.
35+
@inlinable
36+
internal init(_base: Base) {
37+
self._base = _base
38+
}
39+
}
40+
41+
extension EnumeratedSequence: Sendable where Base: Sendable {}
42+
43+
extension EnumeratedSequence {
44+
/// The iterator for `EnumeratedSequence`.
45+
///
46+
/// An instance of this iterator wraps a base iterator and yields
47+
/// successive `Int` values, starting at zero, along with the elements of the
48+
/// underlying base iterator. The following example enumerates the elements of
49+
/// an array:
50+
///
51+
/// var iterator = ["foo", "bar"].enumerated().makeIterator()
52+
/// iterator.next() // (0, "foo")
53+
/// iterator.next() // (1, "bar")
54+
/// iterator.next() // nil
55+
///
56+
/// To create an instance, call
57+
/// `enumerated().makeIterator()` on a sequence or collection.
58+
@frozen
59+
public struct Iterator {
60+
@usableFromInline
61+
internal var _base: Base.Iterator
62+
@usableFromInline
63+
internal var _count: Int
64+
65+
/// Construct from a `Base` iterator.
66+
@inlinable
67+
internal init(_base: Base.Iterator) {
68+
self._base = _base
69+
self._count = 0
70+
}
71+
}
72+
}
73+
74+
extension EnumeratedSequence.Iterator: Sendable where Base.Iterator: Sendable {}
75+
76+
extension EnumeratedSequence.Iterator: IteratorProtocol, Sequence {
77+
/// The type of element returned by `next()`.
78+
public typealias Element = (offset: Int, element: Base.Element)
79+
80+
/// Advances to the next element and returns it, or `nil` if no next element
81+
/// exists.
82+
///
83+
/// Once `nil` has been returned, all subsequent calls return `nil`.
84+
@inlinable
85+
public mutating func next() -> Element? {
86+
guard let b = _base.next() else { return nil }
87+
let result = (offset: _count, element: b)
88+
_count += 1
89+
return result
90+
}
91+
}
92+
93+
extension EnumeratedSequence: Sequence {
94+
/// Returns an iterator over the elements of this sequence.
95+
@inlinable
96+
public __consuming func makeIterator() -> Iterator {
97+
return Iterator(_base: _base.makeIterator())
98+
}
99+
}
100+
101+
@available(SwiftStdlib 6.1, *)
102+
extension EnumeratedSequence: Collection where Base: Collection {
103+
@available(SwiftStdlib 6.1, *)
104+
@frozen
105+
public struct Index {
106+
/// The position in the underlying collection.
107+
public let base: Base.Index
108+
109+
/// The offset corresponding to this index when `base` is not the end index,
110+
/// `0` otherwise.
111+
@usableFromInline
112+
let _offset: Int
113+
114+
@available(SwiftStdlib 6.1, *)
115+
@_alwaysEmitIntoClient
116+
init(base: Base.Index, offset: Int) {
117+
self.base = base
118+
self.offset = offset
119+
}
120+
}
121+
122+
@available(SwiftStdlib 6.1, *)
123+
@_alwaysEmitIntoClient
124+
public var startIndex: Index {
125+
Index(base: _base.startIndex, offset: 0)
126+
}
127+
128+
@available(SwiftStdlib 6.1, *)
129+
@_alwaysEmitIntoClient
130+
public var endIndex: Index {
131+
Index(base: _base.endIndex, offset: 0)
132+
}
133+
134+
@available(SwiftStdlib 6.1, *)
135+
@_alwaysEmitIntoClient
136+
public var count: Int {
137+
_base.count
138+
}
139+
140+
@available(SwiftStdlib 6.1, *)
141+
@_alwaysEmitIntoClient
142+
public var isEmpty: Bool {
143+
_base.isEmpty
144+
}
145+
146+
/// Returns the offset corresponding to `index`.
147+
///
148+
/// - Complexity: O(*n*) if `index == endIndex` and `Base` does not conform to
149+
/// `RandomAccessCollection`, O(1) otherwise.
150+
@available(SwiftStdlib 6.1, *)
151+
@_alwaysEmitIntoClient
152+
func _offset(of index: Index) -> Int {
153+
index.base == _base.endIndex ? _base.count : index.offset
154+
}
155+
156+
@available(SwiftStdlib 6.1, *)
157+
@_alwaysEmitIntoClient
158+
public func distance(from start: Index, to end: Index) -> Int {
159+
if start.base == _base.endIndex || end.base == _base.endIndex {
160+
return _base.distance(from: start.base, to: end.base)
161+
} else {
162+
return end.offset - start.offset
163+
}
164+
}
165+
166+
@available(SwiftStdlib 6.1, *)
167+
@_alwaysEmitIntoClient
168+
public func index(after index: Index) -> Index {
169+
Index(base: _base.index(after: index.base), offset: index.offset + 1)
170+
}
171+
172+
@available(SwiftStdlib 6.1, *)
173+
@_alwaysEmitIntoClient
174+
public func index(_ i: Index, offsetBy distance: Int) -> Index {
175+
let index = _base.index(i.base, offsetBy: distance)
176+
let offset = distance >= 0 ? i.offset : _offset(of: i)
177+
return Index(base: index, offset: offset + distance)
178+
}
179+
180+
@available(SwiftStdlib 6.1, *)
181+
@_alwaysEmitIntoClient
182+
public func index(
183+
_ i: Index,
184+
offsetBy distance: Int,
185+
limitedBy limit: Index
186+
) -> Index? {
187+
guard let index = _base.index(
188+
i.base,
189+
offsetBy: distance,
190+
limitedBy: limit
191+
) else {
192+
return nil
193+
}
194+
195+
let offset = distance >= 0 ? i.offset : _offset(of: i)
196+
return Index(base: index, offset: offset + distance)
197+
}
198+
199+
@available(SwiftStdlib 6.1, *)
200+
@_alwaysEmitIntoClient
201+
public subscript(_ position: Int) -> Element {
202+
_precondition(
203+
_base.startIndex <= position.base && position.base < _base.endIndex,
204+
"Index out of bounds"
205+
)
206+
207+
return (position.offset, _base[position.base])
208+
}
209+
}
210+
211+
@available(SwiftStdlib 6.1, *)
212+
extension EnumeratedSequence.Index: Comparable {
213+
@available(SwiftStdlib 6.1, *)
214+
@_alwaysEmitIntoClient
215+
public static ==(lhs: Self, rhs: Self) -> Bool {
216+
lhs.base == rhs.base
217+
}
218+
219+
@available(SwiftStdlib 6.1, *)
220+
@_alwaysEmitIntoClient
221+
public static func <(lhs: Self, rhs: Self) -> Bool {
222+
lhs.base < rhs.base
223+
}
224+
}
225+
226+
@available(SwiftStdlib 6.1, *)
227+
extension EnumeratedSequence: BidirectionalCollection where Base: BidirectionalCollection {
228+
@available(SwiftStdlib 6.1, *)
229+
@_alwaysEmitIntoClient
230+
public func index(before index: Index) -> Index {
231+
Index(base: _base.index(before: index.base), offset: _offset(of: index) - 1)
232+
}
233+
}
234+
235+
@available(SwiftStdlib 6.1, *)
236+
extension EnumeratedSequence: RandomAccessCollection where Base: RandomAccessCollection {}

stdlib/public/core/GroupInfo.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
],
9797
"Lazy Views": [
9898
"Algorithm.swift",
99+
"EnumeratedSequence.swift"
99100
"Flatten.swift",
100101
"FlatMap.swift",
101102
"Map.swift",

0 commit comments

Comments
 (0)