Skip to content

Commit a91d4aa

Browse files
authored
Merge pull request swiftlang#27670 from Catfish-Man/fastscii-2
2 parents 13c3894 + 007ff00 commit a91d4aa

File tree

1 file changed

+62
-7
lines changed

1 file changed

+62
-7
lines changed

stdlib/public/core/StringCreate.swift

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,34 @@ internal func _allASCII(_ input: UnsafeBufferPointer<UInt8>) -> Bool {
5050
}
5151

5252
extension String {
53-
@usableFromInline
54-
internal static func _fromASCII(
53+
54+
internal static func _uncheckedFromASCII(
5555
_ input: UnsafeBufferPointer<UInt8>
5656
) -> String {
57-
_internalInvariant(_allASCII(input), "not actually ASCII")
58-
5957
if let smol = _SmallString(input) {
6058
return String(_StringGuts(smol))
6159
}
6260

6361
let storage = __StringStorage.create(initializingFrom: input, isASCII: true)
6462
return storage.asString
6563
}
64+
65+
@usableFromInline
66+
internal static func _fromASCII(
67+
_ input: UnsafeBufferPointer<UInt8>
68+
) -> String {
69+
_internalInvariant(_allASCII(input), "not actually ASCII")
70+
return _uncheckedFromASCII(input)
71+
}
72+
73+
internal static func _fromASCIIValidating(
74+
_ input: UnsafeBufferPointer<UInt8>
75+
) -> String? {
76+
if _fastPath(_allASCII(input)) {
77+
return _uncheckedFromASCII(input)
78+
}
79+
return nil
80+
}
6681

6782
public // SPI(Foundation)
6883
static func _tryFromUTF8(_ input: UnsafeBufferPointer<UInt8>) -> String? {
@@ -166,9 +181,9 @@ extension String {
166181

167182
return contents.withUnsafeBufferPointer { String._uncheckedFromUTF8($0) }
168183
}
169-
170-
@usableFromInline @inline(never) // slow-path
171-
internal static func _fromCodeUnits<
184+
185+
@inline(never) // slow path
186+
private static func _slowFromCodeUnits<
172187
Input: Collection,
173188
Encoding: Unicode.Encoding
174189
>(
@@ -194,6 +209,46 @@ extension String {
194209
let str = contents.withUnsafeBufferPointer { String._uncheckedFromUTF8($0) }
195210
return (str, repaired)
196211
}
212+
213+
@usableFromInline @inline(never) // can't be inlined w/out breaking ABI
214+
@_specialize(
215+
where Input == UnsafeBufferPointer<UInt8>, Encoding == Unicode.ASCII)
216+
@_specialize(
217+
where Input == Array<UInt8>, Encoding == Unicode.ASCII)
218+
internal static func _fromCodeUnits<
219+
Input: Collection,
220+
Encoding: Unicode.Encoding
221+
>(
222+
_ input: Input,
223+
encoding: Encoding.Type,
224+
repair: Bool
225+
) -> (String, repairsMade: Bool)?
226+
where Input.Element == Encoding.CodeUnit {
227+
guard _fastPath(encoding == Unicode.ASCII.self) else {
228+
return _slowFromCodeUnits(input, encoding: encoding, repair: repair)
229+
}
230+
231+
var result:String? = nil
232+
233+
if let contigBytes = input as? _HasContiguousBytes,
234+
contigBytes._providesContiguousBytesNoCopy {
235+
result = contigBytes.withUnsafeBytes { rawBufPtr in
236+
let buffer = UnsafeBufferPointer(
237+
start: rawBufPtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
238+
count: rawBufPtr.count)
239+
return String._fromASCIIValidating(buffer)
240+
}
241+
} else {
242+
result = Array(input).withUnsafeBufferPointer {
243+
let buffer = UnsafeRawBufferPointer($0).bindMemory(to: UInt8.self)
244+
return String._fromASCIIValidating(buffer)
245+
}
246+
}
247+
248+
return result != nil ?
249+
(result!, repairsMade: false) :
250+
_slowFromCodeUnits(input, encoding: encoding, repair: repair)
251+
}
197252

198253
public // @testable
199254
static func _fromInvalidUTF16(

0 commit comments

Comments
 (0)