Skip to content

Commit c6dfea6

Browse files
committed
[stdlib] Re-add withContiguousStorageIfAvailable to SubString.UTF8View
This is a second pass at the original patch, which broke an OS test. Due to an oversight it seems that we never added a withContigousStorageIfAvailable implementation to SubString.UTF8View, which meant that if you sliced a String you lost the ability to get fast access to the backing storage. There's no good reason for this functionality to be missing, so this patch adds it in by delegating to the Slice implementation. Resolves SR-11999.
1 parent 22bfebe commit c6dfea6

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

stdlib/public/core/Substring.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,13 @@ extension Substring.UTF8View: BidirectionalCollection {
389389
return _slice.distance(from: start, to: end)
390390
}
391391

392+
@_alwaysEmitIntoClient
393+
public func withContiguousStorageIfAvailable<R>(
394+
_ body: (UnsafeBufferPointer<Element>) throws -> R
395+
) rethrows -> R? {
396+
return try _slice.withContiguousStorageIfAvailable(body)
397+
}
398+
392399
@inlinable
393400
public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
394401
_slice._failEarlyRangeCheck(index, bounds: bounds)

test/stdlib/subString.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,29 @@ func checkMatch<S: Collection, T: Collection>(_ x: S, _ y: T, _ i: S.Index)
1212
expectEqual(x[i], y[i])
1313
}
1414

15+
func checkMatchContiguousStorage<S: Collection, T: Collection>(_ x: S, _ y: T, expected: Bool)
16+
where S.Element == T.Element, S.Element: Equatable
17+
{
18+
let xElement = x.withContiguousStorageIfAvailable { $0.first }
19+
let yElement = y.withContiguousStorageIfAvailable { $0.first }
20+
21+
if expected {
22+
expectEqual(xElement, yElement)
23+
} else {
24+
expectNotEqual(xElement, yElement)
25+
}
26+
}
27+
28+
func checkHasContiguousStorage<S: Collection>(_ x: S, expected: Bool) {
29+
let hasStorage = x.withContiguousStorageIfAvailable { _ in true } ?? false
30+
expectEqual(hasStorage, expected)
31+
}
32+
33+
func checkHasContiguousStorageSubstring(_ x: Substring.UTF8View) {
34+
let hasStorage = x.withContiguousStorageIfAvailable { _ in true } ?? false
35+
expectTrue(hasStorage)
36+
}
37+
1538
SubstringTests.test("Equality") {
1639
let s = "abcdefg"
1740
let s1 = s[s.index(s.startIndex, offsetBy: 2) ..<
@@ -228,6 +251,24 @@ SubstringTests.test("UTF8View") {
228251
expectEqual("", String(t.dropLast(100))!)
229252
expectEqual("", String(u.dropFirst(100))!)
230253
expectEqual("", String(u.dropLast(100))!)
254+
255+
let expectSubstringWCSIA: Bool
256+
// This availability guard should refer to a concrete OS version in
257+
// future.
258+
if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) {
259+
expectSubstringWCSIA = true
260+
} else {
261+
expectSubstringWCSIA = false
262+
}
263+
264+
checkHasContiguousStorage(s.utf8, expected: true) // Strings always do
265+
checkHasContiguousStorage(t, expected: expectSubstringWCSIA)
266+
checkHasContiguousStorage(u, expected: expectSubstringWCSIA)
267+
checkHasContiguousStorageSubstring(t)
268+
checkHasContiguousStorageSubstring(u)
269+
checkMatchContiguousStorage(Array(s.utf8), s.utf8, expected: true)
270+
checkMatchContiguousStorage(Array(t), t, expected: expectSubstringWCSIA)
271+
checkMatchContiguousStorage(Array(u), u, expected: expectSubstringWCSIA)
231272
}
232273
}
233274

0 commit comments

Comments
 (0)