Skip to content

Commit c854cfc

Browse files
authored
Avoid unnecessarily allocating an array when initializing String from a sequence of bytes. (swiftlang#4813)
1 parent 1b514e4 commit c854cfc

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

Darwin/Foundation-swiftoverlay/NSStringAPI.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,23 @@ extension String {
208208
/// - encoding: The encoding to use to interpret `bytes`.
209209
public init?<S: Sequence>(bytes: __shared S, encoding: Encoding)
210210
where S.Iterator.Element == UInt8 {
211-
let byteArray = Array(bytes)
212-
if encoding == .utf8,
213-
let str = byteArray.withUnsafeBufferPointer({ String._tryFromUTF8($0) })
214-
{
215-
self = str
211+
if encoding == .utf8 {
212+
if let str = bytes.withContiguousStorageIfAvailable({ String._tryFromUTF8($0) }) {
213+
guard let str else {
214+
return nil
215+
}
216+
self = str
217+
} else {
218+
let byteArray = Array(bytes)
219+
guard let str = byteArray.withUnsafeBufferPointer({ String._tryFromUTF8($0) }) else {
220+
return nil
221+
}
222+
self = str
223+
}
216224
return
217225
}
218226

227+
let byteArray = Array(bytes)
219228
if let ns = NSString(
220229
bytes: byteArray, length: byteArray.count, encoding: encoding.rawValue) {
221230
self = String._unconditionallyBridgeFromObjectiveC(ns)

Sources/Foundation/NSStringAPI.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,23 @@ extension String {
256256
/// - encoding: The encoding to use to interpret `bytes`.
257257
public init?<S: Sequence>(bytes: __shared S, encoding: Encoding)
258258
where S.Iterator.Element == UInt8 {
259-
let byteArray = Array(bytes)
260-
if encoding == .utf8,
261-
let str = byteArray.withUnsafeBufferPointer({ String._tryFromUTF8($0) })
262-
{
263-
self = str
259+
if encoding == .utf8 {
260+
if let str = bytes.withContiguousStorageIfAvailable({ String._tryFromUTF8($0) }) {
261+
guard let str else {
262+
return nil
263+
}
264+
self = str
265+
} else {
266+
let byteArray = Array(bytes)
267+
guard let str = byteArray.withUnsafeBufferPointer({ String._tryFromUTF8($0) }) else {
268+
return nil
269+
}
270+
self = str
271+
}
264272
return
265273
}
266274

275+
let byteArray = Array(bytes)
267276
if let ns = NSString(
268277
bytes: byteArray, length: byteArray.count, encoding: encoding.rawValue) {
269278
self = String._unconditionallyBridgeFromObjectiveC(ns)

0 commit comments

Comments
 (0)