Skip to content

Commit 4770b04

Browse files
committed
[ReplaceSubrange] Create .overlay namespace struct, add RRC-like convenience methods
1 parent ebdcf5c commit 4770b04

File tree

2 files changed

+156
-75
lines changed

2 files changed

+156
-75
lines changed

Sources/Algorithms/ReplaceSubrange.swift

Lines changed: 118 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,114 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12-
extension LazyCollection {
12+
/// A namespace for methods which overlay a collection of elements
13+
/// over a region of a base collection.
14+
///
15+
/// Access the namespace via the `.overlay` member, available on all collections:
16+
///
17+
/// ```swift
18+
/// let base = 0..<5
19+
/// for n in base.overlay.inserting(42, at: 2) {
20+
/// print(n)
21+
/// }
22+
/// // Prints: 0, 1, 42, 2, 3, 4
23+
/// ```
24+
///
25+
public struct OverlayCollectionNamespace<Elements: Collection> {
26+
27+
@usableFromInline
28+
internal var elements: Elements
29+
30+
@inlinable
31+
internal init(elements: Elements) {
32+
self.elements = elements
33+
}
34+
}
35+
36+
extension Collection {
37+
38+
/// A namespace for methods which overlay another collection of elements
39+
/// over a region of this collection.
40+
///
41+
@inlinable
42+
public var overlay: OverlayCollectionNamespace<Self> {
43+
OverlayCollectionNamespace(elements: self)
44+
}
45+
}
46+
47+
extension OverlayCollectionNamespace {
48+
49+
@inlinable
50+
public func replacingSubrange<Overlay>(
51+
_ subrange: Range<Elements.Index>, with newElements: Overlay
52+
) -> OverlayCollection<Elements, Overlay> {
53+
OverlayCollection(base: elements, overlay: newElements, replacedRange: subrange)
54+
}
55+
56+
@inlinable
57+
public func appending<Overlay>(
58+
contentsOf newElements: Overlay
59+
) -> OverlayCollection<Elements, Overlay> {
60+
replacingSubrange(elements.endIndex..<elements.endIndex, with: newElements)
61+
}
62+
63+
@inlinable
64+
public func inserting<Overlay>(
65+
contentsOf newElements: Overlay, at position: Elements.Index
66+
) -> OverlayCollection<Elements, Overlay> {
67+
replacingSubrange(position..<position, with: newElements)
68+
}
69+
70+
@inlinable
71+
public func removingSubrange(
72+
_ subrange: Range<Elements.Index>
73+
) -> OverlayCollection<Elements, EmptyCollection<Elements.Element>> {
74+
replacingSubrange(subrange, with: EmptyCollection())
75+
}
76+
77+
@inlinable
78+
public func appending(
79+
_ element: Elements.Element
80+
) -> OverlayCollection<Elements, CollectionOfOne<Elements.Element>> {
81+
appending(contentsOf: CollectionOfOne(element))
82+
}
83+
84+
@inlinable
85+
public func inserting(
86+
_ element: Elements.Element, at position: Elements.Index
87+
) -> OverlayCollection<Elements, CollectionOfOne<Elements.Element>> {
88+
inserting(contentsOf: CollectionOfOne(element), at: position)
89+
}
1390

1491
@inlinable
15-
public func replacingSubrange<Replacements>(
16-
_ subrange: Range<Index>, with newElements: Replacements
17-
) -> ReplacingSubrangeCollection<Base, Replacements> {
18-
ReplacingSubrangeCollection(base: elements, replacements: newElements, replacedRange: subrange)
92+
public func removing(
93+
at position: Elements.Index
94+
) -> OverlayCollection<Elements, EmptyCollection<Elements.Element>> {
95+
removingSubrange(position..<position)
1996
}
2097
}
2198

22-
public struct ReplacingSubrangeCollection<Base, Replacements>
23-
where Base: Collection, Replacements: Collection, Base.Element == Replacements.Element {
99+
public struct OverlayCollection<Base, Overlay>
100+
where Base: Collection, Overlay: Collection, Base.Element == Overlay.Element {
24101

25102
@usableFromInline
26103
internal var base: Base
27104

28105
@usableFromInline
29-
internal var replacements: Replacements
106+
internal var overlay: Overlay
30107

31108
@usableFromInline
32109
internal var replacedRange: Range<Base.Index>
33110

34111
@inlinable
35-
internal init(base: Base, replacements: Replacements, replacedRange: Range<Base.Index>) {
112+
internal init(base: Base, overlay: Overlay, replacedRange: Range<Base.Index>) {
36113
self.base = base
37-
self.replacements = replacements
114+
self.overlay = overlay
38115
self.replacedRange = replacedRange
39116
}
40117
}
41118

42-
extension ReplacingSubrangeCollection: Collection {
119+
extension OverlayCollection: Collection {
43120

44121
public typealias Element = Base.Element
45122

@@ -48,10 +125,10 @@ extension ReplacingSubrangeCollection: Collection {
48125
@usableFromInline
49126
internal enum Wrapped {
50127
case base(Base.Index)
51-
case replacement(Replacements.Index)
128+
case overlay(Overlay.Index)
52129
}
53130

54-
/// The underlying base/replacements index.
131+
/// The underlying base/overlay index.
55132
///
56133
@usableFromInline
57134
internal var wrapped: Wrapped
@@ -72,11 +149,11 @@ extension ReplacingSubrangeCollection: Collection {
72149
switch (lhs.wrapped, rhs.wrapped) {
73150
case (.base(let unwrappedLeft), .base(let unwrappedRight)):
74151
return unwrappedLeft < unwrappedRight
75-
case (.replacement(let unwrappedLeft), .replacement(let unwrappedRight)):
152+
case (.overlay(let unwrappedLeft), .overlay(let unwrappedRight)):
76153
return unwrappedLeft < unwrappedRight
77-
case (.base(let unwrappedLeft), .replacement(_)):
154+
case (.base(let unwrappedLeft), .overlay(_)):
78155
return unwrappedLeft < lhs.replacedRange.lowerBound
79-
case (.replacement(_), .base(let unwrappedRight)):
156+
case (.overlay(_), .base(let unwrappedRight)):
80157
return !(unwrappedRight < lhs.replacedRange.lowerBound)
81158
}
82159
}
@@ -87,7 +164,7 @@ extension ReplacingSubrangeCollection: Collection {
87164
switch (lhs.wrapped, rhs.wrapped) {
88165
case (.base(let unwrappedLeft), .base(let unwrappedRight)):
89166
return unwrappedLeft == unwrappedRight
90-
case (.replacement(let unwrappedLeft), .replacement(let unwrappedRight)):
167+
case (.overlay(let unwrappedLeft), .overlay(let unwrappedRight)):
91168
return unwrappedLeft == unwrappedRight
92169
default:
93170
return false
@@ -96,41 +173,41 @@ extension ReplacingSubrangeCollection: Collection {
96173
}
97174
}
98175

99-
extension ReplacingSubrangeCollection {
176+
extension OverlayCollection {
100177

101178
@inlinable
102179
internal func makeIndex(_ position: Base.Index) -> Index {
103180
Index(wrapped: .base(position), replacedRange: replacedRange)
104181
}
105182

106183
@inlinable
107-
internal func makeIndex(_ position: Replacements.Index) -> Index {
108-
Index(wrapped: .replacement(position), replacedRange: replacedRange)
184+
internal func makeIndex(_ position: Overlay.Index) -> Index {
185+
Index(wrapped: .overlay(position), replacedRange: replacedRange)
109186
}
110187

111188
@inlinable
112189
public var startIndex: Index {
113190
if base.startIndex == replacedRange.lowerBound {
114-
if replacements.isEmpty {
191+
if overlay.isEmpty {
115192
return makeIndex(replacedRange.upperBound)
116193
}
117-
return makeIndex(replacements.startIndex)
194+
return makeIndex(overlay.startIndex)
118195
}
119196
return makeIndex(base.startIndex)
120197
}
121198

122199
@inlinable
123200
public var endIndex: Index {
124-
if replacedRange.lowerBound != base.endIndex || replacements.isEmpty {
201+
if replacedRange.lowerBound != base.endIndex || overlay.isEmpty {
125202
return makeIndex(base.endIndex)
126203
}
127-
return makeIndex(replacements.endIndex)
204+
return makeIndex(overlay.endIndex)
128205
}
129206

130207
@inlinable
131208
public var count: Int {
132209
base.distance(from: base.startIndex, to: replacedRange.lowerBound)
133-
+ replacements.count
210+
+ overlay.count
134211
+ base.distance(from: replacedRange.upperBound, to: base.endIndex)
135212
}
136213

@@ -140,19 +217,19 @@ extension ReplacingSubrangeCollection {
140217
case .base(var baseIndex):
141218
base.formIndex(after: &baseIndex)
142219
if baseIndex == replacedRange.lowerBound {
143-
if replacements.isEmpty {
220+
if overlay.isEmpty {
144221
return makeIndex(replacedRange.upperBound)
145222
}
146-
return makeIndex(replacements.startIndex)
223+
return makeIndex(overlay.startIndex)
147224
}
148225
return makeIndex(baseIndex)
149226

150-
case .replacement(var replacementIndex):
151-
replacements.formIndex(after: &replacementIndex)
152-
if replacedRange.lowerBound != base.endIndex, replacementIndex == replacements.endIndex {
227+
case .overlay(var overlayIndex):
228+
overlay.formIndex(after: &overlayIndex)
229+
if replacedRange.lowerBound != base.endIndex, overlayIndex == overlay.endIndex {
153230
return makeIndex(replacedRange.upperBound)
154231
}
155-
return makeIndex(replacementIndex)
232+
return makeIndex(overlayIndex)
156233
}
157234
}
158235

@@ -161,34 +238,34 @@ extension ReplacingSubrangeCollection {
161238
switch position.wrapped {
162239
case .base(let baseIndex):
163240
return base[baseIndex]
164-
case .replacement(let replacementIndex):
165-
return replacements[replacementIndex]
241+
case .overlay(let overlayIndex):
242+
return overlay[overlayIndex]
166243
}
167244
}
168245
}
169246

170-
extension ReplacingSubrangeCollection: BidirectionalCollection
171-
where Base: BidirectionalCollection, Replacements: BidirectionalCollection {
247+
extension OverlayCollection: BidirectionalCollection
248+
where Base: BidirectionalCollection, Overlay: BidirectionalCollection {
172249

173250
@inlinable
174251
public func index(before i: Index) -> Index {
175252
switch i.wrapped {
176253
case .base(var baseIndex):
177254
if baseIndex == replacedRange.upperBound {
178-
if replacements.isEmpty {
255+
if overlay.isEmpty {
179256
return makeIndex(base.index(before: replacedRange.lowerBound))
180257
}
181-
return makeIndex(replacements.index(before: replacements.endIndex))
258+
return makeIndex(overlay.index(before: overlay.endIndex))
182259
}
183260
base.formIndex(before: &baseIndex)
184261
return makeIndex(baseIndex)
185262

186-
case .replacement(var replacementIndex):
187-
if replacementIndex == replacements.startIndex {
263+
case .overlay(var overlayIndex):
264+
if overlayIndex == overlay.startIndex {
188265
return makeIndex(base.index(before: replacedRange.lowerBound))
189266
}
190-
replacements.formIndex(before: &replacementIndex)
191-
return makeIndex(replacementIndex)
267+
overlay.formIndex(before: &overlayIndex)
268+
return makeIndex(overlayIndex)
192269
}
193270
}
194271
}

0 commit comments

Comments
 (0)