Skip to content

Commit 9ae58c9

Browse files
committed
[stdlib] span properties for bridged String instances
1 parent af0aa94 commit 9ae58c9

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

β€Žstdlib/public/core/StringUTF8View.swift

+20-8
Original file line numberDiff line numberDiff line change
@@ -324,21 +324,33 @@ extension String.UTF8View {
324324
public var span: Span<UTF8.CodeUnit> {
325325
@lifetime(borrow self)
326326
borrowing get {
327+
#if _runtime(_ObjC)
328+
// handle non-UTF8 Objective-C bridging cases here
329+
if !_guts.isFastUTF8 && _guts._object.hasObjCBridgeableObject {
330+
let storage: __StringStorage
331+
if let associated = _guts.getAssociatedStorage() {
332+
storage = associated
333+
}
334+
else {
335+
storage = _guts.getOrAllocateAssociatedStorage()
336+
}
337+
let (start, count) = unsafe (storage.start, storage.count)
338+
let span = unsafe Span(_unsafeStart: start, count: count)
339+
return unsafe _overrideLifetime(span, borrowing: self)
340+
}
341+
#endif
327342
let count = _guts.count
328343
if _guts.isSmall {
329344
let a = Builtin.addressOfBorrow(self)
330345
let address = unsafe UnsafePointer<UTF8.CodeUnit>(a)
331346
let span = unsafe Span(_unsafeStart: address, count: count)
332347
return unsafe _overrideLifetime(span, borrowing: self)
333348
}
334-
else if _guts.isFastUTF8 {
335-
let buffer = unsafe _guts._object.fastUTF8
336-
_internalInvariant(count == buffer.count)
337-
let span = unsafe Span(_unsafeElements: buffer)
338-
return unsafe _overrideLifetime(span, borrowing: self)
339-
}
340-
// handle other Objective-C bridging cases here
341-
fatalError("Some bridged Strings are not supported at this time")
349+
_precondition(_guts.isFastUTF8)
350+
let buffer = unsafe _guts._object.fastUTF8
351+
_internalInvariant(count == buffer.count)
352+
let span = unsafe Span(_unsafeElements: buffer)
353+
return unsafe _overrideLifetime(span, borrowing: self)
342354
}
343355
}
344356
}

β€Žtest/stdlib/Span/StringUTF8SpanProperty.swift

+24
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,27 @@ suite.test("Span from Large Native String's Substring")
8383
expectEqual(span[i], u[i])
8484
}
8585
}
86+
87+
import Foundation
88+
89+
let strings: [NSString: String] = [
90+
"Hello, World!" as NSString: "Hello, World!",
91+
"A long ASCII string exceeding 16 code units." as NSString: "A long ASCII string exceeding 16 code units.",
92+
"πŸ‡―πŸ‡΅" as NSString: "πŸ‡―πŸ‡΅",
93+
NSString(utf8String: "πŸ‚β˜ƒβ…β†β„οΈŽβ›„οΈβ„οΈ")!: "πŸ‚β˜ƒβ…β†β„οΈŽβ›„οΈβ„οΈ",
94+
]
95+
96+
strings.forEach { string, expected in
97+
suite.test("Span from Bridged String: \(expected)")
98+
.require(.stdlib_6_2).code {
99+
guard #available(SwiftStdlib 6.2, *) else { return }
100+
101+
let bridged = String(string)
102+
let utf8 = bridged.utf8
103+
let span = utf8.span
104+
expectEqual(span.count, expected.utf8.count)
105+
for (i,j) in zip(span.indices, expected.utf8.indices) {
106+
expectEqual(span[i], expected.utf8[j])
107+
}
108+
}
109+
}

0 commit comments

Comments
Β (0)